在glibc 2.22中,在/socket
目录中找到套接字库实现.
但是,当打开任何这些文件时,我看到的只是一个错误设置功能,下面有一些宏.
这是一个示例文件(/socket/send.c
):
#include#include /* Send N bytes of BUF to socket FD. Returns the number sent or -1. */ ssize_t __send (fd, buf, n, flags) int fd; const __ptr_t buf; size_t n; int flags; { __set_errno (ENOSYS); return -1; } libc_hidden_def (__send) weak_alias (__send, send) stub_warning (send)
(删除了许可证评论.)
那是哪里send
的weak_alias
宏有作为参数?这些宏在哪里定义?
我认为这是由于与一些糟糕的旧编译器的兼容性,但为什么他们仍然使用K&R语法?
最重要的是,为什么这样 __send
定义?
这里有几件事情.
首先,正如本回答所解释的那样,glibc本身不能定义标准C不保留的随机标识符,因为标准C允许程序自己定义这些标识符.以双下划线开头的名称保留用于实现,因此此处的实现定义了该函数__send()
.弱别名允许使用名称send()
来引用它,但也允许该引用被其他地方的强定义覆盖.
其次,正如glibc文档中所解释的,为了便于移植glibc,需要任何特定于机器的函数具有相应的通用函数.如果可以写入相应的泛型函数,那么它应该是,但如果不是,那么泛型函数应该是"存根函数",它基本上只是设置errno
为ENOSYS
(未实现)并返回错误.如果提供了特定于机器的功能,则将使用该功能代替存根功能.由于send()
需要系统调用,显然它不能以与机器无关的方式编写,因此这里有一个存根函数.因此,您应该能够找到特定于机器的实现(或其中的各种实现)__send()
,例如,在/sysdeps/unix/sysv/linux/x86_64/send.c
glibc源代码树中.
顺便说一句,由于send()
确实是一个系统调用,所以你通常会在glibc中看到的是一个简短的汇编语言例程,它使系统调用.实际做的东西的代码将存在于内核中.