Saya sebagian besar melakukan pengembangan pada perangkat yang telah mem-porting Linux sehingga pustaka C standar menyediakan banyak fungsionalitas melalui penerapan panggilan sistem yang memiliki perilaku standar.
Namun untuk bare metal, tidak ada OS yang mendasarinya. Apakah ada standar terkait dengan bagaimana perpustakaan ac harus diimplementasikan atau apakah Anda harus mempelajari kembali kekhasan implementasi perpustakaan ketika Anda beralih ke papan baru yang menyediakan BSP yang berbeda?
Jawaban:
Ya, ada standar, hanya C library standar . Fungsi pustaka tidak memerlukan OS "full blown", atau OS apa pun, dan ada sejumlah implementasi di luar sana yang disesuaikan dengan kode "bare metal", Newlib mungkin yang paling terkenal.
Mengambil Newlib sebagai contoh, ini mengharuskan Anda untuk menulis sebagian kecil fungsi inti, terutama bagaimana file dan alokasi memori ditangani di sistem Anda. Jika Anda menggunakan platform target umum, kemungkinan seseorang telah melakukan pekerjaan ini untuk Anda.
Jika Anda menggunakan linux (mungkin juga OSX dan mungkin bahkan cygwin / msys?) Dan ketik
man strlen
, itu harus memiliki bagian bernama sesuatuCONFORMING TO
, yang akan memberi tahu Anda bahwa implementasinya sesuai dengan standar tertentu. Dengan cara ini Anda dapat mengetahui apakah sesuatu yang Anda gunakan adalah fungsi standar atau apakah itu tergantung pada OS tertentu.sumber
stdlib
mengimplementasikanstdio
tanpa tergantung pada OS. sepertifopen()
,fclose()
,fread()
,fwrite()
,putc()
dangetc()
? dan bagaimana caramalloc()
kerjanya tanpa berbicara dengan OS?getchar
danputchar
yang tahu tentang UART perangkat keras Anda; kemudian layer Newlibprintf
di atas ini. File I / O juga akan bergantung pada beberapa primitif.stdin
danstdout
danstderr
(yang menanganiputchar()
dangetchar()
) yang mengarahkan I / O dari / ke UART, jika platform Anda memiliki penyimpanan file, seperti dengan flash, maka Anda harus menulis lem untuk itu juga. dan Anda harus memiliki sarana untukmalloc()
danfree()
. Saya pikir jika Anda menangani masalah-masalah itu, Anda dapat menjalankan banyak C portabel di target tertanam Anda (tidakargv
atau tidakargc
).Pertama, standar C mendefinisikan sesuatu yang disebut implementasi "berdiri bebas", sebagai lawan dari implementasi "host" (yang kita kenal dengan baik, rangkaian penuh fungsi C yang didukung oleh OS yang mendasarinya).
Implementasi "berdiri bebas" perlu mendefinisikan hanya sebagian dari header perpustakaan C, yaitu yang tidak memerlukan dukungan, atau bahkan definisi fungsi (mereka hanya melakukan
#define
s dantypedef
s):<float.h>
<iso646.h>
<limits.h>
<stdalign.h>
<stdarg.h>
<stdbool.h>
<stddef.h>
<stdint.h>
<stdnoreturn.h>
Ketika Anda mengambil langkah berikutnya menuju implementasi yang di-host, Anda akan menemukan bahwa hanya ada sedikit fungsi yang benar-benar perlu untuk menghubungkan "sistem" dengan cara apa pun, dengan sisa perpustakaan dapat diimplementasikan di atas "primitif" ". Dalam mengimplementasikan PDCLib , saya berusaha mengisolasinya dalam subdirektori terpisah untuk memudahkan identifikasi ketika port lib ke platform baru (contoh untuk port Linux dalam tanda kurung):
getenv()
(extern char * * environ
)system()
(fork()
/execve()
/wait()
)malloc()
danfree()
(brk()
/sbrk()
)_Exit()
(_exit()
)time()
(belum diimplementasikan)Dan untuk
<stdio.h>
(bisa dibilang yang paling "terlibat-OS" dari header C99):open()
)close()
)unlink()
)link()
/unlink()
)write()
)read()
)lseek()
)Detail tertentu dari perpustakaan bersifat opsional, dengan standar yang hanya menawarkan untuk diimplementasikan dengan cara standar tetapi tidak menjadikan implementasi seperti itu suatu persyaratan.
The
time()
Fungsi mungkin secara hukum hanya kembali(time_t)-1
jika tidak ada mekanika waktu-menjaga tersedia.Penangan sinyal yang dideskripsikan untuk
<signal.h>
tidak perlu dipanggil oleh selain panggilan untukraise()
, tidak ada persyaratan bahwa sistem benar-benar mengirim sesuatu sepertiSIGSEGV
ke aplikasi.Header C11
<threads.h>
, yang (karena alasan yang jelas) sangat tergantung pada OS, tidak perlu disediakan sama sekali jika implementasinya menentukan__STDC_NO_THREADS__
...Ada lebih banyak contoh, tetapi saya tidak memilikinya saat ini.
Sisa perpustakaan dapat diimplementasikan tanpa bantuan dari lingkungan. (*)
(*) Peringatan: Implementasi PDCLib belum lengkap, jadi saya mungkin mengabaikan satu atau dua hal. ;-)
sumber
Standar C sebenarnya didefinisikan terpisah dari lingkungan operasi. Tidak ada asumsi tentang OS host yang hadir, dan bagian-bagian yang bergantung pada host didefinisikan sebagai demikian.
Artinya, Standar C sudah cukup logam telanjang.
Tentu saja, bagian-bagian bahasa yang sangat kita cintai, perpustakaan, sering kali merupakan tempat bahasa inti mendorong hal-hal tertentu menjadi tuan rumah. Oleh karena itu, hal-hal kompiler silang "xxx-lib" tipikal ditemukan untuk banyak alat platform logam kosong.
sumber
Newlib contoh runnable minimal
Di sini saya memberikan contoh yang sangat otomatis dan terdokumentasi yang menunjukkan tindakan newlib dalam QEMU .
Dengan newlib, Anda menerapkan panggilan sistem Anda sendiri untuk platform baremetal Anda.
Sebagai contoh, pada contoh di atas, kami memiliki contoh program
exit.c
:dan dalam file C yang terpisah
common.c
, kami menerapkanexit
dengan semihosting ARM :Syscalls khas lainnya yang akan Anda terapkan adalah:
write
untuk menampilkan hasil ke host. Ini dapat dilakukan dengan:brk
untukmalloc
.Mudah digunakan di baremetal, karena kita tidak perlu peduli tentang paging!
TODO Saya bertanya-tanya apakah realistis untuk mencapai eksekusi syscalls penjadwalan preemptive tanpa pergi ke RTOS penuh sesak seperti Zephyr atau FreeRTOS .
Hal keren tentang Newlib, adalah mengimplementasikan semua hal non-OS spesifik seperti
string.h
untuk Anda, dan memungkinkan Anda menerapkan hanya OS bertopik.Juga, Anda tidak harus menerapkan semua bertopik, tetapi hanya yang Anda butuhkan. Misalnya, jika program Anda hanya perlu
exit
, maka Anda tidak perlu menyediakanprint
.Pohon sumber Newlib memang sudah memiliki beberapa implementasi, termasuk implementasi semihosting ARM di bawah
newlib/libc/sys/arm
, tetapi sebagian besar Anda harus mengimplementasikan sendiri. Namun itu memberikan dasar yang kuat untuk tugas tersebut.Cara termudah untuk men-setup Newlib adalah dengan membangun compiler Anda sendiri dengan crosstool-NG, Anda hanya perlu mengatakan bahwa Anda ingin menggunakan Newlib sebagai pustaka C. Setup saya menangani itu secara otomatis untuk Anda dengan skrip ini , yang menggunakan konfigurasi lib baru hadir di
crosstool_ng_config
.Saya pikir C ++ juga akan berfungsi, tetapi TODO mengujinya.
sumber
Ketika Anda menggunakannya, Anda menemukan beberapa dependensi yang tidak diterapkan dan harus menanganinya. Semua dependensi ini adalah tentang menyetel internal sesuai dengan kepribadian sistem Anda. Misalnya ketika saya mencoba menggunakan sprintf () yang menggunakan malloc () di dalamnya. Malloc memiliki simbol fungsi "t_sbrk" sebagai kode kait, yang harus diimplementasikan oleh pengguna untuk menegakkan perangkat keras yang terlatih. Di sini saya dapat mengimplementasikannya, atau membuat malloc saya sendiri () jika saya percaya saya bisa melakukan yang lebih baik untuk perangkat keras yang tertanam, terutama untuk penggunaan lain, tidak hanya sprintf.
sumber