@RunZhi
2016-09-14T00:13:14.000000Z
字数 3069
阅读 1287
操作系统实验报告
加入自己的系统调用
上网下载最新Linux kernel源代码,掌握编译的方法:编译linux源代码
//rzcall.c
#include<linux/linkage.h> //for linkage
#include<linux/kernel.h> //for printk
asmlinkage long sys_rzcall(void) // asmlinkage type sys_NAME(...)
{
printk("Hello, I'm RunzhiZeng\n");
printk("My student ID is:20142101028\n");
printk("See you~\n");
return 0;
}
(编写的时候要注意系统调用的编写格式)
编写完后,保存kernel目录下的某个文件,我的源代码保存在一个新的文件夹mysyscalls中: ~/linux-4.6.4/mysyscalls/rzcall.c
在mysyscalls文件夹中,新建一个makefile文件.内如如下:
obj-y:=rzcall.o
同时,在kernel目录下,修改其中的makefile文件
找到如下部分:
ifeq ($(KBUILD_EXTMOD),)
core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/
修改为:(就是在后面补上你的系统调用所在的文件夹)
ifeq ($(KBUILD_EXTMOD),)
core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/ mysyscalls/
找到kernel目录下的syscall_64.tbl文件(搜索即可).打开,在其中根据相应格式加入系统调用号,比如我的syscall_64.tbl的内容为:
....
324 common membarrier sys_membarrier
325 common mlock2 sys_mlock2
326 common copy_file_range sys_copy_file_range
327 64 preadv2 sys_preadv2
328 64 pwritev2 sys_pwritev2
#
# x32-specific system call numbers start at 512 to avoid cache impact
# for native 64-bit operation.
#
512 x32 rt_sigaction compat_sys_rt_sigaction
513 x32 rt_sigreturn sys32_x32_rt_sigreturn
514 x32 ioctl compat_sys_ioctl
515 x32 readv compat_sys_readv
516 x32 writev compat_sys_writev
517 x32 recvfrom compat_sys_recvfrom
....
我想把我加的系统调用编号为329.那么只需要在328后面加上:(注意,系统调用号不可冲突)
....
324 common membarrier sys_membarrier
325 common mlock2 sys_mlock2
326 common copy_file_range sys_copy_file_range
327 64 preadv2 sys_preadv2
328 64 pwritev2 sys_pwritev2
329 common rzcall sys_rzcall
#
# x32-specific system call numbers start at 512 to avoid cache impact
# for native 64-bit operation.
#
512 x32 rt_sigaction compat_sys_rt_sigaction
513 x32 rt_sigreturn sys32_x32_rt_sigreturn
514 x32 ioctl compat_sys_ioctl
515 x32 readv compat_sys_readv
516 x32 writev compat_sys_writev
517 x32 recvfrom compat_sys_recvfrom
...
按照在第0步分享的网页,重新编译安装内核.
编写以下用户态程序:
//test.c
#include <sys/syscall.h>
int main()
{
syscall(329);
return 0;
}
保存为test.c
在终端下,编译运行.
$ gcc test.c
$ ./a.out
$ dmesg
输入dmesg后,控制台会输出:
...
[ 135.060698] Bluetooth: BNEP filters: protocol multicast
[ 135.060702] Bluetooth: BNEP socket layer initialized
[ 1009.816678] Hello, I'm RunzhiZeng
[ 1009.816686] My student ID is:20142101028
[ 1009.816688] See you~
至此,添加系统调用完毕
Q:系统调用过多会引起进程的性能开销么?为什么?
答:会.因为如果过多进行系统调用,系统频繁在用户态和管态互相切换,,比使用一般的函数调用需要的时间会多一些.
以一个程序例子来说明:
编写另外一个系统调用,代码如下:
//rztest.c
#include<linux/linkage.h>
#include<linux/kernel.h>
asmlinkage long sys_rztest(int a,int b)
{
return a + b;
}
系统调用号设为330.重复上面的步骤进行内核更新.
编写另外一个普通函数和一个头文件:
//test3.c
long RZtest(int a,int b)
{
return a + b;
}
//test.h
#ifndef _TEST_H_
#define _TEST_H_
#include<stdio.h>
#include <sys/syscall.h>
#define cnt 10000000 //运行10000000次
long RZcall(void);
#endif /* _TEST_H_ */
保存在test3.c,test.h中
比较以下两个程序的运行时间:
//test1.c
#include"test.h"
int main(void)
{
int i;
int c;
for ( i = 0 ; i <= cnt ; i++)
c = syscall(330, 100, 100);
return 0;
}
//test2.c
#include"test.h"
int main(void)
{
int c;
int i;
for ( i = 0 ; i <= cnt ; i++)
c = RZtest(100,100);
return 0;
}
编译运行两个程序
$ gcc -o test2 test2.c test3.c
$ gcc -o test1 test1.c
对比test1和test2两个程序的运行时间:
...
[runzhizeng@localhost 2]$ time ./test1
real 0m0.816s
user 0m0.188s
sys 0m0.629s
[runzhizeng@localhost 2]$ time ./test2
real 0m0.035s
user 0m0.035s
sys 0m0.000s
...
发现,test1比test2慢得不是一点.