1、问:什么是系统调用?

用户应用程序访问并使用内核所提供的各种服务的途径即是系统调用,也称系统调用接口层。

2、问:为什么需要系统调用?

① 系统调用作为内核和应用程序之间的中间层,扮演了一个桥梁角色,系统调用把应用程序的请求传达给内核,待内核处理完之后再将结果返回给应用程序

② 系统调用可以为用户空间提供访问硬件资源的统一接口,以至于应用程序不必关心具体的硬件访问操作

③ 系统调用可以对系统进行保护,保证系统的稳定和安全

3、系统调用、API、POSIX、C库、系统命令、内核函数的区别?

①在通常情况下,应用程序是通过操作系统提供的应用编程接口(API)而不是直接通过系统调用来编程

②在UNIX世界里,最通用的操作系统API基于POSIX(Portable Operating System Interface of UNIX,可移植操作系统接口)标准,Linux 兼容于POSIX标准,提供了根据POSIX而定义的API函数,这些API函数和系统调用之间有着直接关系,一个API函数可以由一个系统调用实现,也可以通过多个系统调用实现,还可以完全不用系统调用实现

③API通常以C库的方式提供,C库提供了POSIX的绝大部分API,同时,内核提供的每个系统调用在C库中都有相应的封装函数

④系统命令位于C库的更上层,利用C库实现的可执行程序,strace工具可以追踪命令的执行过程

⑤应用程序通过系统调用进入内核后,会执行各个系统调用对应的内核函数,即系统调用服务例程,除了系统调用服务例程之外,内核还有许多内核函数,有些内核函数局限于某个内核文件自己使用,有些则是用export导出来供内核其他部分使用,可以使用ksyms命令或通过/proc/ksyms 文件查看

4、系统调用表

系统调用表sys_call_table 存储了所有系统调用对应的服务例程的函数地址

5、系统调用号

用户通过系统调用号作为下标去获取系统调用表sys_call_table中的服务例程的函数地址来指明要执行哪个系统调用

系统调用号定义在include/asm-i386/unistd.h文件中

6、系统调用服务例程

系统调用最终由系统调用服务例程来完成明确的操作,它的命名遵守一些规则,函数名都具有“sys_”前缀,函数定义中必须添加asmlinkage标记,通知编译器仅从堆栈中获取该函数的参数,通常返回0表示成功,负数表示失败

7、如何使用系统调用

  第一种方式是通过C库函数,包括系统调用在C库中的封装函数和其他普通函数

  第二种方式是使用_syscall 宏。2.6.18版本之前的内核,在include/asm-i386/unistd.h文件中定义7个宏分别是:

_syscall0(type,name)
_syscall1(type, name, type1, arg1)
_syscall2(type, name, type1, arg1, type2, arg2)
_syscall3(type, name, type1, arg1, type2, arg2, type3, arg3)
_syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4)
_syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5)
_syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5, type6, arg6)

其中,type表示所生成系统调用的返回值类型,name表示该系统调用的名称,typeN、argN分别表示第N个参数的类型和名称,它们的数目和_syscall后面的数字一样大,这些宏的作用是创建名为name的函数,_syscall后面跟的数字指明了该函数的参数的个数。例如:sysinfo系统调用用于获取系统总体统计信息,使用_syscall宏定义如下:

_syscall1(int, sysinfo, struct sysinfo *, info);

展开后的形式为:

int sysinfo(struct sysinfo* info)
{long _res;__asm__ volatile("int $0x80" : "=a" (_res) : "0" (116), "b" ((long) (info)));do {if ((unsigned long)(_res) >= (unsigned long)(-(128 + 1))) {errno = -(_res);_res = -1;}  return (int)(_res);} while (0);
}

在程序文件里使用_syscall宏定义需要的系统调用,就可以在接下来的代码中通过系统调用名称直接调用该系统调用,例如:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <errno.h>
 4 #include <linux/unistd.h>
 5 #include <linux/kernel.h>
 6
 7 _syscall1(int, sysinfo, struct sysinfo *, info);
 8
 9 int main(void)
10 {
11     struct sysinfo s_info;
12     int error;
13
14     error = sysinfo(&s_info);
15     printf("code error = %d\n", error);
16     printf("Uptime = %lds\n", s_info.uptime);
17
18     return 0;
19 }

但是,自2.6.19版本开始,_syscall 宏被废除,我们需要使用syscall函数,通过制定系统调用号和一组参数来调用系统调用

syscall的函数原型为:

int syscall(int number, ...);

其中,number是系统调用号,number后面应顺序接上该系统调用的所有参数,下面是gettid系统调用的实例:

 1 #include <unistd.h>
 2 #include <sys/syscall.h>
 3 #include <sys/types.h>
 4
 5 #define _NR_gettid 224
 6
 7 int main(void)
 8 {
 9     pid_t tid;
10     tid = syscall(_NR_gettid);
11     return 0;
12 }

大部分系统调用都包括了一个SYS_符号常量来制定自己到系统调用号的映射,因此上面第10行可重写为:

tid = syscall(SYS_gettid);

8、系统调用执行过程

如图所示,系统调用的执行需要一个指令完成从用户空间到内核空间的状态转换,这种指令被称为操作系统陷入指令,linux通过软中断来实现这种陷入,对于X86来说,是软中断0x80,也即int $0x80汇编指令,通过软中断0x80,系统会跳到一个预设的内核空间地址,它指向了系统调用处理程序,即在arch/i386/kernel/entry.S文件中使用汇编语言编写的system_call函数

所有的系统调用都会执行system_call 函数,当软中断指令int 0x80执行时,系统调用号会被放入eax寄存器,并且sys_call_table每一项占用4个字节,system_call函数读取eax 寄存器获得当前系统调用的系统调用号,将其乘以4得到偏移地址,然后以sys_call_table为基址,加上得到的偏移地址就是应该执行的系统调用服务例程的地址。

前面说过,系统调用服务地产定义中的asmlinkage标记表示,编译器仅从堆栈中获取该函数的参数,而不需要从寄存器中获得任何参数,在进入system_call之前,用户应用将参数放到对应寄存器中,system_call函数执行时会首先将这些寄存器压入堆栈。

有一个特殊的服务例程sys_ni_syscall,它代表了那些已经被内核中淘汰的系统调用。

系统调用通过软中断0x80陷入内核,跳转到系统调用处理程序system_call函数,并执行相应的服务例程,由于是嗲表用户进程,所以这个执行过程并不属于中断上下文,而是出于进程上下文,因此,系统调用执行过程中,可以访问用户进程的许多信息,可以被其他进程抢占,可以休眠。

9、如何实现一个新的系统调用

  ① 编写系统调用服务例程,并在相应的头文件(include/linux/syscalls.h)中添加原型声明

  ② 在相应的头文件(include/asm-i386/unistd.h)中添加系统调用号

  ③ 修改系统调用表

  ④ 重新编译内核并测试

转载于:https://www.cnblogs.com/linux-rookie/p/3375944.html

linux 内核修炼之道——系统调用相关推荐

  1. 《Linux内核修炼之道》精华分享与讨论(9)——内核学习的相关资源

    推荐博文: Linux内核"问题门"--学习问题.经验集锦 推荐下载:<Linux内核修炼之道>精华版之方法论 "世界上最缺的不是金钱,而是资源." ...

  2. Linux内核修炼之道 之 前言

    推荐博文: Linux内核"问题门"--学习问题.经验集锦 推荐下载:<Linux内核修炼之道>精华版之方法论 至此落笔之际,恰至Linux问世18周年,18年的成长, ...

  3. 《Linux内核修炼之道》精华分享与讨论(1)——缅怀已逝的十八年(1991~1998)

    推荐博文: Linux内核"问题门"--学习问题.经验集锦 推荐下载:<Linux内核修炼之道>精华版之方法论 至此落笔之际,恰至Linux问世18周年,18年的成长, ...

  4. 《Linux内核修炼之道》精华分享与讨论(7)——分析内核源码如何入手?(下)

    推荐博文: Linux内核"问题门"--学习问题.经验集锦 推荐下载:<Linux内核修炼之道>精华版之方法论 下面的分析,米卢教练说了,内容不重要,重要的是态度.就像 ...

  5. 《Linux内核修炼之道》精华版 之 方法论(提供pdf下载)

    到目前为之,博客上分享的精华篇都可以归为方法论的范畴,在很多时候,都是方法论要比细节紧要得多.而这些精华篇又可细分为三个专题:Linux 大史记:内核学习的方法论:驱动开发的方法论. Linux 大史 ...

  6. 《Linux内核修炼之道》精华分享与讨论(14)——内核中的链表

    早上上班坐地铁要排队,到了公司楼下等电梯要排队,中午吃饭要排队,下班了追求一个女孩子也要排队,甚至在网上下载个什么门的短片也要排队,每次看见人群排成一条长龙时,才真正意识到自己是龙的传人.那么下面咱们 ...

  7. Linux驱动修炼之道-SPI驱动框架源码分析(上)

    Linux驱动修炼之道-SPI驱动框架源码分析(上)   SPI协议是一种同步的串行数据连接标准,由摩托罗拉公司命名,可工作于全双工模式.相关通讯设备可工作于m/s模式.主设备发起数据帧,允许多个从设 ...

  8. e2200网卡驱动 linux,Linux驱动修炼之道-驱动中一些常见的宏

    Linux驱动修炼之道-驱动中一些常见的宏 努力成为linux kernel hacker的人李万鹏原创作品,为梦而战.转载请标明出处 http://doc.xuehai.net/woshixinga ...

  9. 向linux内核增加新的系统调用,为linux内核添加新的系统调用

    为linux内核添加新的系统调用 作者:李志勇 更多精彩: 更多精彩: 开发平台:x86 ubuntu 目标平台:S3C6410 linux3.4.4 一.    打开内核源码目录下arch/arm/ ...

  10. linux内核ppt刘小明,【陈老师华为北研所讲座PPT】从机制与策略探究Linux内核设计之道(4)...

    原标题:[陈老师华为北研所讲座PPT]从机制与策略探究Linux内核设计之道(4) 解放编译程序,以统一的方式分配逻辑地址. 首先内核通过映射机制把进程的虚拟地址映射到物理地址,在进程运行时,如果内核 ...

最新文章

  1. 第二十二课.XGBoost
  2. iptables从入门到放弃
  3. .NET程序设计之四书五经
  4. Java 技术篇 - 前端浏览器发送一次url请求后端ServerSocket接收到两次请求原因及解决方法,GET /favicon.ico HTTP/1.1问题处理
  5. 对List中对象的去重
  6. 产品小白的知识点1——用户周期
  7. Redis学习(一)——
  8. 牛客16785 Cantor表
  9. 面向切面编程--AOP(二)
  10. CSS 文字垂直居中自适应 - 代码篇
  11. mysql oracle sqlserver分页,三种常用数据库(Oracle、MySQL、SQLServer)的分页之SQLServer分页...
  12. 九章基础算法03:树和递归
  13. PHP函数的引用传递(地址传递)
  14. Eprime error number 1234 :unable to load sound 203
  15. 模拟人生4修改服务器,模拟人生4 全秘籍、作弊码一览及修改方法汇总
  16. 思科路由器配置NAT地址转换
  17. 什么是范数,及其对应的 “曼哈顿距离“、“欧式距离“、“闵氏距离“、“切比雪夫距离“
  18. html做坦克大战的效果,HTML5实现坦克大战(一)
  19. 什么是“高新技术企业”?申报山西省高企认定有哪些条件?
  20. ElasticSearch重启脚本

热门文章

  1. PAT (Basic Level) Practice1016 部分A+B
  2. 使用hive计算每一年的最大气温的日期+温度
  3. 大数据各组件默认端口
  4. flink API之Sink入门
  5. js处理web页面滚动条
  6. Maven传递依赖冲突解决(版本冲突)
  7. Android apk如何加固防止被破解(防止逆向编译)
  8. 特殊权限及SUID,facl及Linux的终端
  9. [置顶]       Web开发百宝箱——提升网站档次的时尚 jQuery 图片滚动插件
  10. 64位内核第三讲,Windbg的使用.以及命令