關于newlib中的libgloss和libnosys
- Newlib的構成
- libgloss的作用
-
- 提供啟動代碼
- 提供底層I/O支援
- 提供底層系統函數
- libnosys是什麼鬼
- 什麼時候需要libnosys
- 引用libnosys
libgloss提供啟動代碼、底層I/O支援、底層系統函數。libnosys提供空的底層系統函數以便程式通過編譯。
https://blog.csdn.net/zoomdy/article/details/82884285
mingdu.zheng at gmail dot com
Newlib的構成
Newlib由三部分構成:libgloss、libc、libm,三者在Newlib源代碼中的存儲位置如下。
- newlib-x.y.z
- libgloss
- newlib
- libc
- libm
libc是标準C庫,libm是标準數學庫,那libgloss是幹啥的?
libgloss的作用
Libgloss is a library for all the details that usually get glossed over. This library refers to things like startup code, and usually I/O support for gcc and C library.
這段話的來源:Embed with GNU - Libgloss。也就是說libgloss是提供啟動代碼和底層I/O支援的。
提供啟動代碼
libgloss目錄下有很多和處理器相關的子目錄,例如有子目錄arm、m68k、i386、mips等。這些子目錄下都有一個crt0.S彙編檔案,這個就是啟動代碼所在的源檔案了,可能還會有其它的彙編檔案,這和具體的處理器有關。
提供底層I/O支援
libgloss目錄下還包含底層I/O支援相關的源代碼,例如write.c源檔案定義了
write
函數,當程式中引用了
printf
等标準輸出函數時,最終
printf
會調用
write
函數進行輸出,如果沒有定義
write
函數,那麼連結就失敗了。
提供底層系統函數
libgloss目錄下還包含底層系統函數相關的源代碼,例如kill.c源檔案定義了
kill
系統函數,getpid.c源檔案定義了
getpid
系統函數。雖然在libgloss中,很多系統函數都被定義成空函數,沒有實際的作用,但對程式完成正常的連結起到重要作用。特别是在引用了第三方庫,而第三方庫又引用系統函數的情況下,libgloss就顯得特别有用了,這種情況下如果沒有libgloss那麼連結是會失敗的。
libnosys是什麼鬼
libgloss目錄下除了和處理器相關的子目錄外,還有個很特别的子目錄,那就是libnosys目錄,這個目錄下的源檔案重新定義了libgloss的所有函數,但是所有函數都是空的,例如對照一下libgloss/write.c和libgloss/libnosys/write.c這兩個檔案。
// libgloss/write.c
int
_DEFUN (write, (fd, buf, nbytes),
int fd _AND
char *buf _AND
int nbytes)
{
int i;
for (i = 0; i < nbytes; i++) {
if (*(buf + i) == '\n') {
outbyte ('\r');
}
outbyte (*(buf + i));
}
return (nbytes);
}
libgloss/write.c定義的
write
函數調用使用者定義的
outbyte
函數輸出内容。
// libgloss/libnosys/write.c
int
_DEFUN (_write, (file, ptr, len),
int file _AND
char *ptr _AND
int len)
{
errno = ENOSYS;
return -1;
}
libgloss/libnosys/write.c定義的
write
函數設定了錯誤代碼,然後什麼也不做,是以純粹是個
stub
函數,完全是為了連結通過而定義的。
什麼時候需要libnosys
如果程式并不實際使用系統函數,但是某些代碼引用了系統函數,那麼可以引入libnosys,以便通過編譯。
引用libnosys
給GCC傳遞編譯選項
-lnosys
即可引用libnosys,這時編譯器将連結到libnosys.a,這個檔案位于ARM GCC安裝目錄的arm-none-eabi\lib子目錄下。