操作系统课程设计
1.1实验目的
1、理解操作系统系统调用的意义。
2、实现对于Linux操作系统内核的编译。
3、实现一个自己添加的系统调用。
1.2实验内容
自己编写一个函数,内容不限,如可以实现求一个数组的最大数,或实现一个排序算法等。总之是一个功能独立的函数。将其作为系统调用函数。
接下来,要求把这个函数加入到linux的系统调用之中去。因为大家的Linux版本不尽相同,所以做法的大致步骤是:
1、修改linux内核某文件,将你实现的函数名进行注册。
2、重新编译内核,使得上述修改生效。
3、编写程序,调用你的内核函数,即系统调用。
1.3实验过程
内核处理:
新建系统内核函数input()与output(),将其放入相关的文件ca_ch.c中。
如图所示:
对新增的内核函数进行注册,打开unistd.h,定义新增函数的系统号与调用时的函数名。
如图所示:
系统调用号新增
调用函数名新增
对新增的函数在sys.h中进行注册。
如图所示
修改内核的总调用数量,打开system_call.s。修改nr_system_calls。
如图所示:
修改Makefile文件,对添加的函数文件进行编译。
如图所示:
对OBJS部分的修改,增添一个编译生成的*.o调用。
…………
在Dependencies中添加上对新建函数文件ca_ch.c的编译需求,保证编译时正常运行
以上部分为对内核的代码修改内容,增添了两个新的系统调用函数。并且修改了相关的Makefile,保证了编译时可以正常的将新增函数进行对应的处理。
用户调用:
编写input()函数调用。
如图所示:
编写output()函数调用。
如图所示:
编译效果:
在Bochs虚拟机中运行内核,输入两条编译用户调用的命令以及输入相应的测试数据进行输出实验。
如图所示:
测试成功。
1.4实验代码
/* 内核代码 */
//读入函数
int sys_input(const char * chr)
{
int i;
char tmp[30];//临时存储 输入字符串 操作失败时不影响msg
for(i=0; i<30; i++) { //从用户态内存取得数据
tmp[i] = get_fs_byte(chr+i);
if(tmp[i] == '\0') break; //字符串结束
}
i=0;
while(i<30&&tmp[i]!='\0') i++;
int len = i;
if(len > 23) {//字符长度大于23个
printk("String too long!\n");
return -(EINVAL); //置errno为EINVAL 返回“--1”
}
strcpy(msg,tmp);
return i;
}
//打印函数
int sys_output(char* chr, unsigned int size)
{
int len = 0;
for(;msg[len]!='\0';len++);
if(len > size) { return -(EINVAL); }//msg的长度大于 size
int i = 0;
for(i=0; i<size; i++) {
put_fs_byte(msg[i], chr + (len - 1 - i));
if(msg[i] == '\0') break; //字符串结束
}
return i;
}
/* 用户态函数 */
//读入函数
_syscall1(int, input, const char*, chr);
int main(int argc,char ** argv)
{
int wlen = 0;
if(argc<1) {
printf("not enough arguments!\n");
return -2;
}
wlen = input(argv[1]);
return wlen;
}
//打印函数
_syscall2(int, output,char*,chr,unsigned int,size);
int main()
{
char s[30];
int rlen = 0;
rlen = output(s,30);
printf("%s\n",s);
return rlen;
}