Linux系统调用的运行过程

操作系统Linux:增加系统调用 一、系统调用简介 Linux内核中设置了一组用于实现各种系统功能的子程序,称为系统调用。用户可以通过系统调用命令在自己的应用程序中调用它们。从某种角度来看,系统调用和普通的函数调用非常相似。区别仅仅在于,系统调用由操作系统核心提供,运行于核心态;而普通的函数调用由函数库或用户自己提供,运行于用户态。二者在使用方式上也有相似之处。 一般的,进程是不能访问内核的。它不能访问内核所占内存空间... 阅读详情
               在Linux中,系统调用是用户空间访问内核的唯一手段,它们是内核唯一的合法入口。

       一般情况下,应用程序通过应用编程接口(API)而不是直接通过系统调用来编程,而且这种编程接口实际上并不需要和内核提供的系统调用对应。一个API定义了一组应用程序使用的编程接口。它们可以实现成一个系统调用,也可以通过调用多个系统调用来实现,即使不使用任何系统调用也不存在问题。实际上,API可以在各种不同的操作系统上实现,给应用程序提供完全相同的接口,而它们本身在这些系统上的实现却可能迥异。

       在Unix世界中,最流行的应用编程接口是基于POSIX标准的,Linux是与POSIX兼容的。

       从程序员的角度看,他们只需要给API打交道就可以了,而内核只跟系统调用打交道;库函数及应用程序是怎么使用系统调用不是内核关心的。

       系统调用(在linux中常称作syscalls)通常通过函数进行调用。它们通常都需要定义一个或几个参数(输入)而且可能产生一些副作用。这些副作用通过一个long类型的返回值来表示成功(0值)或者错误(负值)。在系统调用出现错误的时候会把错误码写入errno全局变量。通过调用perror()函数,可以把该变量翻译成用户可以理解的错误字符串。

       系统调用的实现有两个特别之处:

       1)函数声明中都有asmlinkage限定词,用于通知编译器仅从栈中提取该函数的参数。

       2)系统调用getXXX()在内核中被定义为sys_getXXX()。这是Linux中所有系统调用都应该遵守的命名规则。

       系统调用号:在linux中,每个系统调用都赋予一个系统调用号,通过这个独一无二的号就可以关联系统调用。当用户空间的进程执行一个系统调用的时候,这个系统调用号就被用来指明到底要执行哪个系统调用;进程不会提及系统调用的名称。系统调用号一旦分配就不能再有任何变更(否则编译好的应用程序就会崩溃),如果一个系统调用被删除,它所占用的系统调用号也不允许被回收利用。Linux有一个"未使用"系统调用sys_ni_syscall(),它除了返回-ENOSYS外不做任何其他工作,这个错误号就是专门针对无效的系统调用而设的。虽然很罕见,但如果有一个系统调用被删除,这个函数就要负责“填补空位”。

       内核记录了系统调用表中所有已注册过的系统调用的列表,存储在sys_call_table中。它与体系结构有关,一般在entry.s中定义。这个表中为每一个有效的系统调用指定了唯一的系统调用号。

       用户空间的程序无法直接执行内核代码。它们不能直接调用内核空间的函数,因为内核驻留在受保护的地址空间上,应用程序应该以某种方式通知系统,告诉内核自己需要执行一个系统调用,系统系统切换到内核态,这样内核就可以代表应用程序来执行该系统调用了。这种通知内核的机制是通过软中断实现的。x86系统上的软中断由int$0x80指令产生。这条指令会触发一个异常导致系统切换到内核态并执行第128号异常处理程序,而该程序正是系统调用处理程序,名字叫system_call().它与硬件体系结构紧密相关,通常在entry.s文件中通过汇编语言编写。

       所有的系统调用陷入内核的方式都是一样的,所以仅仅是陷入内核空间是不够的。因此必须把系统调用号一并传给内核。在x86上,这个传递动作是通过在触发软中断前把调用号装入eax寄存器实现的。这样系统调用处理程序一旦运行,就可以从eax中得到数据。上述所说的system_call()通过将给定的系统调用号与NR_syscalls做比较来检查其有效性。如果它大于或者等于NR_syscalls,该函数就返回-ENOSYS.否则,就执行相应的系统调用:call *sys_call_table(, %eax, 4);

       由于系统调用表中的表项是以32位(4字节)类型存放的,所以内核需要将给定的系统调用号乘以4,然后用所得到的结果在该表中查询器位置。如图图一所示:

                                      结构 

     上面已经提到,除了系统调用号以外,还需要一些外部的参数输入。最简单的办法就是像传递系统调用号一样把这些参数也存放在寄存器里。在x86系统上ebx,ecx,edx,esi和edi按照顺序存放前5个参数。需要六个或六个以上参数的情况不多见,此时,应该用一个单独的寄存器存放指向所有这些参数在用户空间地址的指针。给用户空间的返回值也通过寄存器传递。在x86系统上,它存放在eax寄存器中。

       系统调用必须仔细检查它们所有的参数是否合法有效。系统调用在内核空间执行。如果任由用户将不合法的输入传递给内核,那么系统的安全和稳定将面临极大的考验。最重要的一种检查就是检查用户提供的指针是否有效,内核在接收一个用户空间的指针之前,内核必须要保证:

1)指针指向的内存区域属于用户空间
2)指针指向的内存区域在进程的地址空间里
3)如果是读,读内存应该标记为可读。如果是写,该内存应该标记为可写。

       内核提供了两种方法来完成必须的检查和内核空间与用户空间之间数据的来回拷贝。这两个方法必须有一个被调用。

copy_to_user():向用户空间写入数据,需要3个参数。第一个参数是进程空间中的目的内存地址。第二个是内核空间内的源地址。第三个是需要拷贝的数据长度(字节数)。
copy_from_user():向用户空间读取数据,需要3个参数。第一个参数是进程空间中的目的内存地址。第二个是内核空间内的源地址.第三个是需要拷贝的数据长度(字节数)。
注意:这两个都有可能引起阻塞。当包含用户数据的页被换出到硬盘上而不是在物理内存上的时候,这种情况就会发生。此时,进程就会休眠,直到缺页处理程序将该页从硬盘重新换回到物理内存。

       内核在执行系统调用的时候处于进程上下文,current指针指向当前任务,即引发系统调用的那个进程。在进程上下文中,内核可以休眠(比如在系统调用阻塞或显式调用schedule()的时候)并且可以被抢占。当系统调用返回的时候,控制权仍然在system_call()中,它最终会负责切换到用户空间并让用户进程继续执行下去。

       给linux添加一个系统调用时间很简单的事情,怎么设计和实现一个系统调用是难题所在。实现系统调用的第一步是决定它的用途,这个用途是明确且唯一的,不要尝试编写多用途的系统调用。ioctl则是一个反面教材。新系统调用的参数,返回值和错误码该是什么,这些都很关键。一旦一个系统调用编写完成后,把它注册成为一个正式的系统调用是件琐碎的工作,一般下面几步:

1)在系统调用表(一般位于entry.s)的最后加入一个表项。从0开始算起,系统表项在该表中的位置就是它的系统调用号。如第10个系统调用分配到系统调用号为9。
2)任何体系结构,系统调用号都必须定义于include/asm/unistd.h中
3)系统调用必须被编译进内核映像(不能编译成模块)。这只要把它放进kernel/下的一个相关文件就可以。

      

        用户的程序无法直接执行内核代码。他们不能直接调用内核的函数,因为内核驻留在受保护的地址空间。所以应用程序应该通过某种方式通知内核,告诉内核自己需要执行一个系统调用,希望系统切换到内核态,这样内核就可以代表应用程序来执行该系统调用了。

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

       通常,系统调用靠C库支持,用户程序通过包含标准头文件并和C库链接,就可以使用系统调用(或者使用库函数,再由库函数实际调用)。庆幸的是linux本身提供了一组宏用于直接对系统调用进行访问。它会设置好寄存器并调用int $0x80指令。这些宏是_syscalln(),其中n的范围是从0到6.代表需要传递给系统调用的参数个数。这是由于该宏必须了解到底有多少参数按照什么次序压入寄存器。以open系统调用为例:

open()系统调用定义如下是:
long open(const char *filename, int flags, int mode)
直接调用此系统调用的宏的形式为:
#define NR_open 5
_syscall3(long, open, const char *, filename, int , flags, int, mode)

    这样,应用程序就可以直接使用open().调用open()系统调用直接把上面的宏放置在应用程序中就可以了。对于每个宏来说,都有2+2*n个参数。每个参数的意义简单明了,这里就不详细说明了。





QCustomPlot实现毫秒级时间轴数据的动态可视化与实时刷新优化 本文深入探讨了如何利用QCustomPlot库高效实现毫秒级时间轴数据的动态可视化与实时刷新。文章从基础配置讲起,详细介绍了时间轴初始化、数据平滑滚动、增量更新与内存管理等核心优化技巧,并分享了应对高频数据的缓冲策略及OpenGL硬件加速等高级优化手段,旨在解决实时图表卡顿问题,提升流畅度。 阅读详情

相关推荐

FDTD材料nk值拟合优化指南:利用材料资源管理器提升光学模型精度

本文详细介绍了如何利用FDTD仿真软件中的材料资源管理器,对材料nk值进行精确拟合与优化,从而提升光学模型的仿真精度。文章通过实战案例,解析了拟合参数调整、报告解读以及针对varFDTD求解器的特殊注意事项,帮助用户从根本上解决仿真结果不准的常见问题。

weixin_29196891的博客 353

【Linux】Linux系统调用

>- **操作系统**——管理计算机硬件与软件资源的软件,是用户和系统交互的操作接口,为它上面运行的程序提供服务。 >- **操作系统内核**——操作系统的内核,负责管理系统的进程、内存、设备驱动程序、文件和网络系统。一个内核不是一套完整的操作系统。例如Linux。 >- **Linux操作系统**——基于Linux内核的操作系统。通常由Linux内核、shell(特殊的应用程序,提供运行其他程序的接口)、文件系统和应用程序组成。常见的有:Redhat、Fedora、Centos、Ubuntu和Androi

半生瓜のblog 4623

概率论与数理统计基础概念与重要定义汇总

文章目录一、随机事件和概率1:互斥,对立,独立事件的定义和性质。2:概率,条件概率和五大概率公式3:古典型,几何型概率和伯努利试验 一、随机事件和概率 1:互斥,对立,独立事件的定义和性质。 互斥事件\color{red}\textbf{互斥事件}互斥事件 事件A和B的交集为空,A与B就是互斥事件,也叫互不相容事件。也可叙述为:不可能同时发生的事件。如A∩B为不可能事件(A∩B=Φ),那么称事件A与事件B互斥,其含义是:事件A与事件B在任何一次试验中不会同时发生。 则P(A+B)=P(A)+P(B)(这个公

csyifanZhang的博客 1万+

linux中的系统调用

前言:本文只讨论linux中的系统调用,不考虑windows等其他操作系统。 两个问题: 1.系统调用时,进程调用的是进程吗? 答:进程调用的是操作系统的内核函数,不是进程。 2.系统调用时,会出现上下文切换吗? 答:会出现上下文切换,但和进程调度时的上下文切换还是有区别的。 早期,内存使用的是哈佛结构,即程序和数据分开存储。到了现代,内存使用的是冯诺依曼结构,即程序和数据存储在一起。 在linux中,内存又被分为两部分:内核部分和进程部分。内核部分归操作系统内核使用,进程部分归进程使用。 出于安全考虑,进

u011159820的博客 5333

I-Cache 和 D-Cache

I-Cache 和 D-Cache

liuyuanbin9001 7023

汽车零部件智能装配:C#+YOLOv8实现螺栓漏装检测与齿轮错位识别(附PLC通信与机械臂控制)

YOLOv8:小目标检测的最优解相比YOLOv7,YOLOv8的C2f特征融合网络对小目标(5-10mm螺栓)检测精度提升12%,且推理速度快8%;支持大输入尺寸(不显著增加耗时),可放大螺栓细节;官方提供yolov8n.pt(nano版),在边缘计算盒上能跑40+FPS,满足实时性。C#:工业软件的“兼容性核心”主流PLC(西门子S7-1200/1500)、机械臂(ABB、KUKA)的SDK多基于.NET开发,C#可直接调用,避免跨语言通信延迟;多线程管理成熟(Task。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1146

Linux--系统调用流程

在Linux中,每个进程都有一个私有的内核栈,当从用户栈切换到内核栈时,需完成保存%esp以及相关寄存器的值(%ebx,%ecx…Linux中,在用户态和内核态运行的进程使用的栈是不同的,分别叫做用户栈和内核栈, 两者各自负责相应特权级别状态下的函数调用。当进行系统调用时,进程不仅要从用户态切换到内核态,同时也要完成栈切换, 这样处于内核态的系统调用才能在内核栈上完成调用。计算机的各种硬件资源是有限的,为了更好的管理这些资源,用户进程是不允许直接操作的,所有对这些资源的访问都必须由操作系统控制。

qq_47258284的博客 2470

【Network Management】DCM模块唤醒网络是主动唤醒还是被动唤醒

DCM模块唤醒网络是主动唤醒还是被动唤醒

qq_36056498的博客 1539

Linux操作系统原理-系统调用理论详解

系统调用是一种特殊的函数调用,用于让用户空间的应用程序请求内核执行某些特权操作,例如文件操作、进程管理、网络通信等。系统调用是用户程序与操作系统内核之间的桥梁,它们允许用户程序访问底层硬件和操作系统提供的服务。

sinat_41393249的博客 1114

使用 MATLAB/Simulink + Simscape Electrical + Simulink Design Optimization,构建一个基于SiC/GaN的Z源逆变器在储能系统中的软启

《手把手教你学Simulink:Z源逆变器在储能系统中的应用》摘要 本文详细介绍了使用MATLAB/Simulink构建Z源逆变器储能系统仿真模型的全过程。Z源逆变器凭借其独特的阻抗网络结构,解决了传统逆变器在直通保护和升压能力方面的痛点。文章通过6个关键步骤:主电路搭建、调制策略设计、软启动实现、仿真分析、效率对比和工程问题解决方案,完整展示了Z源逆变器从理论到仿真的实现路径。重点讲解了直通零矢量SPWM调制策略和渐进式升压比控制方法,验证了系统93.3%的效率和优异的抗扰性能。该模型为光伏储能、电动汽车

MHD0815的博客 122

手把手教你学Simulink--基于飞行控制与稳定性的场景实例:固定翼无人机的自动起飞与降落控制

本文介绍了使用Simulink对固定翼无人机自动起飞与降落控制系统进行建模与仿真的完整流程。首先构建了包含飞行器动力学模型、控制系统、环境模拟等模块的系统结构,详细阐述了简化动力学方程的推导和实现。重点讲解了PID控制器设计,包括起飞阶段的速度控制和降落阶段的高度控制策略。通过添加环境干扰和输入信号,建立了完整的仿真模型,并利用输出显示模块评估系统性能。该实例为无人机自主控制系统的开发提供了有效的仿真验证方法,有助于优化参数提高飞行稳定性。

MHD0815的博客 4310

学了这么久的Linux系统调用你知道多少?

Linux系统中, 用户程序可以通过系统调用接口请求内核提供服务,这些服务可能会修改硬件状态,管理文件系统,或者对进程进行同步等操作。用户程序在执行过程中,如果需要使用系统调用,可以通过内置的系统库或者直接使用系统调用的接口函数。系统调用的触发是在用户程序中进行的,当用户程序调用系统实用程序接口时,就会触发系统调用。在常见的情况下,系统调用接口的使用情景包括以下几种:访问系统资源:例如访问硬件设备,管理设备驱动程序,或者配置网络协议等操作,都需要使用系统调用接口发起请求。

leah126的博客 1227

ONVIF协议简介与协议测试工具使用详解

Onvif协议及协议测试工具使用详解

dvlinker的技术专栏 3万+

java使用linux系统调用_Linux系统调用的运行过程

在Linux中,系统调用是用户空间访问内核的唯一手段,它们是内核唯一的合法入口。一般情况下,应用程序通过应用编程接口(API)而不是直接通过系统调用来编程,而且这种编程接口实际上并不需要和内核提供的系统调用对应。一个API定义了一组应用程序使用的编程接口。它们可以实现成一个系统调用,也可以通过调用多个系统调用来实现,即使不使用任何系统调用也不存在问题。实际上,API可以在各种不同的操作系统上实现,...

weixin_31463457的博客 334

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Linux系统调用的运行过程【转】

本文转自:http://blog.youkuaiyun.com/kernel_learner/article/details/7331505 在Linux中,系统调用是用户空间访问内核的唯一手段,它们是内核唯一的合法入口。 一般情况下,应用程序通过应用编程接口(API)而不是直接通过系统调用来编程,而且这种编程接口实际上并不需要和内核提供的系统调用对应...

weixin_34273481的博客 95

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

工业级隔离SPI通信链路设计:MAX14431BAEE+与MKV42F64VLH16实战

SPI总线作为嵌入式系统中常见的板级通信接口,在跨供电域或强干扰的工业场景下常因地电位差导致通信失败。其原理在于信号参考本地地电位,缺乏电气隔离时共模干扰会引发数据错误甚至器件损坏。通过数字隔离器实现信号隔离,并配合独立隔离供电,可显著提升链路可靠性,广泛应用于工业数据采集、多节点传感器网络等场景。本文以MAX14431BAEE+和MKV42F64VLH16为例,详解隔离SPI的选型、硬件设计、软件配置及调试要点,帮助工程师构建稳定的工业通信链路。

weixin_33778544的博客 257

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

linux下C程序运行过程中的系统调用

首先我们先写一个最最简单的程序,helloworld?no,no,helloworld远远比我们自己看到的要复杂的多。 最最简单的程序应该是这样的 /*kong.c源码*/intmain(void){} 接下来,静态编译,strace跟踪查看程序的执行情况。 leon@leon-virtual-machine:~/Desktop/hello...

weixin_34129145的博客 333

[LINUX]使用strace工具抓取程序运行过程中详细系统调用日志

使用strace工具抓取程序运行过程中详细系统调用日志 方法: strace -f -F -ttt -v -s 5000 -o strace.log sh target 说明: -f 递归的监控所有子进程的系统调用; -ttt 日志每一行打印精确到微秒的时间戳 -v 打印系统调用的参数信息 -s 5000 设置每一行字符串最大长度 -o 输出文件名称 可以通过man strace查看参数说明...

小蜗牛之家 967

Linux添加系统调用

Linux添加系统调用 前提知识(系统调用如何执行) 先看文章 裁剪Linux内核,用qemu进行调试 我们通常写的c,有相对应的开源的标准库glibc,(2.23的glibc中还是有很多缺陷的)其中的头文件unistd.h就包含了许多的系统调用,如read/write/open等等 系统调用是通过的修改寄存器eax的值,然后通过触发 软中断使系统进入内核空间,比如32位下经典的int 80以及64位的syscall。如果你想更清楚的了解系统调用可以查看我之前写的 ret2syscall 。 所以内核

huzai9527的博客 705

linux 添加系统调用的方法(arm架构)

在linux中,系统调用是非常重要的一个机制。本文首先探讨了系统调用需要哪些文件的支持,之后讨论如何增加自己的系统调用。

tmkeepgood的专栏 2982

详解系统调用过程

用户运行库函数(系统调用的封装),函数里面其实是执行的int 0x80指令。系统调用先把系统调用号保存在eax寄存器中,然后执行int0x80指令。int 0x80指令先进行切换堆栈(找到进程的堆栈,将寄存器值压入到内核栈中,将esp,ss设置成对应内核栈的值),查找相应中断向量的中断处理程序(system_call)并调用,随后system_call 从系统调用表中找到相应的系统调用进行调用,调用结束后从system_call中返回。

叫好与叫座虽然不是对立面,但想在同一个作品中达到双重效果很难。 1433

linux有没有系统调用功能,Linux下系统调用的实现

Unix/Linux操作系统的体系结构及系统调用介绍什么是操作系统和系统调用操作系统是从硬件抽象出来的虚拟机,在该虚拟机上用户可以运行应用程序。它负责直接与硬件交互,向用户程序提供公共服务,并使它们同硬件特性隔离。因为程序不应该依赖于下层的硬件,只有这样应用程序才能很方便的在各种不同的Unix系统之间移动。系统调用是Unix/Linux操作系统向用户程序提供支持的接口,通过这些接口应用程序向操作系...

weixin_32075843的博客 295

Linux下系统调用的实现

http://hi.baidu.com/xydjh/blog/item/c461c135d1806d8fa61e12bb.html Unix/Linux操作系统的体系结构及系统调用介绍 什么是操作系统和系统调用     操作系统是从硬件抽象出来的虚拟机,在该虚拟机上用户可

WINGCREATE的专栏 1545
上一篇: Linux系统调用简介
下一篇: linux中断处理中的tasklet机制
kernel_learner
博客等级 码龄15年 60粉丝 16原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值