linux系统调用理解之摘录(1)

写在前面:出于对系统调用这一块知识的疑惑,先从网上摘录处一些经典的讲解。


操作系统负责资源管理,当应用层需要使用系统资源时,就会向内核发起系统调用。如:读取文件时发起syscall_read系统调用;建立socket时,发起syscall_socket系统调用等等;

(1)能够触发内核响应的三种操作:

内核在完成引导后,就一直处于等待各种请求的状态,以便做出响应从而实现对硬件资源的管理。

1.系统调用:基于软件中断机制(简称为“软中断”)实现,应用层对内核层发起的请求;

2.异常:如缺页异常,使虚拟地址分配到物理空间;

3.中断:一般为硬件状态改变引起内核响应,如usb设备插入等;

本文主要介绍系统调用,它是由软中断实现的。

1.首先,用户程序为系统调用设置参数。其中一个参数是系统调用编号;

2.参数设置完成后,程序执行“系统调用”指令(这是一个特殊的机器指令);在x86平台上的软中断是由int指令产生的。(不明白?);

3.系统调用指令会产生一个异常:产生一个事件,这个事件首先会导致处理器进行状态切换:用户态——>系统态(或称为内核态),然后跳转到一个新的地址执行异常处理程序,这个程序就是“系统调用处理程序”。


(2)内核空间中的实现

在linux中,每个系统调用都有一个对应的系统调用号

当用户程序的进程执行一个系统调用时,这个系统调用号就是用来指明到底要执行哪一个系统调用。

(2.2)所有系统调用陷入内核的方式都是一样的,所以仅仅是陷入内核空间是不够的。

因此必须将系统调用号一并传给内核。

在x86上,系统调用号是通过eax寄存器传递给内核的。在陷入内核之前,用户空间就将系统调用号一并传给eax中了。这样系统调用处理程序一旦运行,就可以从eax中得到数据。arm中也是类似操作。

(2.3)

除了系统调用号,一般系统调用还需要传递一些输入参数。系统调用时,也需要把这些参数传递给内核。

最简单的方式:如传递系统调用号一样,将这些参数先存在寄存器中;x86上,ebx,ecx,edx,esi,edi按顺序存放前五个外部输入参数。

如果需要传递的参数多于六个时,可以使用一个单独的寄存器来指向存放所有这些参数在用户空间地址的指针。

(2.4)

内核记录了系统调用表中的所有已注册的系统调用,保存在sys_call_table中。

它与体系结构有关,一般在entry.s中定义。

它是一张由指向实现各种系统调用的内核函数的函数指针组成的表。


用户空间的实现:

linux下三种关系发生系统调用的方法:

1.通过glibc提供的库函数

glibc是Linux下使用的开源的标准C库,它是GNU发布的libc库。glibc为程序员提供丰富的API,出了例如字符串处理,数学运算等用户服务外,最重要的是封装了操作系统提供的系统服务,即系统调用的封装。

好处:封装好的系统调用以API形成存在,容易理解,用户不需要知道更多的内部细节,比如chmod系统调用,我们只需要知道它的作用,不需要知道它的内部实现原理。

同时,使用API形式的系统调用,具有更好的可移植性,glibc方便移植;即使采用的不是glibc的c函数库,也只需要进行少量的修改;

2.使用syscall直接调用

glibc中没有进行封装的系统调用,比如用户私自增加的一个系统调用,这时候就需要利用glibc提供过的syscall函数直接调用(值得深入研究)

3.通过int指令陷入

实际上,用户程序通过软中断指令 int 0x80 来陷入内核态(在Intel Pentium II中又引入了sysenter指令),参数的传递是通过寄存器,eax 传递的是系统调用号,ebx、ecx、edx、esi和edi 来依次传递最多五个参数;

当系统调用返回时,返回值会存在eax中。

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值