标准库是如何发起系统调用的
来源:互联网 发布:手机windows主题下载 编辑:程序博客网 时间:2024/05/18 02:55
应用程序在发起某个系统调用时,是先调用标准库中的同名函数,标准库再根据不同体系结构来选择特定的方式陷入内核。
以socket库函数为例(以下均为uClibc中的实现),来说明标准库是如何一步步解析系统调用名并进入内核的:
socket系统调用号:
#define __NR_socket (4000 + 183)
socket()函数的实现就是下面的函数:
_syscall3(int, socket, int, family, int, type, int, protocol)
这个函数调用下面的宏:
SYSCALL_FUNC(3, int, socket, int, family, int, type, int, protocol)
宏展开就成了:
int socket(C_DECL_ARGS_3(int, family, int, type, int, protocol)) { \ return (type)INLINE_SYSCALL(socket, 3, C_ARGS_3(int, family, int, type, int, protocol)); \}
这里会把类型和参数名之间的逗号去掉,参数名增加两个:系统调用名字和参数个数,于是进一步展开得到:
int socket(int family, int type, int protocol) { \ return (int)INLINE_SYSCALL(socket, 3, family, type, protocol); \}
INLINE_SYSCALL的定义仍是一个宏:
INLINE_SYSCALL_NCS(__NR_socket, 3, family, type, protocol)
宏展开,系统调用名改为系统调用号,增加一个err参数:
INTERNAL_SYSCALL_NCS(__NR_socket, err, 3, family, type, protocol)
根据参数个数3找到internal_syscall3,其定义如下,前三个参数用在内嵌汇编里所以看起来有点奇怪,实际上就是直接替换:
internal_syscall3( = __NR_socket, ,"r" (__v0), err, family, type, protocol)!({ \ long _sys_result; \ \ { \ register ARG_TYPE __v0 __asm__("$2") = __NR_socket; \ register ARG_TYPE __a0 __asm__("$4") = (ARG_TYPE) arg1; \ register ARG_TYPE __a1 __asm__("$5") = (ARG_TYPE) arg2; \ register ARG_TYPE __a2 __asm__("$6") = (ARG_TYPE) arg3; \ register ARG_TYPE __a3 __asm__("$7"); \ __asm__ __volatile__ ( \ ".set\tnoreorder\n\t" \ "syscall\n\t" \ ".set\treorder" \ : "=r" (__v0), "=r" (__a3) \ : input, "r" (__a0), "r" (__a1), "r" (__a2) \ : __SYSCALL_CLOBBERS); \ err = __a3; \ _sys_result = __v0; \ } \ _sys_result; \})
上面的过程就是保存参数,传入系统调用号,执行syscall指令,进入内核态,并准备接收两个返回值:错误码和结果。这里陷入内核的过程是体系结构相关的,上述为MIPS的做法,而ARM中是通过swi指令陷入软中断来完成的。
进入到内核之后的工作以及如何返回到用户态,可以参考MIPS中的系统调用这篇文章中的介绍。
如果在标准库中没有定义某个系统调用的同名函数,可以直接通过syscall(),例如获取线程tid的系统调用gettid,其系统调用号为224,但uClibc中并没有定义gettid()库函数,则可以通过syscall(224)使用该系统调用。而对于用户自定义的系统调用(当然不建议这样做),也只能用syscall()。
- 标准库是如何发起系统调用的
- 系统调用与标准库调用的区别
- Linux系统调用是如何被信号终止的
- Ecstore中如何调用发起Ajax请求
- Unix编程学习笔记--------系统调用的疑问????? 到底什么是系统调用???? 系统调用是如何实现的???
- 标准库函数和系统调用的区别
- 标准库函数和系统调用的区别
- 标准库函数和系统调用的区别
- 函数是如何调用的
- 手机病毒是怎样发起攻击的
- linux 系统调用与标准库调用的区别详细解析
- linux 系统调用与标准库调用的区别详细解析
- linux 系统调用与标准库调用的区别详细解析(转)
- 被调用的linux系统函数system的是如何实现的!
- 如何设置工作流的发起权限?
- 看明白在uclibc中网络系统调用是如何实现的
- 函数调用是如何在系统中实现的-以C为例
- 如何在文章页以外调用wordpress文章的第一条,最好是系统函数 而不是数据库调用
- 随笔17.10.15
- json_encode不对中文进行转码、json_decode解析json字符串返回NULL的处理方法
- python zipfile模块
- 【Java 】--jpa中继承的实现
- Android本地拒绝服务漏洞浅析
- 标准库是如何发起系统调用的
- 【leetcode】Keyboard Row题目的C++解法
- 122. Best Time to Buy and Sell Stock II
- Android Material Design 风格的新闻App
- SMPCUP2017——NLP
- RecyclerView使用 以及简单多条目
- AngularJS 注册表单验证
- 浅谈Java里的三种锁:偏向锁、轻量级锁和重量级锁
- Qt5使用qDebug()在windows控制台中输出信息