1. Linux体系结构

  Linux系统的地址空间分为用户空间和内核空间,通过系统调用和硬件中断能够完成从用户空间到内核空间的转移。

2. 系统调用接口

① 一般情况下,用户进程不能访问内核空间。Linux内核中提供了一组用于实现各种系统功能的子程序,用户可以调用它们访问Linux内核的数据和函数,这些子程序称为系统调用接口(SCI)。

② 系统调用和普通函数的区别:系统调用由操作系统内核实现,运行于内核态;普通函数调用由函数库或用户自己提供,运行于用户态。

3. 系统调用分类:主要分3大类

① 进程控制类

  * fork

  * clone

  * execve

  ...

② 文件控制类

  * fcntl

  * open

  * read

  ...

③ 系统控制类

  * ioctl

  * reboot

  ...

4.  系统调用工作原理

  系统调用工作原理是(1)进程先用适当的值填充寄存器(R7),(2)然后调用一个特殊的指令(swi),(3)这个指令会让用户程序跳转到一个事先定义好的内核中的一个位置(vector_swi),(4)这位置的代码会根据寄存器(R7)的值从表sys_call_table中查找相应的函数。

(1)适当的值:系统调用号,定义于文件arch\arm\include\asm\unistd.h中。

#define __NR_restart_syscall        (__NR_SYSCALL_BASE+  0)
#define __NR_exit (__NR_SYSCALL_BASE+ 1)
#define __NR_fork (__NR_SYSCALL_BASE+ 2)
#define __NR_read (__NR_SYSCALL_BASE+ 3)
#define __NR_write (__NR_SYSCALL_BASE+ 4)
#define __NR_open (__NR_SYSCALL_BASE+ 5)
#define __NR_close (__NR_SYSCALL_BASE+ 6)

(2)特殊的指令
  * 在X86 CPU中,这个指令由中断0x80实现

  * 在ARM中,这个指令是SWI(Software interrupt:软中断指令),现在重命名为SVC

(3)固定的位置:在ARM体系中,这个固定位置为ENTRY(vector_swi)(arch\arm\kernel\entry-common.S)

(4)相应的函数:内核根据应用程序传递来的系统调用号,从系统调用表sys_call_table(sys_call_table中表项定于文件:arch\arm\kernel\calls.S)找到相应的内核函数。

5. 参数传递

① 系统调用参数传递是通过寄存器传递的,寄存器传递参数,需要满足两个条件

  * 每个参数长度不能超过寄存器长度,即32位

  * 参数个数不能超过6个(少于等于6个的参数用r0~r5传递),处理器的寄存器并不是无限多的

② 多于6个的参数,会用一个寄存器指向进程地址空间中这些参数值所在的一个内存区域(不必过多深究)

6. 向Linux内核中添加新的系统调用

① 在内核代码的某一位置添加函数,如:向kernel/printk.c中添加

void sys_print(int arg0, int arg1, int arg2, int arg3, int arg4, int arg5)
{
printk("Hello Kevin, this is a new system call\n");
printk("arg0 = %d\n", arg0);
printk("arg1 = %d\n", arg1);
printk("arg2 = %d\n", arg2);
printk("arg3 = %d\n", arg3);
printk("arg4 = %d\n", arg4);
printk("arg5 = %d\n", arg5);
}

② 把函数添加至sys_call_table,如:向arch\arm\kernel\calls.S中373行添加

CALL(sys_print)

③ 添加系统调用号,如:向arch\arm\include\asm\unistd.h中添加

#define __NR_sys_print        (__NR_SYSCALL_BASE+361)

7. 新的系统调用测试

①应用层测试代码方法1:

#include <sys/syscall.h>

int main()
{
syscall(361, 10, 11, 12, 13, 14, 15); return ;
}

①应用层测试代码方法2:

void SystemCallTest()
{
__asm__ (
"ldr r7, =361 \n"
"mov r0, #0\n"
"mov r1, #1\n"
"mov r2, #2\n"
"mov r3, #3\n"
"mov r4, #4\n"
"mov r5, #5\n"
"swi \n"
:
:
:"memory"
);
} int main()
{
SystemCallTest(); return ;
}

Linux系统调用接口添加简单示例的更多相关文章

  1. Linux下GDB调试简单示例

    这里介绍对文件first.c的基本GDB调试操作,只有部分命令,只是一个示例,运行环境为装有gcc编译器和gdb调试器的Linux环境,基本GDB调试命令如下表: 命令                 ...

  2. linux下定时任务的简单示例

    1.方式一:用sleep实现定时任务: 1.1 编辑shell脚本,如下sleep_aa.sh: #!/bin/bash t1=`date "+%Y-%m-%d %H:%M:%S" ...

  3. 使用 Linux 系统调用的内核命令【转】

    转自:http://www.ibm.com/developerworks/cn/linux/l-system-calls/ 探究 SCI 并添加自己的调用 Linux® 系统调用 —— 我们每天都在使 ...

  4. Linux字符设备简单示例

    1. Linux字符设备是一种按字节来访问的设备,字符驱动则负责驱动字符设备,这样的驱动通常实现open.close.read和write系统调用.例如:串口.Led.按键等. 2. 通过字符设备文件 ...

  5. 添加linux系统调用的两种方式

    原文:https://blog.csdn.net/sdulibh/article/details/51889279 向linux内核添加系统调用,一是通过编译内核添加,二是通过内核模块的方式添加: 一 ...

  6. Linux内核模块简单示例

    1. Linux 内核的整体结构非常庞大,其包含的组件也非常多,使用这些组件的方法有两种: ① 直接编译进内核文件,即zImage或者bzImage(问题:占用内存过多) ② 动态添加 * 模块本身并 ...

  7. Linux下的C Socket编程 -- server端的简单示例

    Linux下的C Socket编程(三) server端的简单示例 经过前面的client端的学习,我们已经知道了如何创建socket,所以接下来就是去绑定他到具体的一个端口上面去. 绑定socket ...

  8. (转载)Linux系统调用及用户编程接口(API)

    (转载)http://www.farsight.com.cn/news/emb167.htm 1 Linux系统调用 所谓系统调用是指操作系统提供给用户程序调用的一组“特殊”接口,用户程序可以通过这组 ...

  9. Linux I2C驱动--用户态驱动简单示例

    1. Linux内核支持I2C通用设备驱动(用户态驱动:由应用层实现对硬件的控制可以称之为用户态驱动),实现文件位于drivers/i2c/i2c-dev.c,设备文件为/dev/i2c-0 2. I ...

随机推荐

  1. sql编写注意

    DROP TABLE IF EXISTS `imooc_pro`; CREATE TABLE `imooc_pro`( `id` int unsigned auto_increment key, `p ...

  2. node Util 模块

    该util模块主要设计用于支持Node.js自己的内部API的需求.但是,许多实用程序对于应用程序和模块开发人员也很有用.它可以通过以下方式访问: const util = require('util ...

  3. c++ public protected private 继承

    1:访问控制 1.1 public 这类型成员可以被类本身函数访问,也可以被外部创建的类对象调用.子类对象与子类内部可以访问 1.2 protected类型成员,只能被类本身函数访问.外部创建的类对象 ...

  4. Luogu 2737 [USACO4.1]麦香牛块Beef McNuggets

    NOIP2017 D1T1 的结论,两个数$a, b$所不能表示出的最大的数为$a * b - a - b$. 听了好几遍证明我还是不会 注意到本题中给出的数都非常小,所以最大不能表示出的数$\leq ...

  5. WOJ 18 动态无向图

    一开始我是不会写的,后来点开了题解: 无话可说……那就写吧……然而第一发跑成暴力分,后来加了一个优化:就是在询问里面提到过的边都不用再加了. 然后……然后就过了呀…… 其实还有面向数据的编程的骚操作… ...

  6. IP地址及子网掩码计算

    主机号全0表示网络号,主机号全1表示广播地址 我们都知道,IP是由四段数字组成,在此,我们先来了解一下3类常用的IP A类IP段 0.0.0.0 到127.255.255.255 B类IP段 128. ...

  7. 安装visual_Paradigm,时序图的应用

    此安装包已经上传到sunny的百度网盘. 删除,即,右击别的地方,然后,选择delete即可. 拖箭头,拖到某个实体上,再松开,会自动连线. 很好的一款画图工具.

  8. java全栈day06---数组的练习 冒泡排序

    水仙花练习功能实现 * A: 水仙花练习功能实现 * a: 题目分析 * 明确什么样的数就是水仙花数.水仙花数是指一个3位数(100-999之间),其每位数字立方之和等于该3位数本身. 如153 = ...

  9. EchartJS平均线、最大值、最小值

    1.先来看一个没有平均线.最大值.最小值的简单实例 option = { title: { text: '未来一周气温变化', subtext: '纯属虚构' }, tooltip: { trigge ...

  10. JavaAppArguments示例

    本实验要求编写一个程序,此程序从命令行接收多个数字,求和之后输出结果.一大难点是命令行参数都是字符串,必须先将其转化为数字,才能相加. 中心想法就是将求和数字转换为整型并依次相加. 程序流程图: pu ...