系统调用的封装
2016-02-28 11:24
197 查看
封装系统调用是一件简单而枯燥的事情
封装系统调用的基本过程是:
1. 确认要封装的系统调用,并将系统调用对应的系统调用名称设置为函数的名称。
如系统调用号1对应的系统调用exit封装的函数的名字便是exit。
2. 确认要封装的系统调用的参数及参数类型,并设置为函数的参数。
如exit系统调用的参数为int status,则exit函数参数为int status, exit(int status)。
3. 确认要封装的系统调用的返回值类型,并设置函数的返回值。
如exit系统调用的返回值类型为int,则exit函数返回值为int,int exit(int status)。
完成以上内容,一个函数的基本框架已经搭建完成。
还缺少函数的执行单元,执行单元可以使用嵌入式汇编完成。
通过以上步骤便可以完成任意系统调用的封装。
使用宏,封装变得方便许多
linux内核中提供了一种使用宏来封装系统调用的方式。
宏的使用主要在2个方面。
定义系统调用号与系统调用名称之间的关系。
完成函数的构建。
以_syscall1(type,name,type1,arg1) 为例。
exit系统调用可以写成_syscall1(int,exit,int,status)。而其宏展开后为
替换后一个exit函数也建立起来了。
使用这种宏定义可以快速的构建起系统调用。
附录
32位系统linux所支持的系统调用列表
32位系统linux封装系统调用宏
封装系统调用的基本过程是:
1. 确认要封装的系统调用,并将系统调用对应的系统调用名称设置为函数的名称。
如系统调用号1对应的系统调用exit封装的函数的名字便是exit。
2. 确认要封装的系统调用的参数及参数类型,并设置为函数的参数。
如exit系统调用的参数为int status,则exit函数参数为int status, exit(int status)。
3. 确认要封装的系统调用的返回值类型,并设置函数的返回值。
如exit系统调用的返回值类型为int,则exit函数返回值为int,int exit(int status)。
完成以上内容,一个函数的基本框架已经搭建完成。
系统调用1->exit封装后 int exit(int status) { }
还缺少函数的执行单元,执行单元可以使用嵌入式汇编完成。
int exit(int status) { long __res; asm("int $0x80" : "=a" (__res) : "0" (1),"b" ((long)(status))); if (__res >= 0) return (int) __res; errno = -__res; \ return -1; \ }
通过以上步骤便可以完成任意系统调用的封装。
使用宏,封装变得方便许多
linux内核中提供了一种使用宏来封装系统调用的方式。
宏的使用主要在2个方面。
定义系统调用号与系统调用名称之间的关系。
#define __NR_restart_syscall 0 #define __NR_exit 1 #define __NR_fork 2 #define __NR_read 3 ...
完成函数的构建。
#define _syscall0(type,name) \ type name(void) \ { \ long __res; \ __asm__ volatile ("int $0x80" \ : "=a" (__res) \ : "0" (__NR_##name)); \ if (__res >= 0) \ return (type) __res; \ ex_errno = -__res; \ return -1; \ } #define _syscall1(type,name,type1,arg1) \ type name(type1 arg1) \ { \ long __res; \ __asm__ volatile ("int $0x80" \ : "=a" (__res) \ : "0" (__NR_##name),"b" ((long)(arg1))); \ if (__res >= 0) \ return (type) __res; \ ex_errno = -__res; \ return -1; \ } ...
以_syscall1(type,name,type1,arg1) 为例。
exit系统调用可以写成_syscall1(int,exit,int,status)。而其宏展开后为
int exit(int status) \ { \ long __res; \ __asm__ volatile ("int $0x80" \ : "=a" (__res) \ : "0" (1),"b" ((long)(status))); \ if (__res >= 0) \ return (int) __res; \ errno = -__res; \ return -1; \ } 所有type被第一个宏参数int替换了, 所有的name被第二个宏参数exit替换了。 所有的type1被第三个宏参数int替换了。 所有的arg1被第四个宏参数status替换了。 还有重要的一点 __NR_##name中 ##name表示##name会被修改成name表示的字符串, 当name为exit时,__NR_##name为__NR_exit, __NR_exit将被替换为上面定义的宏__NR_exit对应的值。
替换后一个exit函数也建立起来了。
使用这种宏定义可以快速的构建起系统调用。
附录
32位系统linux所支持的系统调用列表
32位系统linux封装系统调用宏
相关文章推荐
- HTML解析输入网址原理
- bzoj 3505 (排列组合)
- 参数化查询为什么能够防止SQL注入 (转)
- Android:Canvas中drawText的尺寸计算
- 1028. List Sorting (25)
- 【leetcode】【21】Merge Two Sorted Lists
- ZOJ 3785 11th省赛 J What day is that day?【打表找规律】
- 写个函数用来对二维数组排序(新浪)
- 4.1.3.3 Android 网络状态监听的静态广播接受者和动态广播接受者Broadcast-Receiver
- 一个完整的WSDL文档及各标签详解
- 玩转iOS开发 - JSON 和 Xml 数据解析
- poj1655 树的重心 树形dp
- Monkey日志信息Event percentages说明
- 招聘网站
- 关于构建之法的问题
- 字符串反转成整数
- 【转】滚动校验(Rolling Checksum)算法
- Manthan, Codefest 16 D. Fibonacci-ish
- Excel 回归分析
- input标签 和fmt:formatDate的使用