发布网友 发布时间:2023-05-27 14:57
共1个回答
热心网友 时间:2024-11-09 12:58
注意看这个文件
sysdeps/unix/sysv/linux/syscalls.list
里面记录着系统调用的名字和一些属性,具体我也没有研究过,不懂。
再看select的实现,很让人惊讶,一旦使用,结果就是“报错“。
int
__select (nfds, readfds, writefds, exceptfds, timeout)
int nfds;
fd_set *readfds;
fd_set *writefds;
fd_set *exceptfds;
struct timeval *timeout;
{
__set_errno (ENOSYS);
return -1;
}
libc_hidden_def (__select)
stub_warning (select)
weak_alias (__select, select)
这是因为glibc并没有实现系统调用,而是调用系统调用,
更进一步,连调用系统调用都没有一个个实现,而是使用了通用的办法,
理由很简单,所有的系统调用在linux内核头文件里都能找到,
所有的系统调用参数类型就那么几种,参数个数也是有限的,
因此没有必要针对所有的系统调用一一封装,
于是就有了这个list文件,自动生成调用系统调用的函数,
如果生成失败,也就是你看到的“报错”。
符号是有强弱的,当自动生成成功的时候,“报错”的弱符号就被忽略了。
当你在glibc中找到一个系统调用的封装源码,是以下原因,
编译的目标系统不支持这个系统调用,所以自己用另一种方式实现了。
2. 这个系统调用无法使用通用的自动生成方式生成,用特化的方式覆盖。
3. 针对这个系统调用做了特别的优化。
4. 其它可能的原因。
具体可以留意
SYSCALL, PSEUDO, DO_CALL, INLINE_CALL 等名字
这两个文件是重点所在
sysdeps/unix/i386/sysdep.h
sysdeps/unix/i386/sysdep.S
要搞清楚具体的自动生成过程,恐怕得研究glibc自身的编译过程了