在 glibc 2.22 中,在 /socket
目录中,socket 库实现位于。
但是,当打开这些文件中的任何一个时,我所看到的只是一个错误设置函数,它下面有一些宏。
这是一个示例文件 (/socket/send.c
):
#include <errno.h>
#include <sys/socket.h>
/* 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
这样定义?
最佳答案
这里发生了几件事。
首先,如 this answer 中所述, glibc 本身不能定义标准 C 不保留的随机标识符,因为标准 C 允许程序自己定义那些标识符。双下划线开头的名称是为实现保留的,所以这里的实现定义了函数__send()
。弱别名允许使用名称 send()
来引用它,但也允许该引用被其他地方的强定义覆盖。
其次,解释为in the glibc documentation ,为了便于移植,glibc 要求任何特定于机器的函数都具有相应的通用函数。如果可以编写相应的泛型函数,那么它应该是,但如果不能,那么泛型函数应该是一个“ stub 函数”,它本质上只是将 errno
设置为 ENOSYS
(未实现)并返回错误。如果提供了特定于机器的函数,则将使用该函数代替 stub 函数。由于send()
需要系统调用,显然不能用机器无关的方式来写,所以这里有一个 stub 函数。因此,您应该能够找到 __send()
的特定于机器的实现(或其中的多种实现),例如,在 /sysdeps/unix/sysv/linux/x86_64/send .c
在 glibc 源代码树中。
顺便说一句,因为 send()
确实是一个系统调用,所以您在 glibc 中通常会看到的只是一个进行系统调用的简短汇编语言例程。实际执行任务的代码将存在于内核中。
关于c - glibc 的套接字实现在哪里?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34502501/