การใช้ malloc ใน PIC


10

ฉันจะใช้malloc()และfree()ฟังก์ชั่นใน PIC ได้อย่างไร? ฉันตรวจสอบstdlib.hส่วนหัวแล้วและไม่มีการกล่าวถึงเลย ฉันใช้ MCC18

มีใครต้องใช้พวกเขา?

ฉันต้องการพวกเขาเพราะฉันกำลังย้ายห้องสมุดจาก Windows XP ไปยัง PIC คู่มือการย้ายระบบบอกว่า

ปรับฟังก์ชั่นเฉพาะของระบบปฏิบัติการให้เข้ากับ PIC ของฉัน

แต่ฉันไม่รู้วิธี "แปล" malloc()และfree()ฟังก์ชั่น


4
ลองใช้การจัดสรรแบบคงที่ถ้าเป็นไปได้
Nick T

1
ทำไม? ปัญหาจริงๆคือฉันกำลังเขียนเลเยอร์ด้านล่าง (แพลตฟอร์มเฉพาะ) ของไลบรารีขนาดใหญ่ที่สวยและฟังก์ชั่นมากมายที่ฉันไม่รู้ว่าสิ่งที่พวกเขากำลังใช้นี้ .. และฉันไม่รู้ว่าจะเปลี่ยนจากอะไร แบบไดนามิกเป็นแบบคงที่ ..
stef

11
ดูเหมือนว่าไมโครคอนโทรลเลอร์ PIC ที่มี <4KB RAM อาจไม่ถูกต้องสำหรับแอปพลิเคชันของคุณ บนพีซีวัดการใช้หน่วยความจำของไลบรารีพีซีของคุณก่อนเริ่มพอร์ต คุณอาจจะเก่งกว่ากับบางสิ่งที่น่าสนใจยิ่งขึ้นเช่น ARM Cortex-M3 Rule of thumb: ถ้า codebase ที่คุณพอร์ตนั้นใหญ่เกินกว่าจะเข้าใจได้มันจะไม่เข้ากับ PIC
Toby Jaffey

ไดร์เวอร์ Windows (และแอพพลิเคชั่นโดยทั่วไป) นั้นถูกเขียนด้วยกระบวนทัศน์ 'Unlimited RAM' เนื่องจากหากฟิสิคัลแรมหมดลงหน่วยความจำเสมือนก็สามารถสลับหน่วยความจำเสมือนได้ขึ้นอยู่กับสิ่งที่ห้องสมุดกำลังทำอยู่ มีอยู่ใน PIC18F87J11 ของคุณ ฉันสงสัยว่าคุณจะไม่สามารถวัดจำนวนหน่วยความจำที่ไดรเวอร์จะใช้งานได้
Adam Lawrence

ปัญหาที่เป็นไปได้อีกอย่างหนึ่ง: Win32 int คือ 32 บิตในขณะที่คอมไพเลอร์ MCC18 จะมีเพียง 16 บิต คุณอาจพบกับปัญหาน้ำล้นแปลก ๆ หากคุณไม่ระวัง
Adam Lawrence

คำตอบ:


8

ในหลาย ๆ แอปพลิเคชั่นหนึ่งจะต้องจัดสรรหน่วยความจำ แต่ไม่จำเป็นต้องว่างอะไรในขณะที่รักษาบางสิ่งที่ถูกจัดสรรไว้หลังจากนั้น ในระบบดังกล่าวสิ่งที่ผู้ใช้ต้องทำคือใช้ตัวเชื่อมโยงเพื่อกำหนดอาร์เรย์โดยใช้ RAM ที่มีอยู่ทั้งหมดตั้งค่าตัวชี้ไปที่จุดเริ่มต้นของอาร์เรย์นั้นจากนั้นใช้ฟังก์ชัน malloc ง่าย ๆ ที่ดี:

ถ่าน * next_alloc;
เป็นโมฆะ * malloc (ขนาด int)
{
    ถ่าน * this_alloc;
    this_alloc = next_alloc;
    ถ้า ((END_OF_ALLOC_SPACE - this_alloc) <ขนาด)
      กลับ -1;
    next_alloc + = ขนาด;
    กลับ this_alloc;
}
เป็นโมฆะฟรี (เป็นโมฆะ * ptr)
{
    ถ้า (ptr)
        next_alloc = (ถ่าน *) ptr;
}

ดีและง่ายและมีค่าใช้จ่ายรวมเพียงสองไบต์สำหรับการจัดสรรจำนวนเท่าใดก็ได้ การโทรฟรี () บนบล็อกจะเป็นการยกเลิกการจัดสรรบล็อกนั้นและทุกสิ่งที่อยู่หลังจากนั้น

รูปแบบการจัดสรรที่ซับซ้อนมากขึ้นเล็กน้อยสามารถจัดการได้โดยใช้สองพอยน์เตอร์ - หนึ่งซึ่งจัดสรรสิ่งต่าง ๆ จากด้านล่างของหน่วยความจำที่เลื่อนขึ้นและหนึ่งในนั้นจะไปจากด้านบนของหน่วยความจำลง นอกจากนี้ยังเป็นไปได้ที่จะใช้ตัวรวบรวมขยะขนาดเล็กถ้าข้อมูลในกองนั้นเป็นเนื้อเดียวกันและมีใครรู้ว่าข้อมูลอ้างอิงภายนอกทั้งหมดอยู่ที่ใด


หากต้องการทราบข้อมูลอย่างละเอียดเกี่ยวกับความเป็นไปได้อ่านคำตอบได้ที่electronics.stackexchange.com/questions/7850/…
gavioto20

14

malloc()ในไมโครคอนโทรลเลอร์โดยทั่วไปถือว่าเป็น "สิ่งเลวร้าย" แต่ถ้าคุณต้องการมันอย่างแน่นอนคุณจะต้องหาบุคคลที่สาม

หากคุณโชคดีรหัสที่คุณย้ายระบบอาจไม่พึ่งพาการนำหน่วยความจำกลับมาใช้ซ้ำ หากเป็นกรณีนี้คุณสามารถเขียนตัวจัดสรรอย่างง่ายซึ่งส่งกลับตัวชี้ไปยังบัฟเฟอร์ RAM แล้วเลื่อนตัวชี้ไปตามขนาดบล็อกที่ร้องขอ

ฉันเคยใช้วิธีการนี้มาก่อนในการย้ายพอร์ตไลบรารีพีซีไปยังไมโครคอนโทรลเลอร์

ด้านล่างนี้คุณควรที่จะติดตั้งที่มีการจัดสรรและการจัดสรรหน่วยความจำmy_malloc_init() มีไว้เพื่อตอบสนองการพึ่งพา แต่จะไม่ทำอะไรเลย ในที่สุดคุณก็จะหมดพื้นที่แน่นอนmy_malloc()my_free()

ในการทำให้งานนี้คุณจะต้องวัดความต้องการหน่วยความจำกรณีเลวร้ายที่สุดของรหัสของคุณ (ทำได้บนพีซีถ้าเป็นไปได้) จากนั้นตั้งค่าให้HEAP_SIZEเหมาะสม my_malloc_init()ก่อนที่จะเข้าเป็นส่วนหนึ่งของห้องสมุดของคุณที่ต้องการหน่วยความจำแบบไดนามิกโทร heapก่อนที่จะกลับมาใช้ให้แน่ใจว่าจุดอะไรที่ยังคงอยู่ที่

uint8_t heap[HEAP_SIZE];
uint8_t *heap_ptr;

void my_malloc_init(void)
{
    heap_ptr = heap;
}

void *my_malloc(size_t len)
{
    uint8_t *p = heap_ptr;
    heap_ptr += len;
    if (heap_ptr >= heap + HEAP_SIZE)
        return NULL;
    else
        return p;
}

void my_free(void)
{
    // do nothing
}

(หมายเหตุ: ในโลกแห่งความเป็นจริงคุณอาจต้องพิจารณาการจัดตำแหน่งตัวชี้เช่นการปัดเศษขึ้นheap_ptr2 หรือ 4 ไบต์)

อีกทางเลือกหนึ่งคือการใช้โครงสร้างการจัดสรรที่ง่ายกว่าmalloc()ปกติที่มีให้เช่น FreeListถึงแม้ว่าสิ่งนี้อาจไม่อนุญาตให้คุณจัดสรรบล็อกขนาดตัวแปร


3
ฉันสงสัยว่า malloc IS นั้นถือว่าเป็นสิ่งที่ดีในการฝังตัว
Kellenjb

1
ฉันยังเห็นด้วยว่าคุณไม่ต้องการการจัดสรรแบบไดนามิกในโปรแกรมตามที่คนอื่นพูด แต่นี่เป็นวิธีที่ยอดเยี่ยมในการทำเรื่องนี้ malloc ของบุคคลที่สามที่ออกแบบมาสำหรับการฝังตัวเป็นตัวเลือกที่ดีที่สุด การหลีกเลี่ยงการแบ่งส่วนเป็นสิ่งที่จำเป็น @jobyTaffey เขียนได้ดี
Kortuk

1
@Kellenjb ดีนั่นเป็นคำถามใหม่ทั้งหมด :-)
Toby Jaffey

1
ฉันขอแนะนำให้ my_free ควรตั้ง heap_ptr เป็นค่าที่ส่งผ่านซึ่งจะช่วยให้รายการที่ระบุและทุกอย่างถูกจัดสรรอย่างมีประสิทธิภาพ แน่นอนหนึ่งต้องจัดสรรสิ่งต่าง ๆ ในลำดับที่อนุญาตการใช้งานดังกล่าว แต่รูปแบบดังกล่าวไม่ใช่เรื่องแปลก อีกรูปแบบที่มีประโยชน์คือการมีฟังก์ชั่นจัดสรร / อิสระสองคู่โดยหนึ่งในนั้นจะจัดสรรจากบนลงล่างและอีกหนึ่งฟังก์ชันจะจัดสรรจากล่างขึ้นบน
supercat

13

นี่คือคำตอบสำหรับคำถามของคุณแทบจะไม่ แต่การจัดสรรหน่วยความจำแบบไดนามิกมักจะเกิดขึ้นกับสภาพแวดล้อม RAM ขนาดเล็กและในกรณีที่ไม่มีระบบปฏิบัติการ (เช่นในโลกของไมโครคอนโทรลเลอร์) ... พื้นที่ฮีปที่คุณมีในสภาพแวดล้อมแบบฝังตัว วัดเป็นร้อยไบต์ ...

การใช้ malloc และ free เป็นการดูแลรักษารายการเชื่อมโยงของโครงสร้าง "เซ็กเมนต์ฟรี" และอย่างที่คุณจินตนาการได้ว่าข้อมูลเมตาที่เชื่อมโยงกับเซ็กเมนต์อิสระนั้นไม่มั่นคงเมื่อเทียบกับจำนวนหน่วยความจำที่มีอยู่โดยทั่วไป ... นั่นคือ "ค่าใช้จ่าย" "การจัดการพูลหน่วยความจำแบบไดนามิกจะใช้ทรัพยากรจำนวนมากที่มีอยู่เป็นจำนวนมาก


มีการนำไปใช้งานที่ค่าใช้จ่ายเมทาดาทามีขนาดเล็กมาก สำหรับบล็อกที่จัดสรรคุณต้องมีขนาดเท่านั้น สำหรับบล็อกที่ไม่ได้ใช้ตัวชี้รายการที่เชื่อมโยงมักจะสามารถใช้งานได้ฟรีแม้จะมีขนาดบล็อกที่น้อยที่สุดก็ตาม
Reinstate Monica

ปัญหาเกี่ยวกับระบบขนาดเล็กที่ใช้เวลานานซึ่งใช้ไมโครคอนโทรลเลอร์มักไม่เกี่ยวกับข้อมูลเมตา แต่เกี่ยวกับการกระจายตัวของหน่วยความจำ สิ่งที่แย่กว่านั้นคือการเปลี่ยนแปลงเล็กน้อยในรหัสของคุณสามารถแนะนำการแตกแฟรกเมนต์ของหน่วยความจำซึ่งไม่เคยมีมาก่อนดังนั้นคุณอาจทำการเปลี่ยนแปลงที่ดูไร้เดียงสาซึ่งทำให้โปรแกรมของคุณหยุดทำงานทันที "เร็วเกินไป"
Reinstate Monica

11

ฉันไม่ทราบว่าไลบรารี่มาตรฐาน C18 รองรับmallocหรือfreeไม่ แต่Microchip App Note AN914จะแสดงวิธีการใช้งานของคุณเอง

ไม่ว่าในกรณีใดโทมัสและผู้โพสต์คนอื่น ๆ แนะนำให้ใช้หน่วยความจำแบบไดนามิกบน PIC ที่มีพื้นที่ RAM ขนาดเล็กมากซึ่งเต็มไปด้วยอันตราย คุณสามารถหมดพื้นที่ที่ต่อเนื่องได้อย่างรวดเร็วเนื่องจากไม่มีผู้จัดการหน่วยความจำเสมือนขั้นสูงที่ระบบปฏิบัติการเต็มรูปแบบให้คุณนำไปสู่การจัดสรรและล้มเหลวที่ล้มเหลว ที่แย่กว่านั้นคืออาจไม่สามารถกำหนดได้และอาจเป็นปัญหาในการแก้ไขข้อบกพร่อง

หากสิ่งที่คุณทำมีการกำหนดแบบไดนามิกอย่างแท้จริงในเวลาทำงาน (หายากสำหรับสิ่งที่ฝังตัวส่วนใหญ่) และคุณจะต้องจัดสรรพื้นที่ในโอกาสพิเศษสองสามครั้งฉันสามารถเห็นmallocและfreeยอมรับได้


หมดพื้นที่ต่อเนื่องหรือที่เรียกว่า heap fragmentation เป็นปัญหาที่ไม่ขึ้นอยู่กับว่าพื้นที่ที่อยู่ของคุณมีขนาดใหญ่เพียงใดและคุณมีหน่วยความจำเสมือนหรือไม่ คุณอาจต้องการแลกเปลี่ยน RAM ที่สูญเปล่าไปแล้วบางส่วนเพื่อลดการแยกส่วนของฮีปที่ต่ำกว่า แต่ในที่สุดในระบบที่ใช้เวลานานคุณไม่สามารถรับประกันได้ว่าจะไม่ใช้พื้นที่ฮีพ ความแตกต่างเพียงอย่างเดียวระหว่างระบบขนาดเล็กและขนาดใหญ่ที่นี่คือหนึ่งในระยะเวลาที่ดิสก์ใช้ในการเริ่มการฟาด (บนระบบที่มี VM-paged VM) หรือตัวจัดสรรเพื่อส่งคืนค่า NULL (บนอุปกรณ์แบบฝัง)
Reinstate Monica

@KubaOber: โดยทั่วไปเป็นไปได้ที่จะรับประกันว่า RAM ขนาดที่แน่นอนจะสามารถจัดการการจัดสรรและการดำเนินการลำดับที่ไม่ต้องการจำนวน RAM (เล็กกว่า) จำนวนหนึ่งที่จะจัดสรรพร้อมกันได้ ปัญหาของระบบฝังตัวคือการรับประกันความสำเร็จแม้ในกรณีที่เลวร้ายที่สุดจะต้องใช้ RAM มากกว่าที่จำเป็นโดยไม่มีการแตกแฟรกเมนต์
supercat

@supercat คุณพูดถูก ฉันรู้สึกทึ่งมาก มีการพิสูจน์อย่างเป็นทางการของการค้ำประกันเหล่านั้น
Reinstate Monica

2

PIC ของคุณมีขนาดเท่าไหร่ในแง่ของหน่วยความจำ?

malloc เป็นมากวิธีที่ไม่มีประสิทธิภาพของหน่วยความจำที่จัดสรร ปัญหาก็คือหน่วยความจำสามารถแยกส่วนกับ frees และ mallocs บ่อยและมีหน่วยความจำเพียงไม่กี่กิโลไบต์ความล้มเหลวในการจัดสรรเป็นเรื่องธรรมดาเกินไป อาจเป็นไปได้ว่าถ้าคุณใช้ชิปขนาดเล็กกว่าหรือ PIC18 รุ่นก่อนหน้านี้ไม่มีการรองรับ malloc เนื่องจาก Microchip มองว่ามันยากที่จะติดตั้ง (หรืออาจเป็นไปไม่ได้ในบางกรณี) หรือไม่เพียงพอสำหรับการใช้งาน คุ้มค่า ไม่ต้องพูดถึง แต่ก็ค่อนข้างช้าคุณมองไปที่ 1 รอบเพื่อใช้บัฟเฟอร์แบบคงที่ที่มีอยู่แล้วและ 100 ถึง 1,000 รอบของการทำ malloc

หากคุณต้องการจัดสรรแบบคงที่ให้สร้างสิ่งต่าง ๆ เช่นบัฟเฟอร์สำหรับฟังก์ชั่น sprintf ของคุณ (ถ้ามีประมาณ 128 ไบต์) บัฟเฟอร์สำหรับการ์ด SD ของคุณ (ถ้ามี) และอื่น ๆ จนกว่าคุณจะลบ malloc ออก เป็นการดีที่คุณจะใช้เฉพาะในกรณีที่คุณต้องการอย่างมากและไม่สามารถหลีกเลี่ยงการจัดสรรแบบคงที่ได้ แต่สถานการณ์เหล่านี้มักเป็นของหายากและอาจเป็นสัญญาณว่าคุณควรมองไมโครคอนโทรลเลอร์ที่มีขนาดใหญ่ขึ้น / มีประสิทธิภาพมากขึ้น

และหากคุณกำลังพัฒนา / ย้ายพอร์ต "ระบบปฏิบัติการ" บน PIC18 และหากรองรับไมโครคอนโทรลเลอร์ก็อาจมีการรองรับการจัดสรรแบบคงที่ ตัวอย่างเช่น SQLite3 รองรับการจัดสรรแบบคงที่ - คุณจัดสรรอาร์เรย์บัฟเฟอร์ที่มีขนาดใหญ่และใช้สิ่งที่เป็นไปได้แม้ว่าจะไม่เหมาะสำหรับไมโครคอนโทรลเลอร์ ถ้าไม่เช่นนั้นคุณแน่ใจหรือไม่ว่ามันถูกออกแบบมาสำหรับ PIC18 ขนาดเล็ก?


ฉันเห็นสิ่งที่คุณหมายถึง .. ฉันกำลังใช้ PIC18F87J11 ซึ่งมี RAM 128K มันเพียงพอหรือไม่
stef

สเตฟาโนชิปตัวนั้นมี RAM 3,904 ไบต์ มีหน่วยความจำแฟลชโปรแกรม 128K
W5VO

@Stefao Salati - 3.8KB มีขนาดเล็ก
โทมัส O

ใช่ .. คุณคิดว่ามันเพียงพอหรือไม่
stef

@Stefano Salati ไม่จำเป็นต้องขอโทษ ฉันคิดว่าคุณต้องการผลักดันมันจริงๆ อาจใช้งานได้ แต่จะทำให้ประสิทธิภาพและหน่วยความจำว่างของคุณลดลง
โทมัสโอ

2

หากคุณกำลังพิจารณาmalloc()และfree()ซอฟต์แวร์ฝังตัวของคุณผมขอแนะนำให้คุณลองดูที่ UC / OS-II และและOSMemGet() OSMemPut()ในขณะที่malloc()ให้คุณจัดสรรบล็อกหน่วยความจำโดยพลการOSMem*()ให้บล็อกขนาดคงที่จากพูลที่จัดสรรไว้ล่วงหน้า ฉันพบว่าวิธีนี้มีความสมดุลที่ดีระหว่างความยืดหยุ่นmalloc()และความทนทานของการจัดสรรแบบคงที่


0

AFAIK เพื่อทำสิ่งนี้อย่างถูกต้องคุณต้องมองอุปกรณ์ที่มีหน่วยความจำการจัดการ (MMU) ในขณะที่มีกลไกการจัดสรรแบบไดนามิกสำหรับซีรีย์ PIC18 นั้นมีอยู่จริงพวกเขาจะไม่เป็นแบบนั้น - และพูดในฐานะคนที่ทำงานกับเฟิร์มแวร์ที่ผลักดันขีด จำกัด ของซีรีย์ PIC18 ฉันสามารถพูดได้ว่า แอปพลิเคชั่นขนาดใหญ่ภายในนั้นหากคุณใช้โอเวอร์เฮดทั้งหมดในตัวจัดการหน่วยความจำ

วิธีแก้ปัญหาที่ดีกว่า: พยายามเข้าใจสิ่งที่กำลังทำอยู่และทำไมจึงต้องมีการจัดสรรแบบไดนามิก ดูว่าคุณไม่สามารถจัดปัจจัยใหม่ให้ทำงานกับการจัดสรรแบบคงที่ได้หรือไม่ (อาจเป็นกรณีที่เป็นไปไม่ได้ - ถ้าไลบรารี่ / แอปพลิเคชันออกแบบมาเพื่อทำสิ่งที่ปรับขนาดได้อย่างอิสระหรือไม่มีขอบเขตของจำนวนอินพุตที่สามารถรับได้) แต่บางครั้งถ้าคุณคิดจริงๆ เกี่ยวกับสิ่งที่คุณพยายามทำคุณอาจพบว่าเป็นไปได้ (และอาจเป็นเรื่องง่ายมาก) ในการใช้การจัดสรรแบบคงที่แทน


1
คุณไม่ถูกต้อง MMU ช่วยให้คุณสามารถเชื่อมต่อกับหน่วยความจำภายนอก (น่าจะมากกว่า 4kB บน PIC) มีความแตกต่างน้อยมากในการจัดสรรแบบไดนามิกและแบบคงที่ที่มีและไม่มี MMU เมื่อคุณเริ่มเข้าสู่หน่วยความจำเสมือนมีความแตกต่าง แต่นั่นก็มีความเกี่ยวข้องกับ malloc แบบสัมผัส
Kevin Vermeer

1
โปรแกรมเมอร์ของแมคอินทอชรุ่นก่อนใช้ malloc () และ free () (หรือ Pascal เทียบเท่า) ค่อนข้างบ่อยอย่างไรก็ตามข้อเท็จจริงที่ว่าคอมพิวเตอร์ Macintosh รุ่นแรกไม่มี MMU แนวคิดที่ว่า "ถูกต้อง" โดยใช้ malloc () ต้องใช้ MMU ซึ่งดูเหมือนว่าไม่ถูกต้องสำหรับฉัน
davidcary
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.