glibc中socket实现分析

时间:2022-09-29 03:17:50

glibc-2.9, linux-2.6.32-rc1
在查看系统调用的时候发现: 关于网络的系统调用只有一个socketcall:

  1. /usr/include/asm/unistd_32.h 
  2. #define __NR_socketcall         102

而这个系统调用的调用实现是在glibc中:
在glibc中socket的实现实在这里:
sysdeps/unix/sysv/linux/i386/socket.S 对这个文件稍后分析,先看其它的函数:
而其它的网络相关函数都在这里定义:

  1. 2 F   d    socket            sysdeps/unix/sysv/linux/accept.S
  2.                #define socket accept
  3.   3 F   d    socket            sysdeps/unix/sysv/linux/bind.S
  4.                #define socket bind
  5. 。。。。其它还有:
  6.                #define socket connect
  7.                #define socket getpeername
  8.                #define socket getsockname
  9.                #define socket getsockopt
  10.                #define socket listen
  11.                #define socket recv
  12.                #define socket recvfrom
  13.                #define socket recvmsg
  14.                #define socket sendmsg
  15.                #define socket sendto
  16.                #define socket setsockopt
  17. 。。。。

而其中每个.S文件中的内容几乎一致,下面只取几个说明一下:

  1. #define socket  bind
  2. #define NARGS   3    //这个是说它的参数的个数
  3. #define NO_WEAK_ALIAS   1 //这个是说这个没有其它的别名
  4. #include <socket.S
  5. ---------------------------------------------------------
  6. #define socket  listen                                                                         
  7. #define NARGS   2
  8. #define NO_WEAK_ALIAS   1
  9. #include <socket.S>
  10. ----------------------------------------------------------
  11. #define socket  accept                                                                         
  12. #define __socket __libc_accept  //这里还定义了其它的别名
  13. #define NARGS   3
  14. #include <socket.S>

也就是所有的网络系统调用都是基于socket这个系统调用的,只是在调用的时候传递的参数不同而已。

那现在再来具体分析sysdeps/unix/sysv/linux/i386/socket.S:
主要内容如下:

  1. /*这个要在上面定义其它函数中使用,如accept,bind等
  2. *看在上面的具体函数中有些定义了__socket,有些没有,有些定义了NO_WEAK_ALIAS。
  3. *这些都是为选择不同的函数做设置的
  4. */
  5. #ifndef __socket    
  6. # ifndef NO_WEAK_ALIAS
  7. define __socket P(__,socket)
  8. # else
  9. define __socket socket
  10. # endif
  11. #endif
  12.  
  13. .globl __socket
  14.  
  15. ENTRY (__socket)                                                                               
  16. #if defined NEED_CANCELLATION && defined CENABLE
  17.         SINGLE_THREAD_P
  18.         jne 1f
  19. #endif
  20.  
  21.         /* Save registers.  */
  22.         movl %ebx, %edx
  23.         cfi_register (3, 2)
  24.  
  25.         movl $SYS_ify(socketcall), %eax /* System call number in %eax.  */
  26.  
  27.         /* Use ## so `socket' is a separate token that might be #define'd.  */
  28.     /* 这个号是来区别调用那个具体函数的,是socket还是bind
  29.     *这里的socket的具体值是会发生变化的,就是在上面的#define socket bind
  30.         *这样类似的语句中变换这个socket的值,关于其具体的值在后面给出
  31.         */
  32.         movl $P(SOCKOP_,socket), %ebx  
  33.         lea 4(%esp), %ecx               /* Address of args is 2nd arg. 这里以堆栈方式传递其它的参数 */
  34.  
  35.         /* 这里进入系统调用,从PII之后的cpu都有两种方式进入系统调用,一种是传统的int 0x80
  36.        另一种就是cpu直接提供的指令enter_syscall,所以这里提供了这样一个语句,
  37.        而其实这也是通过条件编译的方式将其值为int 0x80或其它方式
  38.          */
  39.         ENTER_KERNEL
  40.  
  41.         /* Restore registers. 恢复寄存器 */
  42.         movl %edx, %ebx
  43.         cfi_restore (3)
  44.  
  45.         /* %eax is < 0 if there was an error. 比较返回值 */
  46.         cmpl $-125, %eax
  47.         jae SYSCALL_ERROR_LABEL
  48.  
  49.         /* Successful; return the syscall's value. 正常返回 */
  50. L(pseudo_end):
  51.         ret

$P(SOCKOP_,socket)的值:
sysdeps/unix/sysv/linux/socketcall.h :

 

#define SOCKOP_socket  1
#define SOCKOP_bind  2
#define SOCKOP_connect  3
#define SOCKOP_listen  4
#define SOCKOP_accept  5
#define SOCKOP_getsockname 6
#define SOCKOP_getpeername 7
#define SOCKOP_socketpair 8
#define SOCKOP_send  9
#define SOCKOP_recv  10
#define SOCKOP_sendto  11
#define SOCKOP_recvfrom  12
#define SOCKOP_shutdown  13
#define SOCKOP_setsockopt 14
#define SOCKOP_getsockopt 15
#define SOCKOP_sendmsg  16
#define SOCKOP_recvmsg  17