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的选择,跳转到对应的函数去执行的。
原文地址:https://www.cnblogs.com/luhaipeng/p/12055566.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- C#字符串截取
- 使用Topshelf部署Windows服务
- IIS进程回收后第一次访问慢的问题
- k8s中服务添加hosts及一键转换脚本
- 【一起学系列】之状态模式:你听过“流程”模式吗?
- 【一起学系列】之代理模式:是为了控制访问啊!
- 【一起学系列】之剩下的设计模式们
- 如何使用k3OS和Argo进行自动化边缘部署?
- 设计模式总篇:从为什么需要原则到实际落地(附知识图谱)
- 一文入门DNS?从访问GitHub开始
- 没内鬼,来点干货!SQL优化和诊断
- 好像很厉害的生成器!一秒钟搞定一个项目
- 【一起学系列】之策略模式:好多鸭子啊
- 没内鬼,来点干货!volatile和synchronized
- 【一起学系列】之观察者模式:我没有在监控你啊