1. 引言

本文档解释了怎样在Linux2.6中实现一个新的系统调用。一个系统调用被应用程序用来向操作系统请求服务。

2.   系统调用

一个系统调用被应用程序用来向操作系统请求服务。下面的语句阐述了为什么需要

系统调用。一个操作系统可以直接访问一个系统的硬件,但是一个用户程序没有直接访问硬件的权限。这样做是为了使系统免于遭受恶意的用户程序的破坏,保证系统的安全和保密。但是,经常,一个用户程序需要一些硬件相关的信息(例如,从一个摄像头中获取数据以显示图像),但是,它不能直接获取信息。因此,它请求操作系统提供它这些信息。这个请求是通过使用一个合适的系统调用来完成的。

一个系统调用可以在内核模式下执行。每个系统调用有一个与之关联的数字。这个数字被传递给内核,内核是根据这个数字来决定该执行哪个系统调用。当一个用户程序发出一个系统调用时,它实现上是调用一个库函数。该库函数通过执行汇编指令INT0x80向Linux操作系统发出一个陷阱。它同时也通过EAX寄存器将系统调用号传递给内核。系统调用的参数通过其他的寄存器(EBX,ECX,etc)也传递给内核。内核执行该系统调用,并通过一个寄存器将执行结果返回给用户程序。如果该系统调用需要返回给用户程序大量的数据,它会使用其他的机制(例如,copy_to_user调用)。

  3.  需要修改或创建的文件列表

假设你的Linux源码的基目录是/usr/src/linux.需要修改的内核文件如下所示:

1./usr/src/linux/arch/i386/kernel/syscall_table.S

2./usr/src/linux/include/asm-i386/unistd.h

3./usr/src/linux/include/linux/syscalls.h

4. /usr/src/linux/Makefile

需要新创建的文件/目录如下所示:

1. /usr/src/linux/mycall –包含我们自己的系统调用的源文件,头文件和Makefile的目录(你也可以在一个已存在的文件中实现自己的系统调用).

2. /usr/src/linux/mycall/mycall.c–实现我们自已的系统调用的源码.

3. /usr/src/linux/mycall/Makefile- Makefile

新创建的用户空间文件以及用于测试我们的系统调用的文件列表如下所示:

1. testmycall.c –调用我们自己的系统调用的源码.

2. testmycall.h –头文件.

  4.  需要修改的内核文件

文件的全路径-/usr/src/linux/arch/i386/kernel/syscall_table.S

该文件包含系统调用的名字.

1.在该文件的后面添加一行(假设我们的系统调用名是mycall).

2. 添加".longsys_mycall"列表的尾部.

       4. 2. unistd.h

文件全路径-/usr/src/linux/include/asm-i386/unistd.h

该文件包含系统调用号,当一个系统调用被调用时通过寄存器(EAX)将其传递给内核.

在列表后面添加"#define__NR_mycall Last_System_Call_Num + 1 "

如果上一个系统调用定义在这里:

"#define__NR_vmsplice 316",那么在列表后面添加:

"#define__NR_mycall 317".

将"NR_syscalls"增1.这样,如果NR_syscalls定义如下:

"#defineNR_syscalls 317",那么将其改为:

"#defineNR_syscalls 318"

   4. 3. syscalls.h

文件全路径-/usr/src/linux/include/linux/syscalls.h

该文件包含了系统调用的声明.

在该文件的末尾加入如下语句:

"asmlinkagelong sys_mycall(int i);"

 

        4.4. Makefile

文件全路径-/usr/src/linux/Makefile

Add  mycall/ to core-y (Search for regex: core-y.*+=). You will be creating this directory.

This directory will contain the source   file, header file and the Makefile for our system call.

  5. 新创建的内核文件/目录

5.1mycall

文件全路径-/usr/src/linux/mycall

在/usr/src/linux创建一个新目录,并命名为"mycall".

5.2. mycall.c

文件全路径-/usr/src/linux/mycall/mycall.c

  1. 在目录"mycall"下创建源码文件"mycall.c".mycall.c包含系统调用的源码.源文件中系统调用的定义是asmlinkagelong sys_mycall(...){...} . 它应该包含linux/linkage.h.因此,源文件"mycall.c"看起来是这样的:

/*---Startof mycall.c----*/

#include<linux/linkage.h>

asmlinkagelong sys_mycall(int i)

{

returni+10;

}

/*---Endof mycall.c------*/

什么是asmlinkage?

asmlinkage用于在内核栈中查找参数.

5.3. Makefile

文件全路径-/usr/src/linux/mycall/Makefile

目录"mycall"下的Makefile只有一行:

#####MakefileStart#####

obj-y:= mycall.o

#####MakefileEnd#######

6.新创建的用于测试我们自己的系统调用的用户空间文件

6.1testmycall.h(新创建的用户空间头文件)

往该头文件中加三行代码.testmycall.c(新创建的用户空间源文件)

testmycall.h

创建一个头文件testmycall.h.该头文件将被任何调用我们的系统调用的程序所包含.

第1行:它是必须的,因为我们需要__syscall1的定义.

#include<linux/unistd.h>

第2行:这也是需要的,因为我们需要系统调用号.

#define__NR_mycall 317

第3行:这对于拥有一个参数的系统调用是必须的.下面我们会详述.

_syscall1(long,mycall, int, i)

因此,我们的头文件看起来是这样的:

/*---Startof header file------*/

#include<linux/unistd.h>

#define__NR_mycall 317

_syscall1(long,mycall, int, i)

/*---Endof header file--------*/

6.2. testmycall.c(新创建的用户空间源文件)

testmycall.c

在与testmycall.h同一目录下创建一个C文件testmycall.c.C文件看起来如下所示:

/*---Startof C file------*/

#include<stdio.h>

#include"testmycall.h"

intmain(void)

{

printf("%d\n",mycall(15));

}

/*---Endof C file------*/

6.3. __syscallN

longmycall(int i)

{

returnsyscall(__NR_mycall, i);

}

但是,宏_syscallN宏在内核中是不同的.你可以在/usr/src/linux/include/asm-i386/unistd.h中查看定义.

7. 测试我们新的系统调用

Step 1:重新编译和安装新的内核,使得操作系统中包含进我们的系统调用.

Step 2:编译和执行用户空间C文件(testmycall.c).

RESULT:你应该得到的输出是25. 这已经在内核2.6.17.13上测试过.

转载于:https://my.oschina.net/fuyajun1983cn/blog/263952

在i386平台Linux 2.6 上实现一个系统调用相关推荐

  1. Linux 编译内核且增加一个系统调用

    Linux 编译内核且增加一个系统调用 文章目录 Linux 编译内核且增加一个系统调用 一.在添加系统调用之前需要先编译一个Linux的内核. 解压 安装依赖 编译 安装内核 二.系统调用 声名和定 ...

  2. linux tr命令书上的一个很好的例子

  3. linux怎么看数据库实例,Linux/Unix平台如何查看OS上存在有哪些数据库或实例

    其实这是一个不难的问题,由于有同事问到这个问题,我就把这个问题的方法写下来好了,必竟有一个人来问,说不定还有第二个人不会,希望对还不会的或是刚入行的朋友有所帮助吧. linux/unix平台如何查看O ...

  4. i386平台和x86-64平台机器代码的区别

    2019独角兽企业重金招聘Python工程师标准>>> i386平台和x86_64平台机器代码的区别 By Qianghaohao 说明: 在此i386(IA32)指的是Intel3 ...

  5. 在 Oracle Enterprise Linux 和 iSCSI 上构建您自己的 Oracle RAC 11g 集群 (2)

    13. 创建任务角色划分操作系统权限组.用户和目录 在集群的两个 Oracle RAC 节点上针对 grid 和 oracle 用户执行以下用户.组和目录配置并设置 shell 限制的任务.     ...

  6. 在 Oracle Enterprise Linux 和 iSCSI 上构建您自己的 Oracle RAC 集群(续)

    DBA:Linux    下载  Oracle 数据库 11g    标签 linux, rac, clustering, 全部 在 Oracle Enterprise Linux 和 iSCSI 上 ...

  7. 在 Oracle Enterprise Linux 和 iSCSI 上构建您自己的 Oracle RAC 11g 集群

    作者:Jeffrey Hunter 了解如何以低于 2,700 美元的费用在 Oracle Enterprise Linux 上安装并配置 Oracle RAC 11g 第 2 版开发集群. 本指南中 ...

  8. Linux学习总结02——内存管理——Linux在X86上的虚拟内存管理

    Linux内存管理之二:Linux在X86上的虚拟内存管理 本文档来自网络,并稍有改动. 前言 Linux支持很多硬件运行平台,常用的有:Intel X86,Alpha,Sparc等.对于不能够通用的 ...

  9. Linux发行版上安装Netbeans IDE的各种方法

    在本文中,您将学习在Ubuntu和其他Linux发行版上安装Netbeans IDE的各种方法. NetBeans是一个开源的集成开发环境,具有良好的跨平台支持.该工具已被Java和C/C ++开发社 ...

最新文章

  1. oracle expdp/impdp exclude=STATISTICS
  2. C语言是始祖,科技日历| 61年前,ALGOL语言创立!它是C语言等高级语言的直接“鼻祖”...
  3. RESTful Web Service
  4. input type='file' 上传文件时显示文件名及上传进度
  5. 尚学堂java 参考答案 第八章
  6. Hibernate重附(Reattach)和合并(Merge)操作的比较
  7. c语言编译器 for mac,编译工具CMake for mac
  8. Java编程ture找不到符号,[未解决]Bugly中上传符号表dSYM文件
  9. ★追风的牛★添翼圈Moto Droid玩家手册(感谢原作者,只是做个备份而已,如果牵扯到越劝,我会立即删掉)
  10. 未将对象引用设置到对象的实例 解决办法
  11. “成本刺客”防不胜防,如何应用亚马逊云科技驾驭云成本
  12. 贪心搜索(greedy search)、集束搜索(beam search)、随机采样(random sample)
  13. 百万级数据连表查询优化
  14. 用Modules优雅地管理你的环境变量
  15. ScreenToGif: Gif 图片神器
  16. 【IIS音频传输】1、认识IIS
  17. 微信投票系统java开发_微信投票系统 v3.0
  18. mysql数据库取交集_不同数据库取并集、交集、差集
  19. ORA-20000:ORU-10027:buffer overflow,limit of 10000 bytes
  20. 多核编程指南(六)---进程间通信(三)

热门文章

  1. ngx_lua module 模块安装
  2. 【AJAX】反向Ajax第1部分:Comet介绍
  3. 张孝祥Java培训视频及孙鑫java视频网址
  4. 有return的情况下try catch finally的执行顺序
  5. input type 属性
  6. C++day15 学习笔记
  7. 如何在修改checkbox状态,不触发事件
  8. [Google App Engine] Hello, world!
  9. SQLSERVER拆分字符串的函数(表值函数)
  10. MySQL使用可重复读作为默认隔离级别的原因