操作系统实验二:新增系统调用
一、实验内容
1.阅读并分析Linux内核源码,深入了解Linux内核中系统调用内部数据结构;
2.编写一个新系统调用的响应函数,函数的名称和功能由实验者自行定义;
3.将新的系统调用函数嵌入到Linux内核中;
4.编写应用程序以测试新的系统调用并输出测试结果。
二、实验目的
1.熟悉Linux系统调用;
2.深入了解Linux操作系统中系统调用的实现机制和执行过程。
三、设计思路和流程图
新增的系统调用可以自行定义,比如我增加一个选择排序的系统调用。
新增系统调用 select_sort ,用于对数组进行选择排序,对应的系统调用函数为 sys_select_sort 。
1.设置新增系统调用的名称及编号
修改文件 arch/i386/kernel/syscall_table.S
2.设置系统调用的具体内容
因为我新增的函数没有用到头文件,所以没有添加头文件。后面的实验如果需要,可在include/linux目录下添加。
在kernel目录下新建文件 select_sort.c ,实现函数 sys_select_sort 。
宏asmlinkage定义在linux/linkage.h中,表示函数的参数通过栈传递,而不是寄存器,所有的系统调用都遵循这种参数传递方式。
3.使该系统调用在编译时可见
修改文件kernel/Makefile
4.加上系统调用号的宏定义
修改文件include/asm-i386/unistd.h
注意:NR_syscalls表示的值应该是最大的系统调用号加一
5.加上函数sys_select_sort的声明
修改文件include/linux/syscalls.h
如果之前添加了头文件,则还要注意在这里包括头文件。
6.重新编译内核
参照实验一。
这个实验主要是系统调用函数内部的实现,但要注意细心实验,不能遗漏步骤
四、主要数据结构及说明
在指导手册中使用了结构体,放在头文件里,但是我没有采用这种大众的方法。
我的系统调用中采用的是线性顺序表——数组。
使用选择排序的方法对数组进行排序,每次选出其中最小的元素,然后与前面的元素进行交换。
最后的数组元素按照从小到大的顺序进行排序。
五、源程序并附上注释
1.系统调用函数的实现(select_sort.c)
选择排序,主要是两步,一是选出最小的元素,二是交换,程序如下。
#include<linux/linkage.h> #include<linux/types.h> asmlinkage int sys_select_sort(int *a,const int n) { int temp,temp1,min,i,j; for(i=0;i<n-1;i++) { temp=i; min=*(a+i); for(j=i+1;j<n;j++) { if(*(a+j)<min) { temp=j; min=*(a+j); } } if(i != temp) { temp1=*(a+i); *(a+i)=*(a+temp); *(a+temp)=temp1; } } return 0; }
2.测试程序
#include<stdio.h> #include<sys/syscall.h> #include<unistd.h> #define n 9 int main() { int a[n]={43,23,2,33,65,12,6,12,16}; int i=0; //print the array before sorting printf("%s\n","Before sorting:"); for(i=0;i<n;i++) { printf("%d ",a[i]); } printf("%s","\n"); syscall(320,a,n);//system call //print the array after sorting printf("%s\n","After sorting:"); for(i=0;i<n;i++) { printf("%d ",a[i]); } printf("%s","\n"); return 0; }
六、程序运行结果及分析
测试程序编译运行结果如下
七、实验体会
通过新增系统调用可以学到很多linux基本命令的使用,比如,使用vi打开文件,然后i修改文件,:wq保存文件并退出,等等。
新增系统调用后需要重新编译安装内核,然后重启才能生效,如果因为某些原因,重启时不能进入内核,那么可以选择进入之前的内核对新的内核进行修改。
这个实验是为下一个做铺垫的,循序渐进逐步提高,加油!