Socket与系统调用深度分析
Posted luhaipeng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Socket与系统调用深度分析相关的知识,希望对你有一定的参考价值。
一、Socket和系统调用
操作系统是计算机资源的管理者,他保证资源被所有的进程共享,并且进程之间不会有干扰,为了达到这个目的,进程不会拥有操作硬件的功能,即进程在计算机上运行是受限制的。而操作系统为了对程序员提供操作硬件的功能,对外暴露一层接口,这层接口就称为系统调用(syscall)。系统调用有很多种类,今天我们主要讨论的是网络相关的系统调用。
1 系统调用号 函数名 系统调用 所在文件 2 41 socket sys_socket net/socket.c 3 42 connect sys_connect net/socket.c 4 43 accept sys_accept net/socket.c 5 44 sendto sys_sendto net/socket.c 6 45 recvfrom sys_recvfrom net/socket.c 7 46 sendmsg sys_sendmsg net/socket.c 8 47 recvmsg sys_recvmsg net/socket.c 9 48 shutdown sys_shutdown net/socket.c 10 49 bind sys_bind net/socket.c 11 50 listen sys_listen net/socket.c 12 51 getsockname sys_getsockname net/socket.c 13 52 getpeername sys_getpeername net/socket.c 14 53 socketpair sys_socketpair net/socket.c 15 54 setsockopt sys_setsockopt net/socket.c 16 55 getsockopt sys_getsockopt net/socket.c
上述就是网络相关的主要的系统调用,可以看到我们的在编写网络程序的时候,socket、bind、listen、accept等都榜上有名。
但是在man手册上我看到这样一句话:
On a some architectures--for example, x86-64 and ARM--there is no socketcall() system call; instead socket(2), accept(2), bind(2), and so on really are implemented as separate system calls.
意味着在不同的体系结构上可能用的不是socket ---> sys_socket / bind ---> sys_bind 这样的调用方式,可能调用的是socketcall()。 下面我们来进行验证。
二、gdb跟踪内核代码
2.1 调用sys_socket?
可以看到我们打断点在sys_socket函数上,并没有进入到断点,可以断定,创建socket的时候并没有调用sys_socket。
2.2 sys_socketcall?
果然在sys_socketcall打了断点后,运行我们的replyhi程序(命令?),即在断点处停止了,我们查看其函数调用栈,发现其进入系统调用的顺序是 entry_SYSENTER_32() ---> do_syscall_32_irqs_on()---->sys_socketcall()(实际上是调用的SYSCALL_DEFINE2函数)。我们来看看SYSCALL_DEFINE2()的代码:
1 SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args) 2 { 3 switch (call) { 4 case SYS_SOCKET: 5 err = __sys_socket(a0, a1, a[2]); 6 break; 7 case SYS_BIND: 8 err = __sys_bind(a0, (struct sockaddr __user *)a1, a[2]); 9 break; 10 case SYS_CONNECT: 11 err = __sys_connect(a0, (struct sockaddr __user *)a1, a[2]); 12 break; 13 case SYS_LISTEN: 14 err = __sys_listen(a0, a1); 15 break; 16 .... 17 }
可以看到SYSCALL_DEFINE2()函数通过其参数call来决定执行哪个函数。说起来可能有点乱,下面我们来一张图:
图里很清晰的展示了其中的调用关系,在调用库函数bind、listen、accept等函数时,通过SYSCALL_DEFINE2中的type参数来分发调用具体的工作函数。如call=1,则调用__sys_socket()函数来创建套接字。
2.3 __sys_socket
下面我们就来具体的进入到完成工作的函数中去看看。我们这里以创建socket的函数为例。
可以看到我们进入了其中,并且其参数family和type的值分别为2和1。代表着使用的协议和类型。其他的也没什么好看,就是创建了一个socket套接字,并且返回了。而bind、listen和accept等函数的实现都是通过swtich的选择,跳转到对应的函数去执行的。
以上是关于Socket与系统调用深度分析的主要内容,如果未能解决你的问题,请参考以下文章