《ARM与Linux些许问题》第四章:ARM平台系统调用原理分析

发布者:EternalSunset最新更新时间:2016-06-24 来源: eefocus关键字:ARM  Linux  系统调用原理 手机看文章 扫描二维码
随时随地手机看文章
本文基于mstar801平台Linux2.6.35.11版本。

首先说明:系统调用不会导致进程上下文切换。

一、介绍系统调用——Linux用户空间主动进入内核空间的唯一方法

    1.系统调用是操作系统提供给用户程序调用的一组“特殊”接口;用户程序可以通过这组“特殊”接口来获得操作系统内核提供的服务。

       从逻辑上来说,系统调用可被看成是一个内核与用户空间程序交互的接口;把用户进程的请求传达给内核,待内核把请求处理完毕后再将处理结果送回给用户空间。

    2.系统调用按照功能逻辑大致可分为“进程控制”、“文件系统控制”、“系统控制”、“存储管理”、“网络管理”、“socket控制”、“用户管理”和“进程间通信”几类。

    3.内核接口:kernel2.6.35.11/arch/arm/include/asm/unistd.h

二、系统调用的主要用途

    1.控制硬件——系统调用往往作为硬件资源和用户空间的抽象接口,比如读写文件时用到的write/read调用。

    2.设置系统状态或读取内核数据——因为系统调用是用户空间和内核的唯一通讯手段,所以用户设置系统状态、比如开/关某项内核服务(设置某个内核变量)或读取内核数据都必须通过系统调用。比如getpid、getpriority、setpriority和sethostname等。

    3.进程管理——系统调用接口用来保证系统中进程能以多任务在虚拟内存环境下运行。比如fork、clone、execve和exit等。

三、内核函数和系统调用、用户编程接口(API)、系统命令的关系

    1.系统调用并非直接和程序员或系统管理员打交道,它仅仅是一个通过软中断机制向内核提交请求、获取内核服务的接口。而在实际使用中程序员调用的多是用户编程接口——api,而管理员使用的则多是系统命令。

    2.用户编程接口(API)其实是一个函数定义,说明了如何获得一个给定的服务,比如read()、malloc()、free()、abs()等。

       它有可能和系统调用形式一致,比如read()接口就和read系统调用一一对应;

       往往会出现几种不同的API内部用到同一个系统调用,比如malloc()、free()内部利用brk()系统调用来扩大或缩小进程的堆;

       或一个API利用了好几个系统调用组合来完成任务;

       更有些API甚至不需要任何系统调用,因为它不需要内核服务、如计算整数绝对值的abs()接口。

       Linux系统中这些API主要是通过C库(libc)实现的;它除了定义的一些标准的C函数外,一个重要的任务是提供了一套封装例程、将系统调用在用户空间包装后供用户编程使用。

       说明:上述封装并非必须;如果你愿意直接调用,Linux提供了一个syscall()的系统调用函数来实现调用。

    3.系统命令相对编程接口更高了一层,它是内部引用API的可执行程序,比如我们常用的系统命令ls、hostname等。

三、内核函数和系统调用的关系

    内核函数没有想像中那么复杂;它们和普通函数很像、只不过在内核实现,因此要满足一些内核编程的要求。

    系统调用是一层用户进入内核的接口,它本身并非内核函数;进入内核后,不同的系统调用会找到对应到各自的内核函数——专业术语叫:系统调用服务例程。

    总结:从用户角度向内核看;依次是系统命令、编程接口、系统调用和内核函数。
四、系统调用的实现

    系统调用利用了ARM体系结构中的软件中断,软件中断和我们常说的中断(硬件中断)不同之处在于———它是通过软件指令触发而并非外设,也就是说由编程人员发出的一种异常;具体地讲就是调用SWI汇编指令(x86上int $0x80),这条汇编指令将产生向量为128的编程异常,ARM从用户模式切入管理模式、并强制R15-PC(程序计数器)为0x0000 0008,Linux从用户态进入内核态。见:《ARM与Linux些许问题》第一章:ARM工作模式

    之所以系统调用需要借助异常实现;是因为当用户态的进程调用一个系统调用时,CPU便被切换到内核态执行内核函数。我们前边分析ARM体系结构部分已经讲过进入内核态——ARM高特权模式,必须经过系统的门机制——异常(SWI汇编指令(x86上int $0x80等);其他异常用户空间无法利用,都是由内核使用的。)。

    1.SWI汇编指令(x86上int $0x80)指令的目的是产生一个编号为128的编程异常,这个编程异常对应中断描述符表IDT中的第128项——也就是对应的系统门描述符。门描述符中含有一个预设的内核空间地址,它指向了系统调用处理程序:vector_SWI()(x86上system_call())。注意:不是系统调用服务程序本身。

    即:系统命令——>用户编程API——>系统调用(调用SWI汇编指令异常)——>系统调用处理函数(vector_SWI)——>具体的系统调用服务程序。其中蓝色部分是内核态函数。

    2.所有的用户空间系统调用函数都是通过调用SWI汇编指令(x86上int $0x80)异常、进入内核态,此时、ARM默认从某一固定地址执行程序(vector_SWI()(x86上system_call())的地址)。vector_SWI()(x86上system_call())这个内核函数又怎样分发这些系统调用到各自的内核服务程序中呢?Linux为每个系统调用都进行了编号(0——_NR_syscall);同时在内核中保存一张系统调用表,该表中保存了系统调用编号和其对应的服务例程。因此,在系统调用通过门陷入内核前,需要把系统调用号一并传入内核。这个传递工作是通过把系统调用号装入相应寄存器实现的。

    有了如上的分析:系统调用处理程序vector_SWI()(x86上system_call())一旦运行;就可以从相应寄存器中得到数据,然后再去系统调用表中寻找相应的服务例程了。

    注意:除了系统调用号之外,有的系统调用还需要传递一些参数给内核;这是Linux在vector_SWI()(x86上system_call())调用时将参数等值传入其他寄存器。

    内核系统服务例程结束时,system_call()从相应寄存器中获得系统调用返回值,并把这个返回值放在曾保存用户态相应寄存器栈单元的那个位置;然后跳转到ret_from_sys_call(),终止系统调用处理程序的执行。

====================================================================================================================================

五、主要路径

1.用户空间:libc库没有研究代码,大体机制如下——

                       调用SWI汇编指令(x86上int $0x80))软中断进入内核,并传入中断向量号

                       相关中断向量号arm-2010.09/arm-none-linux-gnueabi/libc/usr/include/bits/syscall.h

                           #define SYS_getuid __NR_getuid

2.内核空间:ARM中系统调用号定义路径:kernel2.6.35.11/arch/arm/include/asm/unistd.h
                           #define __NR_getuid         (__NR_SYSCALL_BASE+ 24)  

                      异常进入内核空间函数路径:kernel2.6.35.11/arch/arm/kernel/entry-common.s

                          默认执行vector_SWI(x86上system_call())函数                       

                       ARM中系统调用表定义路径:kernel2.6.35.11/arch/arm/kernel/calls.S 

                           CALL(sys_getuid)           //第24个,要与前面unistd中对应

                       ARM中系统调用服务程序的声明路径:kernel2.6.35.11/include/linux/syscalls.h

                           asmlinkage long sys_getuid(void);

====================================================================================================================================

x86平台相关路径(内核):

    系统调用号路径——kernel2.6.35.11/arch/x86/include/asm/unistd.h

    system_call()函数路径——kernel2.6.35.11/arch/x86/kernel/entry.S

    系统调用表路径——kernel2.6.35.11/arch/x86/kernel/syscall_table.S或直接在entry.S中定义
关键字:ARM  Linux  系统调用原理 引用地址:《ARM与Linux些许问题》第四章:ARM平台系统调用原理分析

上一篇:ARM体系的7种工作模式
下一篇:《ARM与Linux些许问题》第三章:Linux如何从用户态进入内核态

推荐阅读最新更新时间:2024-03-16 14:58

arm gnu 汇编语法
尽管在Linux下使用C或C++编写程序很方便,但汇编源程序用于系统最基本的初始化,如初始化堆栈指针、设置页表、操作ARM的协处理器等。初始化完成后就可以跳转到C代码执行。需要注意的是,GNU的汇编器遵循AT&T的汇编语法,可以从GNU的站点(www.gnu.org)上下载有关规范。 一. Linux汇编行结构 任何汇编行都是如下结构: ]] 每一个段以段名为开始, 以下一个段名或者文件结尾为结束。这些段都有缺省的标志(flags),连接器可以识别这些标志。(与armasm中的AREA相同)。 下面是ELF格式允许的段标志 标志 含义 a 允许段 w 可写段 x 执行段 定义段 .section .my
[单片机]
[初级教程]arm-linux裸机开发之-bootstrap.bin的实现
1.前言 我们知道,在Linux平台下编写的程序要想在arm平台上运行,我们就得使用交叉的编译器,我们用arm-linux-none-gnueabi-gcc 或者arm-linux-gcc也罢,这些编译器编译产生的程序能够直接运行在arm的平台上,那我们的bootstrap.bin自己来实现,都需要具备哪些文件呢?众所周知,在引导程序中当今做大的最大的莫过于U-Boot这个组织,今天,我们就模仿U-Boot来实现一个简易的引导程序,我们称之为Bootstrap.bin。实现该bin文件我们模仿U-Boot的工程模版,写出几个实现文件: start.S 我们知道汇编指令的代码在机器上执行的速度比较快,那些短小精悍的程序往往运行在
[单片机]
[初级教程]<font color='red'>arm</font>-<font color='red'>linux</font>裸机开发之-bootstrap.bin的实现
从最简单的例子,带你轻松学习ARM指令集
首先编辑一个最简单的函数,包含变量分配及初始化:test1.c 1. #include 2. 3. void main() 4. { 5. int d = 4; 6. } 然后编译: arm - linux -gnueabihf-gcc test.c -o test1 然后看看汇编代码:arm-linux-gnueabihf-objdump -D test1;每一句的含义我已经给出详细注释。 首先对输出的文件格式说明,对于如下的输出,左边是程序地址(各种函数地址等等),第二列是指令码的十六进制表示也俗称机器码,剩下的就是给人类看的指令助记符号,举例举例: 835c: b480 push {
[单片机]
从最简单的例子,带你轻松学习<font color='red'>ARM</font>指令集
采用ARM嵌入式微处理器的VGA显示技术分析
目前很多SOC厂商的微处理器芯片都集成了LCD控制器,如三星公司的S3C2410.S3C2440,Intel的Xscale系列等。大多数嵌入式系统也采用流行的LCD显示技术。但是在需要大屏幕显示、对分辨率要求不高的场合,如车间、厂房,采用大屏幕LCD则成本过高。另一方面,VGA显示技术因为技术发展成熟,成本低廉,仍在被大量使用,直到今天它仍是所有显示终端最为成熟的标准接口。如果让嵌入式处理器直接支持VGA显示器,则能很大地利用现有资源,节约系统成本。 1 基于S3C2440的VGA显示技术分析 通过分析VGA显示技术的时序逻辑与S3C2440内部集成LCD控制器驱动TFT LCD的时序逻辑,找出它们的共同点,分析在S3C244
[单片机]
采用<font color='red'>ARM</font>嵌入式微处理器的VGA显示技术分析
采用ARM/FPGA主从处理器的嵌入式采集系统设计
随着人们对高空的兴趣发展和研究需要,越来越多的科学实验被科研人员搬到了空中进行,气球探空和无人机实验是比较典型的方法。这些科学实验往往需要在一定的实验条件到达时触发某特定实验现象,从而对发生时间非常短促且不具备可重复再现性的实验目标数据进行高速采集。日前,笔者参与的项目中需要完成的任务是:通过无线通信实现对高空实验设备进行控制,对整个实验过程进行实时观察分析(其中的实验条件数据通过GPS接收机,红外虚拟逻辑分析仪等设备实时采集),待实验到达触发条件时,通过手动(或自动可选)的方法实施触发,再对触发后的实验目标数据进行采集并传回地面PC进行后续的分析处理。该项目采用ARM和FPGA分别作为主从处理器设计嵌入式采集系统,采用多通道A/
[单片机]
采用<font color='red'>ARM</font>/FPGA主从处理器的嵌入式采集<font color='red'>系统</font>设计
基于嵌入式Linux的倒车影音系统设计
引言 电子信息与数字图像处理技术目前已被广泛地应用在各个领域,车载系统的信息化已成为现代汽车业的重要标志。现在的倒车雷达系统可以为驾驶者提供许多帮助,多数采用超声波测距技术,可以直接显示出车尾与障碍物之间的距离。但由于超声波的散射特性,如果地面有尖锐的突起或存在横在半空的棱角状物体,系统就不能有效地“察觉”。假如能为现有的倒车系统增加一个可视功能,那么驾驶员在倒车时不必回头就可清楚车后的情况。本文设计了一种可视化安全倒车系统,该系统采用嵌入式Linux操作系统内核驱动USB摄像头实现车后状况实时监控,通过判断超声波测距是否达到阈值来启动语音报警功能。 1 系统方案设计 如图1所示,系统由主控模块、超声波收发模块、USB摄像头图像采
[嵌入式]
linux 调试之lrz的移植与一些说明
开发板:RT5350 编译器:mipsel-linux-gcc ( 如果是arm平台和arm_linux的话,请参照修改即可) 1.获取源码:lrzsz-0.12.20.tar.gz 2. 解压: tar–xvf lrzsz-0.12.20.tar.gz 3.添加配置参数: vi mipsel-linux.cache (默认下没有这个文件,因为新建这个文件并打开,添加以下内容) 添加内容: ac_cv_prog_CC=${ac_cv_prog_CC=/opt/buildroot-gcc342/bin/mipsel-linux-gcc'} 备注一下: /opt/buildroot-gcc342/bin是mipse-l
[单片机]
<font color='red'>linux</font> 调试之lrz的移植与一些说明
ARM物联网事业部策略副总裁:mbed平台催化物联网发展
安谋国际(ARM)mbed平台再添新开发资源。继支援无线区域网路(Wi-Fi)、蓝牙(Bluetooth)、全球卫星定位系统(GPS)等无线通讯技术之后,安谋国际针对物联网(IoT)发布的开发平台mbed将再增加ZigBee网际网路通讯协定(IP),助力系统开发商弹性于装置中配备更多无线技术,以提高产品的附加价值。 安谋国际物联网事业部策略副总裁Kerry McGuire表示,尽管ZigBee为发展物联网的重要无线通讯技术,然目前市场规模较Wi-Fi与蓝牙受限,因此初期mbed平台并未优先加入。 安谋国际物联网事业部策略副总裁Kerry McGuire表示,随着mbed平台支援更多无线通讯技术,将可提供客户更多产
[物联网]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved