Linux内核网络协议栈2-socket从库函数到内核

来源:互联网 发布:苹果mac下载软件怎么弄 编辑:程序博客网 时间:2024/04/28 16:34
一、socket()库函数到系统调用,再到内核
1、Linux运行的C库是glibc;
2、socket()调用如下:
1) socket()->__socket():glibc-2.3.6/sysdept/generic/socket.c (weak_alias(name1, name2))
2) __socket():glibc-2.3.6/sysdept/unix/sysv/linux/i386/socket.S
3) ENTER_KERNEL:
  1.   
  2. movl $SYS_ify(socketcall), %eax /* System call number in %eax.  */  
  3.   
  4. /* Use ## so `socket' is a separate token that might be #define'd.  */  
  5. movl $P(SOCKOP_,socket), %ebx   /* Subcode is first arg to syscall.  */  
  6. lea 4(%esp), %ecx       /* Address of args is 2nd arg.  */  
  7.   
  8.         /* Do the system call trap.  */  
  9. ENTER_KERNEL  
复制代码
这里,
SYS_ify宏定义为:glibc-2.3.6/sysdept/unix/sysv/linux/i386/Sysdept.h
  1.   
  2. #define SYS_ify(syscall_name)   __NR_##syscall_name;  
复制代码
P宏定义为:glibc-2.3.6/sysdept/unix/sysv/linux/i386/socket.S
  1.     
  2. #define P(a, b) P2(a, b)  
  3. #define P2(a, b) a##b  
复制代码
其中,##为连接符号;
  1.     
  2. #define __NR_socketcall     102  
  3. SOCKOP_socket:glibc-2.3.6/sysdept/unix/sysv/linux/Socketcall.h

  4. #define SOCKOP_socket       1  
复制代码
因此,中断号是102,子中断号是1;
4) int 0x80进入内核:glibc-2.3.6/sysdept/unix/sysv/linux/i386/Sysdept.h:
  1.   
  2. # define ENTER_KERNEL int $0x80  
复制代码
5) system_call中断入口:kernel/arch/x86/kernel/entry_32.S:
  1.     
  2. syscall_call:  
  3.     call *sys_call_table(,%eax,4)  
复制代码
6) 进入中断向量表:kernel/arch/x86/kernel/syscall_table_32.S中的102号中断:
  1.     
  2. .long sys_socketcall  
复制代码
7) 进入sys_socketcall()函数,根据子中断号以决定走哪个分支:kernel/net/Socket.c:
  1.     
  2. switch (call) {  
  3.     case SYS_SOCKET:  
  4.         break;  
  5.     case SYS_BIND:  
  6.         …...  
复制代码
二、socket其他库函数(bind, accept...)
1、对于其他库函数,都是引用上面提到的glibc-2.3.6/sysdept/unix/sysv/linux/i386/socket.S来实现的,如
a) bind.S:
  1.   
  2. #define socket  bind  
  3. #define NARGS   3  
  4. #define NO_WEAK_ALIAS   1  
  5. #include <socket.S>  
  6. weak_alias (bind, __bind)  
复制代码
b) accept.S:
  1.     
  2. #define socket  accept  
  3. #define __socket __libc_accept  
  4. #define NARGS   3  
  5. #define NEED_CANCELLATION  
  6. #include <socket.S>  
  7. libc_hidden_def (accept)  
复制代码
在各个库函数调用中,设置不同的参数,如socket(用于设置子中断号), NARGS(系统调用的参数个数)等,最终由

C代码  
movl $P(SOCKOP_,socket), %ebx   /* Subcode is first arg to syscall.  */  

来生成最终的子中断号,然后放到ebx寄存器中;
2、所有socket系统调用的子中断号参见glibc-2.3.6/sysdept/unix/sysv/linux/Socketcall.h:
  1.     
  2. #define SOCKOP_socket       1  
  3. #define SOCKOP_bind     2  
  4. #define SOCKOP_connect      3  
  5. #define SOCKOP_listen       4  
  6. #define SOCKOP_accept       5  
  7. #define SOCKOP_getsockname  6  
  8. #define SOCKOP_getpeername  7  
  9. #define SOCKOP_socketpair   8  
  10. #define SOCKOP_send     9  
  11. #define SOCKOP_recv     10  
  12. #define SOCKOP_sendto       11  
  13. #define SOCKOP_recvfrom     12  
  14. #define SOCKOP_shutdown     13  
  15. #define SOCKOP_setsockopt   14  
  16. #define SOCKOP_getsockopt   15  
  17. #define SOCKOP_sendmsg      16  
  18. #define SOCKOP_recvmsg      17  
复制代码
系列文章,请参考我在iteye的blog:http://diecui1202.iteye.com
原创粉丝点击