[关闭]
@RunZhi 2016-09-13T16:13:14.000000Z 字数 3069 阅读 1221

在linux kernel4.6.4中添加自己的系统调用

操作系统实验报告

实验目的

加入自己的系统调用

实验过程:

0.获得linux kernel

上网下载最新Linux kernel源代码,掌握编译的方法:编译linux源代码

1.编写要增加系统调用的源代码

  1. //rzcall.c
  2. #include<linux/linkage.h> //for linkage
  3. #include<linux/kernel.h> //for printk
  4. asmlinkage long sys_rzcall(void) // asmlinkage type sys_NAME(...)
  5. {
  6. printk("Hello, I'm RunzhiZeng\n");
  7. printk("My student ID is:20142101028\n");
  8. printk("See you~\n");
  9. return 0;
  10. }

(编写的时候要注意系统调用的编写格式)
编写完后,保存kernel目录下的某个文件,我的源代码保存在一个新的文件夹mysyscalls中: ~/linux-4.6.4/mysyscalls/rzcall.c

2.修改makefile

在mysyscalls文件夹中,新建一个makefile文件.内如如下:

  1. obj-y:=rzcall.o

同时,在kernel目录下,修改其中的makefile文件
找到如下部分:

  1. ifeq ($(KBUILD_EXTMOD),)
  2. core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/

修改为:(就是在后面补上你的系统调用所在的文件夹)

  1. ifeq ($(KBUILD_EXTMOD),)
  2. core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/ mysyscalls/

3.加入系统调用号

找到kernel目录下的syscall_64.tbl文件(搜索即可).打开,在其中根据相应格式加入系统调用号,比如我的syscall_64.tbl的内容为:

  1. ....
  2. 324 common membarrier sys_membarrier
  3. 325 common mlock2 sys_mlock2
  4. 326 common copy_file_range sys_copy_file_range
  5. 327 64 preadv2 sys_preadv2
  6. 328 64 pwritev2 sys_pwritev2
  7. #
  8. # x32-specific system call numbers start at 512 to avoid cache impact
  9. # for native 64-bit operation.
  10. #
  11. 512 x32 rt_sigaction compat_sys_rt_sigaction
  12. 513 x32 rt_sigreturn sys32_x32_rt_sigreturn
  13. 514 x32 ioctl compat_sys_ioctl
  14. 515 x32 readv compat_sys_readv
  15. 516 x32 writev compat_sys_writev
  16. 517 x32 recvfrom compat_sys_recvfrom
  17. ....

我想把我加的系统调用编号为329.那么只需要在328后面加上:(注意,系统调用号不可冲突)

  1. ....
  2. 324 common membarrier sys_membarrier
  3. 325 common mlock2 sys_mlock2
  4. 326 common copy_file_range sys_copy_file_range
  5. 327 64 preadv2 sys_preadv2
  6. 328 64 pwritev2 sys_pwritev2
  7. 329 common rzcall sys_rzcall
  8. #
  9. # x32-specific system call numbers start at 512 to avoid cache impact
  10. # for native 64-bit operation.
  11. #
  12. 512 x32 rt_sigaction compat_sys_rt_sigaction
  13. 513 x32 rt_sigreturn sys32_x32_rt_sigreturn
  14. 514 x32 ioctl compat_sys_ioctl
  15. 515 x32 readv compat_sys_readv
  16. 516 x32 writev compat_sys_writev
  17. 517 x32 recvfrom compat_sys_recvfrom
  18. ...

4.重新编译,安装内核

按照在第0步分享的网页,重新编译安装内核.

实验结果

编写以下用户态程序:

  1. //test.c
  2. #include <sys/syscall.h>
  3. int main()
  4. {
  5. syscall(329);
  6. return 0;
  7. }

保存为test.c
在终端下,编译运行.

  1. $ gcc test.c
  2. $ ./a.out
  3. $ dmesg

输入dmesg后,控制台会输出:

  1. ...
  2. [ 135.060698] Bluetooth: BNEP filters: protocol multicast
  3. [ 135.060702] Bluetooth: BNEP socket layer initialized
  4. [ 1009.816678] Hello, I'm RunzhiZeng
  5. [ 1009.816686] My student ID is:20142101028
  6. [ 1009.816688] See you~

至此,添加系统调用完毕

一点问题

Q:系统调用过多会引起进程的性能开销么?为什么?

答:会.因为如果过多进行系统调用,系统频繁在用户态和管态互相切换,,比使用一般的函数调用需要的时间会多一些.

以一个程序例子来说明:
编写另外一个系统调用,代码如下:

  1. //rztest.c
  2. #include<linux/linkage.h>
  3. #include<linux/kernel.h>
  4. asmlinkage long sys_rztest(int a,int b)
  5. {
  6. return a + b;
  7. }

系统调用号设为330.重复上面的步骤进行内核更新.
编写另外一个普通函数和一个头文件:

  1. //test3.c
  2. long RZtest(int a,int b)
  3. {
  4. return a + b;
  5. }
  1. //test.h
  2. #ifndef _TEST_H_
  3. #define _TEST_H_
  4. #include<stdio.h>
  5. #include <sys/syscall.h>
  6. #define cnt 10000000 //运行10000000次
  7. long RZcall(void);
  8. #endif /* _TEST_H_ */

保存在test3.c,test.h中

比较以下两个程序的运行时间:

  1. //test1.c
  2. #include"test.h"
  3. int main(void)
  4. {
  5. int i;
  6. int c;
  7. for ( i = 0 ; i <= cnt ; i++)
  8. c = syscall(330, 100, 100);
  9. return 0;
  10. }
  1. //test2.c
  2. #include"test.h"
  3. int main(void)
  4. {
  5. int c;
  6. int i;
  7. for ( i = 0 ; i <= cnt ; i++)
  8. c = RZtest(100,100);
  9. return 0;
  10. }

编译运行两个程序

  1. $ gcc -o test2 test2.c test3.c
  2. $ gcc -o test1 test1.c

对比test1和test2两个程序的运行时间:

  1. ...
  2. [runzhizeng@localhost 2]$ time ./test1
  3. real 0m0.816s
  4. user 0m0.188s
  5. sys 0m0.629s
  6. [runzhizeng@localhost 2]$ time ./test2
  7. real 0m0.035s
  8. user 0m0.035s
  9. sys 0m0.000s
  10. ...

发现,test1比test2慢得不是一点.

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注