当前位置: 首页 > 编程日记 > 正文

Linux内核分析——第五章 系统调用

                第五章 系统调用

5.1 与内核通信

1、系统调用在用户空间进程和硬件设备之间添加了一个中间层,该层主要作用有三个:

  (1)为用户空间提供了一种硬件的抽象接口

  (2)系统调用保证了系统的稳定和安全

  (3)每个进程都运行在虚拟系统中,而在用户空间和系统的其余部分提供这样一层公共接口。

2、在Linux中,系统调用是用户空间访问内核的唯一手段:除异常和陷入外,它们是内核唯一的合法入口。

5.2 API、POSIX和C库

1、一般情况下,应用程序通过在用户空间实现的应用编程接口(API)而不是直接通过系统调用来编程。

2、一个API定义了一组应用程序使用的编程接口。

3、API、POSIX、C库以及系统调用之间的关系:

4、在Unix世界中,最流行的应用编程接口是基于POSIX标准的。

5、Linux的系统调用作为C库的一部分提供。

6、C库实现了Unix系统的主要API,包括标准C库函数和系统调用接口。

5.3 系统调用

一、系统调用

  1、要访问系统调用(syscall),通常通过C库中定义的函数调用来进行。

  2、系统调用通过一个long类型的返回值来表示成功或者错误。通常,但也不绝对,用一个负的返回值来表明错误。返回一个0值通常表明成功。系统调用在出现错误的时候C库会把错误码写入errno全局变量,通过调用perror()库函数,可以把该变量翻译成用户可以理解的错误字符串。

  3、系统调用在用户空间和内核空间有不同的返回值类型,在用户空间为int,在内核空间为long。

二、系统调用号

  1、当用户空间的进程执行一个系统调用时,就用系统调用号指明到底执行哪个系统调用。进程不会提及系统调用的名称。

  2、系统调用号独一无二,一旦分配就不能再有任何变更。否则编译好的应用程序就会崩溃。

  3、Linux有一个“未实现”系统调用sys_ni_syscall(),它除了返回-ENOSYS外不做任何其他工作,这个错误号就是专门针对无效的系统调用而设的。

  4、内核记录了系统调用表中的所有已注册过的系统调用的列表,存储在sys_call_table中。

三、系统调用的性能

  1、Linux系统调用比其他许多操作系统执行得要快。

  2、原因:

    (1)上下文切换时间短。

    (2)系统调用处理程序和每个系统调用本身也都非常简洁。

5.4 系统调用处理程序

一、系统调用处理程序

  1、通知内核的机制是软中断实现的:通过引发一个异常来促使系统切换到内核态去指向异常处理程序,而此时的异常处理程序就是系统调用的处理程序。

  2、在x86系统上预定义的软中断是中断号128,通过int $0x80指令触发该中断。

二、指定恰当的系统调用

  1、在x86上,系统调用号是通过eax寄存器传递给内核的。

  2、system_call()函数通过将给定的系统调用号与NR_syscalls作比较来检查其有效性。大于等于返回-ENOSYS,否则执行相应系统调用:call *sys_call_table(,%rax,8)

三、参数传递

  1、在x86—32系统上,ebx,ecx,edx,esi和edi按顺序存放前五个参数。需要6个及以上参数,应用一个单独的寄存器存放指向这些参数在用户空间地址的指针。

 

  2、给用户空间的返回值也通过寄存器传递。在x86系统上,它存放在eax寄存器中。

5.5 系统调用的实现

一、实现系统调用

  1、实现一个新的系统调用的第一步是决定它的用途。在Linux中不提倡采用多用途的系统调用。

  2、系统调用的接口应该力求简洁。

  3、系统调用设计得越通用越好。

  4、提供机制而不是策略。

  5、时刻注意可移植性和健壮性。

二、参数验证

  1、最重要的检查:检查用户提供的指针是否有效。

  2、在接受一个用户空间的指针之前,内核必须保证:

    (1)指针指向的内存区域必须属于用户空间。

    (2)指针指向的内存区域在进程的地址空间里。

    (3)决不能绕过内存访问限制。

  3、两个方法检查在内核空间与用户空间之间数据的来回拷贝:

    (1)向用户空间写入数据,内核提供了copy_to_user();

    (2)从用户空间读取数据,内核提供了copy_from_user()。

    如果成功:返回0;

    如果失败:返回标准-EFAULT

  4、copy_to_user()和copy_from_user()都有可能引起阻塞。当包含用户数据的页被换出到硬盘上而不是在物理内存上的时候,会引起阻塞,此时,进程就会休眠,直到缺页处理程序将该页从硬盘重新换回物理内存。

  5、检查针对是否有合法权限——capable():返回0无权操作,返回非0有权操作。

5.6 系统调用上下文

一、系统调用上下文

  1、内核在执行系统调用时处于进程上下文。current指针指向当前任务,即引发系统调用的那个进程。

  2、在进程上下文中,内核可以休眠并且可以被抢占。

  3、当系统调用返回时,控制权仍然在system_call()中,它最终会负责切换到用户空间,并让用户进程继续执行下去。

二、绑定一个系统调用的最后步骤

  1、在系统调用表的最后加入一个表项。

  2、对于所支持的各种体系结构,系统调用号都必须定义于<asm/unistd.h>中。

  3、系统调用必须被编译进内核映像(不能被编译成模块)。放入kernel/下的一个相关文件中即可。

三、从用户空间访问系统调用

  1、系统调用靠C库支持,用户程序通过包含标准头文件并和C库链接,就可以使用系统调用。

  2、Linux本身提供了一组宏,用于直接对系统调用进行访问。它会设置好寄存器并调用陷入指令。这些宏是_syscalln(),其中n的范围从0到6,代表需要传递给系统调用的参数个数。

四、为什么不通过系统调用的方式实现

  1、建立一个新的系统调用的好处:

    (1)系统调用创建容易且使用方便。

    (2)linux系统调用的高性能显而易见。

  2、问题是:

    (1)你需要一个系统调用号,而这需要一个内核在处于开发版本的时候由官方分配给你。

    (2)系统调用被加入稳定内核后就被固化了,为了避免应用程序的崩溃,它的接口不允许做运动。

    (3)需要将系统调用分别注册到每个需要支持的体系结构中去。

    (4)在脚本中不容易调用系统调用,也不能从文件系统直接访问系统调用。

    (5)如果仅仅进行简单的信息交换,系统调用就大材小用了。

  3、替代方法:

  实现一个设备节点,并对此实现read()和write()。使用ioctl()对特定的设置进行操作或者对特定的信息进行检索。

    (1)像信号量这样的某些接口,可以用文件描述符来表示,因此也就可以按上述方式对其进行操作。

    (2)把增加的信息作为一个文件放在sysfs的合适位置。

  4、Linux系统尽量避免每出现一种新的抽象就简单地加入一个新的系统调用。

总结

  系统调用(System Call)是操作系统为在用户态运行的进程与硬件设备(如CPU、磁盘、打印机等)进行交互提供的一组接口。当用户进程需要发生系统调用时,CPU 通过软中断切换到内核态开始执行内核系统调用函数。

  一般情况下,应用程序通过在用户空间实现的应用编程接口(API)而不是直接通过系统调用来编程。一个API定义了一组应用程序使用的编程接口。

参考资料

  《Linux内核设计与实现》  原书第3版

转载于:https://www.cnblogs.com/20135235my/p/5322773.html

相关文章:

BZOJ 3110

http://www.lydsy.com/JudgeOnline/problem.php?id3110 整体二分区间修改树状数组维护 #include<cstdio> #define FOR(i,s,t) for(register int is;i<t;i) inline int max(int a,int b){return a>b?a:b;} inline int min(int a,int b){return a<b?a:b;} type…

css 选择器 伪元素_CSS伪元素-解释选择器之前和之后

css 选择器 伪元素选择器之前 (Before Selector) The CSS ::before selector can be used to insert content before the content of the selected element or elements. It is used by attaching ::before to the element it is to be used on.CSS ::before选择器可用于在选定…

各种面试题啊1

技术 基础 1.为什么说Objective-C是一门动态的语言&#xff1f; 什么叫动态静态 静态、动态是相对的&#xff0c;这里动态语言指的是不需要在编译时确定所有的东西&#xff0c;在运行时还可以动态的添加变量、方法和类 Objective-C 可以通过Runtime 这个运行时机制&#xff0c…

PEP8 Python

写在前面 对于代码而言&#xff0c;相比于写&#xff0c;它更多是读的。 pep8 一、代码编排 缩进&#xff0c;4个空格的缩进&#xff0c;编辑器都可以完成此功能&#xff1b;每行最大长度79&#xff0c;换行可以使用反斜杠&#xff0c;换行点要在操作符的后边。类和top-level函…

粒子滤波 应用_如何使用NativeScript开发粒子物联网应用

粒子滤波 应用If youre developing any type of IoT product, inevitably youll need some type of mobile app. While there are easy ways, theyre not for production use.如果您要开发任何类型的物联网产品&#xff0c;则不可避免地需要某种类型的移动应用程序。 尽管有简单…

wkwebView基本使用方法

WKWebView有两个delegate,WKUIDelegate 和 WKNavigationDelegate。WKNavigationDelegate主要处理一些跳转、加载处理操作&#xff0c;WKUIDelegate主要处理JS脚本&#xff0c;确认框&#xff0c;警告框等。因此WKNavigationDelegate更加常用。 比较常用的方法&#xff1a; #p…

引用类型(一):Object类型

对象表示方式 1、第一种方式&#xff1a;使用new操作符后跟Object构造函数 var person new Object();<br/> person.name Nicholas;<br/> person.age 29; 2、对象字面量表示法 var person {name:Nicholas,age:29 } *:在age属性的值29的后面不能添加逗号&#xf…

(第四周)要开工了

忙碌的一周又过去了&#xff0c;这周的时间很紧&#xff0c;但是把时间分配的比较均匀&#xff0c;考研复习和各门功课都投入了一定的精力&#xff0c;所以不像前三周一样把大多数时间都花费在了软件工程上。也因为结对项目刚开始&#xff0c;我们刚刚进行任务分工以及查找资料…

统计数字,空白符,制表符_为什么您应该在HTML中使用制表符空间而不是多个非空白空间(nbsp)...

统计数字,空白符,制表符There are a number of ways to insert spaces in HTML. The easiest way is by simply adding spaces or multiple character entities before and after the target text. Of course, that isnt the DRYest method.有多种方法可以在HTML中插入空格。…

Python20-Day02

1、数据 数据为什么要分不同的类型 数据是用来表示状态的&#xff0c;不同的状态就应该用不同类型的数据表示&#xff1b; 数据类型 数字&#xff08;整形&#xff0c;长整形&#xff0c;浮点型&#xff0c;复数&#xff09;&#xff0c;字符串&#xff0c;列表&#xff0c;元组…

Android网络框架-OkHttp3.0总结

一、概述 OkHttp是Square公司开发的一款服务于android的一个网络框架&#xff0c;主要包含&#xff1a; 一般的get请求一般的post请求基于Http的文件上传文件下载加载图片支持请求回调&#xff0c;直接返回对象、对象集合支持session的保持github地址&#xff1a;https://githu…

第一天写,希望能坚持下去。

该想的都想完了&#xff0c;不该想的似乎也已经尘埃落定了。有些事情&#xff0c;终究不是靠努力或者不努力获得的。顺其自然才是正理。 以前很多次想过要努力&#xff0c;学习一些东西&#xff0c;总是不能成&#xff0c;原因很多&#xff1a; 1.心中烦恼&#xff0c;不想学…

mac gource_如何使用Gource显示项目的时间表

mac gourceThe first time I heard about Gource was in 2013. At the time I watched this cool video showing Ruby on Rails source code evolution:我第一次听说Gource是在2013年 。 当时&#xff0c;我观看了这段很酷的视频&#xff0c;展示了Ruby on Rails源代码的演变&a…

insert语句让我学会的两个MySQL函数

我们要保存数据到数据库&#xff0c;插入数据是必须的&#xff0c;但是在业务中可能会出于某种业务要求&#xff0c;要在数据库中设计唯一索引&#xff1b;这时如果不小心插入一条业务上已经存在同样key的数据时&#xff0c;就会出现异常。 大部分的需求要求我们出现唯一键冲突…

对PInvoke函数函数调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。...

C#引入外部非托管类库时&#xff0c;有时候会出现“对PInvoke函数调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配”的报错。 通常在DllImport标签内加入属性CallingConventionCallingConvention.Cdecl即可解决该问题。 如&#xff1a; [Dll…

Python字符串方法用示例解释

字符串查找方法 (String Find Method) There are two options for finding a substring within a string in Python, find() and rfind().在Python中的字符串中有两个选项可以找到子字符串&#xff1a; find()和rfind() 。 Each will return the position that the substring …

关于命名空间namespace

虽然任意合法的PHP代码都可以包含在命名空间中&#xff0c;但只有以下类型的代码受命名空间的影响&#xff0c;它们是&#xff1a;类&#xff08;包括抽象类和traits&#xff09;、接口、函数和常量。在声明命名空间之前唯一合法的代码是用于定义源文件编码方式的 declare 语句…

一 梳理 从 HDFS 到 MR。

MapReduce 不仅仅是一个工具&#xff0c;更是一个框架。我们必须拿问题解决方案去适配框架的 map 和 reduce 过程很多情况下&#xff0c;需要关注 MapReduce 作业所需要的系统资源&#xff0c;尤其是集群内部网络资源的使用情况。这是MapReduce 框架在设计上的取舍&#xff0c;…

huffman树和huffman编码

不知道为什么&#xff0c;我写的代码都是又臭又长。 直接上代码&#xff1a; #include <iostream> #include <cstdarg> using namespace std; class Node{ public:int weight;int parent, lChildren, rChildren;Node(int weight, int parent, int lChildren, int …

react 监听组合键_投资组合中需要的5个React项目

react 监听组合键Youve put in the work and now you have a solid understanding of the React library.您已经完成工作&#xff0c;现在对React库有了扎实的了解。 On top of that, you have a good grasp of JavaScript and are putting its most helpful features to use …

Unity 单元测试(PLUnitTest工具)

代码测试的由来 上几个星期上面分配给我一个装备系统,我经过了几个星期的战斗写完90%的代码. 后来策划告诉我需求有一定的改动,我就随着策划的意思修改了代码. 但是测试(Xu)告诉我装备系统很多功能都用不上了. Xu: 我有300多项测试用例,现在有很多项都无法运行了. 你修改了部分…

Best Time to Buy and Sell Stock II

题目&#xff1a; Say you have an array for which the i th element is the price of a given stock on day i. Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multipl…

求给定集合的幂集

数据结构中说这个问题可以用类似8皇后的状态树解法。 把求解过程看成是一棵二叉树&#xff0c;空集作为root&#xff0c;然后遍历给定集合中的元素&#xff0c;左子树表示取该元素&#xff0c;右子树表示舍该元素。 然后&#xff0c;root的左右元素分别重复上述过程。 就形成…

angular 命令行项目_Angular命令行界面介绍

angular 命令行项目Angular is closely associated with its command-line interface (CLI). The CLI streamlines generation of the Angular file system. It deals with most of the configuration behind the scenes so developers can start coding. The CLI also has a l…

oracle-imp导入小错filesize设置

***********************************************声明*********************************************************************** 原创作品&#xff0c;出自 “深蓝的blog” 博客。欢迎转载&#xff0c;转载时请务必注明出处。否则追究版权法律责任。表述有错误之处&#xf…

CentOS 7 下用 firewall-cmd / iptables 实现 NAT 转发供内网服务器联网

自从用 HAProxy 对服务器做了负载均衡以后&#xff0c;感觉后端服务器真的没必要再配置并占用公网IP资源。 而且由于托管服务器的公网 IP 资源是固定的&#xff0c;想上 Keepalived 的话&#xff0c;需要挤出来 3 个公网 IP 使用&#xff0c;所以更加坚定了让负载均衡后端服务器…

八皇后的一个回溯递归解法

解法来自严蔚敏的数据结构与算法。 代码如下&#xff1a; #include <iostream> using namespace std; const int N 8;//皇后数 int count 0;//解法统计 int a[N][N];//储存值的数组const char *YES "■"; const char *NO "□"; //const char *Y…

即时编译和提前编译_即时编译说明

即时编译和提前编译Just-in-time compilation is a method for improving the performance of interpreted programs. During execution the program may be compiled into native code to improve its performance. It is also known as dynamic compilation.即时编译是一种提…

bzoj 2588 Spoj 10628. Count on a tree (可持久化线段树)

Spoj 10628. Count on a tree Time Limit: 12 Sec Memory Limit: 128 MBSubmit: 7669 Solved: 1894[Submit][Status][Discuss]Description 给定一棵N个节点的树&#xff0c;每个点有一个权值&#xff0c;对于M个询问(u,v,k)&#xff0c;你需要回答u xor lastans和v这两个节点…