Linux系统调用. 复习总结

在现代操作系统中,内核提供了用户进程与内核交互的一组接口。这些接口让应用程序受限的访问硬件设备,提供了创建新进程并于已有进程通信的机制,也提供了申请操作系统其他资源的能力。实际上提供这些接口主要是为了保证系统稳定可靠,避免应用程序恣意妄为。

1. 用户态与内核的交互

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

  1. 它为用户空间提供了一种硬件的抽象接口。例如:在读取文件的额时候,应用程序不用去管磁盘类型和介质,甚至不用管文件所在的文件系统到底是哪种类型。
  2. 系统调用保证了系统的稳定和安全性。作为硬件设备和应用程序之间的中间人,内核可以基于权限、用户类型和其他一些规则对需要进行的访问进行裁决。例如:这样可以避免应用程序不正确的使用设备,窃取其他进程的资源,或做出其他危害系统的事情。
  3. 为了实现多任务和虚拟内存。每个进程运行在虚拟系统中,而在用户空间和系统的其余部分提供这样一层接口,也是出于这种考虑。如果应用程序可以随意访问硬件而内核内核对此一无所知的话,几乎就没办法实现多任务和虚拟内存,当然也不可能实现良好的稳定性和安全性。

在linux系统中,系统调用是用户空间访问内核的唯一手段,除异样和陷入外,它们是内核的唯一合法入口。实际上,其他的象设备文件和/proc之类的方式,最终还是通过系统调用进行访问的。

2. API、POSIX、和C库 

一般情况下,应用程序通过在用户空间实现的应用编程接口(API)而不是直接通过系统调用来编程。这点很重要,因为应用程序使用的这种编程接口实际上并不需要和内核提供的系统调用对应。一个API定义了一组应用程序使用的编程接口。他们可以实现成以一个系统调用,也可以通过调用多个系统调用来实现,而完全不适用任何系统调用也不成问题。实际上API可以在不同的才做系统上实现,给应用程序提供完全不同的接口,而他们本身在这些系统上的实现却可能不同。

3. 系统调用 

3.1. 系统调用号 

在Linux中,每个系统调用被赋予一个系统调用好号。这样,通过这个独一无二的号就可以关联系统调用。当用户空间的进程执行一个系统调用的时候,这个调用号(此时存放在eax中)就用来指明到底要调用那个系统调用,进程不会提供系统调用的名称。

系统调用号相当重要,一旦分配就不能再有任何变更,否则编译好的应用层程序就会奔溃。此外,如果一个系统调用被删除,它所占用的系统调用好也不允许被回收利用,否则,以前编译过的代码会调用这个系统调用,但事实上调用的是另外一个系统调用。Linux有一个”未实现“系统调用sys_ni_syscall(),他除了返回-ENOSYS外不做任何其他工作,这个错误就是专门针对无效的系统调用而设置的。

内核中记录了系统调用表中的所有已注册过的系统调用列表。存储在sys_call_table中。每一种体系结构中,都明确定义了这个表,再x86-64中,它定义于arch/i386/kernel/syscall_64.c文件中。这个表为每一个系统调用指定了唯一的系统调用号。

3.2 系统调用处理程序

在调用系统调用的时候是通过软中断的方式切换到内核中的,通过引发一个异常来促使系统切换到内核态去执行异常处理程序。此时异常处理程序实际上就是系统调用处理程序。在x86系统上预定义的软中断是终端号128,通过int $0x80指令触发该中断。这条指令会触发一个异常导致系统切换到内核态并执行128号异常处理程序,而该程序正是系统调用处理程序。这个处理程序的名字起得很贴切,叫做system_call()。

3.3 指定恰当的系统调用

因为所有的系统调用陷入内核的方式都一样,所以仅仅是陷入内核空间是不够的。因为必须把系统调用号一并传给内核。在x86上,系统调用号是通过eax寄存器传递给内核的。在陷入内核之前,用户空间就把相应的系统调用所对应的号放到eax中。这样系统调用处理程序一旦运作就可以从eax中得到数据。其他体系结构上的实现也类似。

system_call()通过将给定的系统调用号于NR_syscalls做比较来检查其有效性。如果它大于或者等于NR_syscalls,该函数就返回-ENOSYS。否则,执行相应的系统调用:

call *sys_call_table(,%rax,8)

由于系统调用表中的表项是以64位类型存放的,所以,内核需要将给定的系统调用乘以4,然后用得到的结果在该表中查询其位置。

3.4. 参数传递

处理系统调用号外,大部分系统调用还需要一些外部的参数传入。所以,在发生陷入的时候,应该把这些参数从用户空间传递给内核。最简单的办法就是想传递系统调用号一样,把这些参数也存放到寄存器中。在x86-32系统上,ebx、ecx、edx、esi和edi按照顺序存放前五个参数。需要六个或者六个以上参数的情况不多见,此时,应该用一个单独的寄存器存放指向所有这些参数的指在用户空间地址的指针。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值