linux内核设计与实现(第五章)----系统调用

主要内容:

  1. 什么是系统调用
  2. Linux系统调用实现原理
  3. 一个ARM体系架构的系统调用实现

1、什么是系统调用

简单来说,系统调用就是用户程序和硬件设备之间的桥梁。

用户程序在需要的时候,通过系统调用来使用硬件设备。

系统调用的存在,有以下重要的意义:

1)用户程序通过系统调用来使用硬件,而不用关心具体的硬件设备,这样大大简化了用户程序的开发。

    比如:用户程序通过write()系统调用就可以将数据写入文件,而不必关心文件是在磁盘上还是软盘上,或者其他存储上。

2)系统调用使得用户程序有更好的可移植性。

    只要操作系统提供的系统调用接口相同,用户程序就可在不用修改的情况下,从一个系统迁移到另一个操作系统。

3)系统调用使得内核能更好的管理用户程序,增强了系统的稳定性。

    因为系统调用是内核实现的,内核通过系统调用来控制开放什么功能及什么权限给用户程序。

    这样可以避免用户程序不正确的使用硬件设备,从而破坏了其他程序。

4)系统调用有效的分离了用户程序和内核的开发。

    用户程序只需关心系统调用API,通过这些API来开发自己的应用,不用关心API的具体实现。

    内核则只要关心系统调用API的实现,而不必管它们是被如何调用的。

2、Linux系统调用实现原理

当进程执行系统调用函数时,进程跳转到内核态,进入ENTRY(vector_swi)在entry-common.S头文件中。里面涉及到一些EABI和OABI,也就是高版本linux和低版本linux的区别,汇编代码阅读起来可能会繁琐一点。在这个函数中系统检测系统调用号,根据调用号,系统会查看sys_call_table(用户体系下arch/arm/include/asm/unistd.h)查找到内核函数的入口地址ENTRY(sys_call_table)中进入calls.S。接着就在内核态调用该函数,等待返回检查后,返回用户态。

注:仔细的读者可能会想,如果系统调用一旦被删除,怎么办?linux中有一个原则,系统调用号一旦分配不能有任何变更,否则编译好的应用程序就会崩溃,此外一个系统调用号如果被删除,它所占用的系统调用号也不允许被回收。仔细研究发现linux系统中存在一个未被调用的系统调用函数sys_ni_syscall(),它除了返回-ENOSYS外不做任何事情。如果系统调用号错误(大于最大系统调用号或调用函数不存在),这个函数就要填补空缺。

3、一个ARM体系架构的系统调用实现

向内核中添加新的系统调用,需要执行如下3个步骤:

1、 添加新的内核函数

2、 更新头文件unistd.h

3、 针对这个新函数更新系统调用表calls.S

实验内核版本linux3.0.1(注低版本内核可能不适用该方法)

打开arch/arm/kernel/sys_arm.c

添加自己要添加的函数,代码如下:

asmlinkage int sys_add(int a,int b)
{
	int c;
	c = a + b;
	return c;
}

注:asmlinkage是GNU的一个重要标签,具体详见GNU手册。


更新头文件unistd.h

在arch/arm/include/asm/unistd.h

添加如下代码:

#define __NR_add		(__NR_SYSCALL_BASE+376)


更新调用表

在arch/arm/kernel/calls.S

添加如下代码:

CALL(sys_add)

添加一个系统调用后必须重新编译内核。

编写应用层实现函数:

#include <stdio.h>
#include <linux/unistd.h>
int main(void)
{
        int result;
        result = syscall(376,3,2);
        printf("result = %d\n", result);
        return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值