关于newlib中的libgloss和libnosys

  • ​​Newlib的构成​​
  • ​​libgloss的作用​​
  • ​​提供启动代码​​
  • ​​提供底层I/O支持​​
  • ​​提供底层系统函数​​
  • ​​libnosys是什么鬼​​
  • ​​什么时候需要libnosys​​
  • ​​引用libnosys​​

libgloss提供启动代码、底层I/O支持、底层系统函数。libnosys提供空的底层系统函数以便程序通过编译。

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支持的。

2022年2月23日追加:C库的部分函数需要引用系统调用,裸机系统没有这些系统调用,那么就由C库中的libgloss来提供,gloss这个单词的本意是“假象”。

提供启动代码

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子目录下。