linux内核增加系统调用--Beginner‘s guide

Linux内核中设置了一组用于实现系统功能的子程序,称为系统调用。系统调用和普通库函数调用非常相似明知是系统调用由操作系统核心提供,运行于核心态,而普通的函数调用由函数库或用户自己提供,运行于用户态。 一般的,进程是不能访问内核的,它不能访问内核所占用内存空间也不能调用内核函数。这被称为保护模式。为了和用户空间上运行的进程进行交互,内核提供一组接口。通过该接口应用程序可以访问硬件设备和其他操作系统资源。

实际上提供这组接口主要是为了保证系统稳定可靠,避免应用程序肆意妄为。 系统调用在用户空间和硬件设备之间添加一个中间层,也使得用户的应用程序可以不去管磁盘类型和介质,甚至不用去管文件所在的文件系统是什么类型。这方便了应用程序的可移植性。 在linux中系统调用是用户空间访问内核的唯一手段,除了异常和中断外。

一般情况下,应用程序通过应用程序接口API而不是直接通过系统调用来编程。因为应用程序使用的这种编程接口实际上并不需要和内核提供的系统调用一一对应。一个API接口可以实现成一个系统调用,也可以通过调用多个系统调用实现,也可以不使用任何系统调用。程序员可以不考虑系统调用而直接和API打交道。

系统调用:内核为用户进程提供的服务 提供用户模式的进程和硬件设备的接口; 保护对内核所管理的资源的访问,提高系统安全; 提高程序的可移植性; Linux系统调用在内核中全部以“sys_”开头,如sys_fork, sys_exit.

本文以内核版本为3.13.10为例演示hello world等级的调用,先看需要编译内核的系统调用

1.在kernel/sys.c中添加头文件#include<linux/linkage.h> 文件末尾添加自定义的系统调用函数:sys_mycall

内核版本为3.13.10
-->

2.在arch/x86/syscalls/syscall_64.tbl (32位系统则改为32)添加自定义系统调用号(在本人的机子上按顺序接下来是314)

3.在arch/x86/include/asm/syscalls.h中添加自己的系统调用函数声明

asmlinkage long sys_mycall(int num);

4.内核编译

记得加上-j4等来加快速度(即使是在第二次编译没有清理原目标文件的情况下也很耗时间(磁盘IO很耗时,固态硬盘应该很快吧)

5.编写用户态测试程序

int main(){     printf("The return value is:%d.\n",syscall(314,1234567));     return 0;}

编译为test_hello

6.测试

你可以更新内核,修改系统的启动项等。还可以使用虚拟机来测试,下面使用QEMU来测试(简便而且强大,可指定内核和文件系统来启动)

ubuntu下可从源下载QEMU,可顺便下一个linux-0.2 (wget wiki.qemu.org/download/linux-0.2.img)

然后将test_hello放到测试系统中,也许你想直接在测试系统中直接编译出test_hello,如果你没有现成的装有编译器的可测试系统,可用busybox来编译一个根文件系统

下面列出粗略步骤(但未包含编译工具及链接库):

make menuconfig时在Build Options选Build BusyBox as a static binary (no shared libs)确保不会对共享库产生依赖。

执行make CONFIG_PREFIX=your/dir install 将安装到制定目录,如rootfs/

dd if=/dev/zero of=rootfs.img bs=10240k count=1

mkfs -t ext3 rootfs.img

sudo mount -t ext3 -o loop rootfs.img rootfs

拷贝busybox到rootfs.img,将你的测试程序编译为静态的(gcc -static)拷贝至rootfs.img

$ cd rootfs
$ sudo mkdir dev
创建常用device(mknod 用于制作字符或块相关文件):
$sudo  cd dev
$ sudo mknod tty0 c 4 0
$ sudo mknod tty1 c 4 1
$ sudo mknod tty2 c 4 2
$ sudo mknod tty3 c 4 3
$ sudo mknod console c 5 1
$ sudo mknod null c 1 1
创建init启动脚本
/etc/inittab文件
$ sudo mkdir etc
$ cd etc/
$ sudo vim inittab
#This is the first script to run when startup
::sysinit:/etc/rc.d/rc.sysinit
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a –r
$ sudo mkdir rc.d
$ cd rc.d/
$ sudo vim rc.sysinit
加入以下内容:
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
/bin/sh
$ sudo chmod a+x rc.sysinit
$ cd ../../../
根文件系统制作完成,umount rootfs
$ sudo umount rootfs.img

准备就绪,现在可以开始带根文件系统跑内核
qemu-system-x86_64 -hda rootfs.img -kernel /boot/vmlinuz-3.13.10 --append root=/dev/sda m=256 (看你的情况使用不同的命令)
可以看到linux在quem上跑起来了(刚启动可能需要回车才显示命令提示符,文件系统若是只读的可用mount -o rw,remount /重挂载,若启动时提示init等文件不可执行是你没有赋予它可执行权限。执行测试程序,下图中的call_static(执行时需要写全路径)。

时间: 2024-10-05 12:50:30

linux内核增加系统调用--Beginner‘s guide的相关文章

linux内核增加系统调用 - 内核版本3.16.39

详细内容见下面链接: http://files.cnblogs.com/files/jingjingblog/linux%E5%86%85%E6%A0%B8%E5%A2%9E%E5%8A%A0%E7%B3%BB%E7%BB%9F%E8%B0%83%E7%94%A8.pdf 文档主要内容: 1.基础知识介绍 2.增加系统调用 3.以树的形式输出进程间的父子关系

向linux内核添加系统调用新老内核比较

2.6内核 1>修改linux-source-2.6.31/kernel/sys.c文件,在文件末尾添加系统响应函数.函数实现如下: asmlinkage int sys_mycall(int number) { printk("这是我添加的第一个系统调用"); return number; } 2>在linux-source-2.6.31/arch/x86/kernel/syscall_table_32.S 中添加:.long sys_mycall 如: .long sy

[linux内核]ARM-Linux系统调用

1,系统调用的概念: 是用户空间访问内核的唯一手段,系统调用依靠软件中断实现,每个系统调用被赋予一个系统调用号,用来指明要执行哪个系统调用. 2,系统调用的实现:系统调用是通过软中端(SWI)实现的,SWI指令SWI指令的格式为:SWI{条件} 24位的立即数SWI指令用于产生软件中断,以便用户程序能调用操作系统的系统例程.操作系统在SWI的异常处理程序中提供相应的系统服务,指令中24位的立即数指定用 户程序调用系统例程的类型,相关参数通过通用寄存器传递,当指令中24位的立即数被忽略时,用户程序

Linux内核(四)系统调用

转载请注明出处:jiq?钦's technical Blog 什么是系统调用? 系统调用--内核和用户应用程序的桥梁,中间人. 系统调用就是内核实现的一系列函数,这些函数提供了一套固定的接口,通过这套接口,用户程序可以访问系统硬件和操作系统的资源,即内核提供的服务. 为什么提供系统调用? 用户空间只能通过系统调用来访问内核提供的服务的根本原因是为了对系统进行"保护",因为我们知道Linux的运行空间分为内核空间与用户空间,它们各自运行在不同的级别中,逻辑上相互隔离.用户进程在通常情况下

通过内核编译法向Linux内核添加系统调用

[实验内容]: 向Linux添加一个系统调用 测试该系统调用 使用ptrace或类似的系统跟踪工具来对该测试程序进行跟踪调试 [软件]:VMWare支持的Ubuntu虚拟机 VSCode [步骤] 1.在实验之前先下载好相关软件包 不过如果升级了make以后,如果内核版本低,会报错 1. sudo apt-get install make 2. sudo apt-get install gcc 3. sudo apt-get install libncurses5-dev 4. sudo apt

Linux内核的系统调用---linux内核学习笔记(四)

内容一:实验报告相关说明. 真实姓名 谢润帮 原创作品转载请注明出处  所学课程:<Linux内核分析>MOOC课程   链接:http://mooc.study.163.com/course/USTC-1000029000 代码来源于孟宁老师的课件 虚拟实验室实验截图 实验结果图 实验代码截图

深入理解Linux内核-系统调用

系统调用:用户态进程向内核发出的,实现用户态进程调用硬件设备的函数或者中断:优点:使编程更容易,将用户从学习硬件设备的低级编程特性中解放:提高系统到安全性,内核在满足请求之前可以做正确性检查:提高可移植性: 系统调用与API调用的区别:1.API调用是一个函数定义:系统调用是通过软中断向内核发出的明确请求2.内核不可以访问库函数 内核中,返回值为正数或者0表示系统调用成功结束,否则表示出错条件 进入内核态的两种方式:1.执行 int $0x80 指令 :2.执行 sysenter 指令内核推出系

《Linux内核分析》 week6作业-Linux内核fork()系统调用的创建过程

一.进程控制块PCB-stack_struct 进程在操作系统中都有一个结构,用于表示这个进程.这就是进程控制块(PCB),在Linux中具体实现是task_struct数据结构,它主要记录了以下信息: 状态信息,例如可执行状态.就绪状态.阻塞状态等. 性质,由于unix有很多变种,进行有自己独特的性质. 资源,资源的链接比如内存,还有资源的限制和权限等. 组织,例如按照家族关系建立起来的树(父进程.子进程等). task_struct结构体内容非常庞大,暂时没有去分析源代码,以后有时间再去研究

向linux内核加入系统调用新老内核比較

2.6内核 1>改动linux-source-2.6.31/kernel/sys.c文件,在文件末尾加入系统响应函数.函数实现例如以下: asmlinkage int sys_mycall(int number) { printk("这是我加入的第一个系统调用"); return number; } 2>在linux-source-2.6.31/arch/x86/kernel/syscall_table_32.S 中加入:.long sys_mycall 如: .long