系统调用
实验过程
- 修改
include/unistd.h,增加iam和whoami系统调用号。

- 修改
kernel/system_call.s,将系统调用总数由72改为74。

- 修改
include/linux/sys.h,添加sys_whoami和sys_iam。


- 在
kernel/目录下创建who.c文件。who.c见code/目录。 - 修改
kernel/目录下的Makefile文件。

- 在
linux-0.11目录下执行make all命令,重新编译内核。 - 编写
whoami_test.c和iam_test.c测试文件,见code/目录。 - 挂载
Linux 0.11的文件系统hdc,将whoami_test.c、iam_test.c、testlab2.c和testlab2.sh共4个文件移动到hdc/usr/root/。 - 运行
Bochs,进入Linux 0.11。编译运行 C语言测试文件,运行Shell测试文件。 - 若报错:

则是因为Linux 0.11文件系统中的/usr/include/unistd.h没有对应调用号,添加即可。

实验结果

实验报告
从 Linux 0.11 现在的机制看,它的系统调用最多能传递几个参数?

从include/unistd.h可以看出,总共有4个系统调用的宏定义:
_syscall0:无参数。_syscall1:1个参数。_syscall2:2个参数。_syscall3:3个参数。
所以,如果不算系统调用的编号的话,最多能传递 3个参数,分别通过寄存器ebx,ecx,edx传递。
你能想出办法来扩大这个限制吗?
我的想法是,3个参数可以分别用来存放 指向参数的指针、指向参数大小的指针和参数的数量。
这样,参数的大小可以用一个字节来表示,因此,可以通过递增第二个参数的值来获取每个参数的大小。同时,第一个参数(参数指针)会根据第二个参数(参数大小)所指示的值进行移动,以便获取每个参数的值。最终,在第三个参数(参数数量)的限制下,取得所有的参数。
这种设计使得系统调用能够接收任意数量和类型的参数。
用文字简要描述向 Linux 0.11 添加一个系统调用 foo() 的步骤。
- 在
include/unistd.h中为foo()增加系统调用号。例如,如果当前系统调用的数量为72,那么foo()的系统调用号可以定义为73。 - 修改
kernel/system_call.s中的系统调用总数。例如,如果当前系统调用的数量为72,那么添加foo()后,系统调用的总数应该修改为73。 - 在
include/linux/sys.h中的sys_call_table函数表中增加foo()的函数引用,使用extern声明系统调用函数,比如extern int sys_foo();。 - 在
kernel/目录下创建foo.c文件,实现foo()函数。这个函数将会在系统调用foo()时被执行。 - 修改
kernel/目录下的Makefile文件,使得在编译内核时能够编译foo.c文件。 - 在
linux-0.11目录下执行make all命令,重新编译内核。
源代码
iam_test.c
#define __LIBRARY__
#include <unistd.h>
_syscall1(int, iam, const char*, name);
int main(int argc, char* argv[])
{
iam(argv[1]);
return 0;
}
who.c
#include <string.h>
#include <asm/segment.h>
#include <errno.h>
#include <linux/kernel.h>
char my_name[24] = {0};
int sys_iam(const char* name)
{
printk("<sys_iam>\n");
char temp_name[24];
unsigned int i = 0;
for (i = 0; i < 24; i = i + 1)
{
temp_name[i] = get_fs_byte(name + i);
if (temp_name[i] == '\0') break;
}
if (i == 24 && temp_name[23] != '\0')
{
return -EINVAL;
// _syscall1
}
strcpy(my_name, temp_name);
return i;
}
int sys_whoami(char* name, unsigned int size)
{
printk("<sys_whoami>\n");
unsigned name_len = strlen(my_name);
if (name_len > size) {
return -EINVAL;
}
unsigned int i = 0;
for (i = 0; i < name_len; i = i + 1)
{
put_fs_byte(my_name[i], name + i);
}
return name_len;
}
whoami_test.c
#define __LIBRARY__
#include <unistd.h>
#include <stdio.h>
_syscall2(int, whoami, char*, name, unsigned int, size);
int main()
{
char username[32] = {0};
int username_len = whoami(username, 31);
printf("%s\n",username);
}
本文来自博客园,作者:江水为竭,转载请注明原文链接:https://www.cnblogs.com/Az1r/p/17955540

浙公网安备 33010602011771号