9

这是我正在浏览的源代码:glibc source。我的特殊问题来自这组特殊的函数:socket library

例如(大部分功能都是这样设置的)socket/bind.c的来源是:

  19 #include <errno.h>
  20 #include <sys/socket.h>
  21 
  22 /* Give the socket FD the local address ADDR (which is LEN bytes long).  */
  23 int
  24 __bind (fd, addr, len)
  25      int fd;
  26      __CONST_SOCKADDR_ARG addr;
  27      socklen_t len;
  28 {
  29   __set_errno (ENOSYS);
  30   return -1;
  31 }
  32 
  33 weak_alias (__bind, bind)
  34 
  35 stub_warning (bind)
  36 #include <stub-tag.h>

我承认我没有花很多时间,但是实际功能的代码到底在哪里,发生了什么?这是一个很好用的范例吗?

4

2 回答 2

9

__bind函数是一个存根:它是一个在外部看起来像真实事物(相同原型)但不执行必要功能的函数。

weak_alias宏告诉链接器bind将成为__bind. 也就是说,这个定义bind是一个弱符号。如果没有其他定义称为 的符号bind,则此定义成立;如果存在另一个(非弱)定义,bind则该非弱定义存在并且弱定义被忽略。弱别名是一个弱符号,它是另一个符号的别名(而不是拥有自己的定义)。如果使用该弱别名,该stub_warning宏会导致链接器发出警告。

的真正实现bind取决于编译 Glibc 的操作系统。在Hurd上,它被定义在sysdeps/mach/hurd/bind.c. 在 Linux 上,bind是一个系统调用:在 Glibc 源代码中没有 C 代码,只有汇编代码。bind提供,其中重用了in或sysdeps/unix/sysv/linux/bind.S的体系结构相关定义。这些定义都是底层系统调用的薄包装,注意将参数和返回值复制到适当的寄存器中。socketsysdeps/unix/sysv/linux/**/socket.Sports/sysdeps/unix/sysv/linux/*/socket.S

于 2013-02-14T19:36:40.033 回答
8

您正在查看一般的 bind() 实现,它...只是告诉您 bind() 没有实现(它只是返回一个错误并将 errno 设置为 ENOSYS - 未实现系统调用。)。

glibc 中的许多依赖于平台的系统调用都以这种方式工作 - 有一个默认实现只返回一个错误,并且每个平台/架构师都必须提供系统调用的实现(如果存在)。

查看例如 ./sysdeps/unix/sysv/linux/i386/socket.S 以获得 linux x86 实现。

当然,socket() 只是一个系统调用,所以实际的实现是在内核中。Glibc 只是提供了一个 C 包装器来调用它。

于 2013-02-14T19:19:22.360 回答