linux 2.6 添加系统调用,向linux-2.6.34内核中添加系统调用

(2010-06-20 17:51:37)

转载

标签:

系统调用

linux-2.6.34

it

分类: 嵌入式Linux学习历程

系统调用,顾名思义,说的是操作系统提供给用户程序调用的一组“特殊”接口。用户程序可以通过这组“特殊”接口来获得操作系统内核提供的服务,比如用户可以通过文件系统相关的调用请求系统打开文件、关闭文件或读写文件,可以通过时钟相关的系统调用获得系统时间或设置定时器等。它并非直接和程序员或系统管理员打交道,它仅仅是一个通过软中断机制(我们后面讲述)向内核提交请求,获取内核服务的接口。而在实际使用中程序员调用的多是用户编程接口——API,而管理员使用的则多是系统命令。

系统调用是用户空间和内核空间交互的一种有效手段,但是这并不是说要完成交互功能就非要添加新系统调用不可。除了系统本身提供的系统调用外,用户还可以添加自己的系统调用。下面我们就以一个简单的例子来说明系统调用添加的具体过程。

首先,进入到内核源码目录/usr/src/linux-2.6.34中,添加自己的系统调用号。

sally@sally-desktop:~$ cd /usr/src/linux-2.6.34/

系统调用号在unistd_32.h文件中定义。内核中每个系统调用号都是以“__NR_"开头的,在该文件中添加自己的系统调用号

sally@sally-desktop:/usr/src/linux-2.6.34$ sudo vim arch/x86/include/asm/unistd_32.h

#define __NR_pwritev            334

#define __NR_rt_tgsigqueueinfo  335

#define __NR_perf_event_open    336

#define __NR_recvmmsg           337

#define __NR_mycall             338

#ifdef __KERNEL__

#define NR_syscalls 339

在内核源文件中该行为#define NR_syscalls 338,在系统调用执行的过程               中,system_call()函数会根据该值来对用户态进程的有效性进行检查。如果这个号大于或等于NR_syscalls,系统调用处理程序终止。所以应该将原来的#define NR_syscalls 338修改为#define NR_syscalls 339

其次,在系统调用表中添加相应的表项

(1)sally@sally-desktop:/usr/src/linux-2.6.34$ sudo vim arch/x86/kernel/syscall_table_32.S

ENTRY(sys_call_table)

.long sys_restart_syscall

.long sys_exit

………………(这里省略了部分)

.long sys_rt_tgsigqueueinfo

.long sys_perf_event_open

.long sys_recvmmsg

.long sys_mycall

(2)sally@sally-desktop:/usr/src/linux-2.6.34$ sudo vim arch/h8300/kernel/syscalls.S

#include

#include

#include

……………………(这里省略了部分)

.long SYMBOL_NAME(sys_vmsplice)

.long SYMBOL_NAME(sys_ni_syscall)

.long SYMBOL_NAME(sys_getcpu)

.long SYMBOL_NAME(sys_ni_syscall)

.long SYMBOL_NAME(sys_mycall)

最后,实现系统调用服务例程。

系统调用服务例程函数名为"sys_xxx”

sally@sally-desktop:/usr/src/linux-2.6.34$ sudo vim arch/x86/kernel/sys_i386_32.c

asmlinkage long sys_mycall(void)

{

printk("mycall worked!!\n");

printk("current pid is:%d\n",current->pid);

return current->pid;

}

其中,asmlinkage修饰符是gcc中一个特殊的标志,加了该修饰符的函数必须从堆栈中获取参数。内核中所有系统调用的实现都使用这个修饰符。该服务例程的作用是输出当前进程的pid。

接下来的任务就是重新编译内核了!通过上述几步,添加新的系统调用的所有工作已经完成。但是要使这个系统调用真正的运行起来,还需要重新编译内核。这里内核编译相对之前内核编译及安装而言非常简单,依次输入如下命令即可:

sally@sally-desktop:/usr/src/linux-2.6.34$ sudo make bzImage

sally@sally-desktop:/usr/src/linux-2.6.34$ sudo make modules

sally@sally-desktop:/usr/src/linux-2.6.34$ sudo make install

sally@sally-desktop:/usr/src/linux-2.6.34$ sudo make modules_install

这样内核便编译好了。

注意:内核编译完了之后必须重启,否则已经添加的用户系统调用不能使用。

sally@sally-desktop:~$ sudo  /usr/include/bits/syscall.h

#ifndef _SYSCALL_H

# error "Never use directly; include instead."

#endif

#include

#define SYS__sysctl __NR__sysctl

#define SYS_access __NR_access

………………(这里省略了部分)

#define SYS_vm86old __NR_vm86old

#define SYS_waitpid __NR_waitpid

#define SYS_mycall __NR_mycall

#endif

为了检验添加的系统调用是否成功,特编写下面的测试程序。

sally@sally-desktop:~/linux课程实验/系统调用$ vim test.c

#include

#include

#include

#include

#include

#define mycall() syscall(SYS_mycall)

int main()

{

int x = 0;

x = mycall();

printf("current pid : %d\n", x);

return 0;

}

sally@sally-desktop:~/linux课程实验/系统调用$ gcc test.c -o test

sally@sally-desktop:~/linux课程实验/系统调用$ ./test

current pid : 5570

使用dmesg命令可以看到系统信息如下:

[ 3051.573873] mycall worked!!

[ 3051.573879] current pid is:5570

这样一个简单的系统调用便添加成功了!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值