- 设计目的与要求
采用编译内核法,在Linux中增加两个系统调用。
- 设计内容
- 系统调用实现的功能:
a.一个系统调用把输入的字符串保存到test.txt中;b.另一个系统调用读取test.txt中的内容。
(2)另外写一个程序进行调用。
- 设计设备与环境
8G内存笔记本电脑,VMware Workstation Pro,VMware-workstation-full-16.1.0-17198959,Linux-5.11.1。
- 报告正文
- 分析与设计思路
本题目需要更改Linux内核系统调用来实现对字符串在文件中的读和写,就需要更改或添加原有的系统调用来实现功能。要将系统调用号,系统调用函数声明和自定义的系统调用函数添加进入相应的文件中。
-
- 详细设计
- 首先下载并安装VMware Workstation Pro和VMware-workstation-full-16.1.0,运行虚拟机。
- 下载Linux内核Linux-5.11.1。
- 自定义系统调用函数,/usr/src/linux-5.1.11/kernel/sys.c。
- 添加系统调用函数申明, /usr/src/linux-5.1.1/include/linux/syscalls.h。
- 添加系统调用号,用 gedit 打开 /usr/src/linux-5.11.1/arch/x86/entry/syscalls/syscall_64.tbl
- 完成添加系统调用操作后,进行几个小时的内核编译,成功以后重启。
- 将.c文件编译并执行,查看txt文件内容,再用dmesg命令查看系统日志,就可以查看到文件读写的具体执行信息。
- 编程实现
- 自定义系统调用函数:
SYSCALL_DEFINE0(testread)
{
printk("testread executing");
struct file *filp;
struct inode *inode;
const char* filename="/usr/src/test.txt\0";
//mm_segment_t fs;
off_t fsize;
char *buf;
unsigned long magic;
printk("<1>start....\n");
filp=filp_open(filename,O_RDONLY,0);
inode=file_inode(filp);
magic=inode->i_sb->s_magic;
printk("<1>file system magic:%li \n",magic);
printk("<1>super blocksize:%li \n",inode->i_sb->s_blocksize);
printk("<1>inode %li \n",inode->i_ino);
fsize=inode->i_size;
printk("<0>file size:%i \n",(int)fsize);
buf=(char *) kmalloc(fsize+1,GFP_ATOMIC);
printk("buf correct\n");
//fs=get_fs();
printk("get_fs correct\n");
//set_fs(KERNEL_DS);
printk("set_fs correct\n");
kernel_read(filp,buf,fsize,&(filp->f_pos));
//set_fs(fs);
buf[fsize]='\0';
printk("<1>The File Content is:\n");
printk("<1>%s\n",buf);
filp_close(filp,NULL);
printk("testread end\n");
return 0;
}
SYSCALL_DEFINE2(testwrite,int,count,char __user *,string)
{
printk("testwrite executing");
struct file *filp;
char* filename="/usr/src/test.txt\0";
//mm_segment_t fs;
filp = filp_open(filename, O_RDWR|O_TRUNC, 0755);
if(IS_ERR(filp))
{
printk("open error...\n");
//return;
}
//fs=get_fs();
//set_fs(KERNEL_DS);
printk("writing\n");
char* buf;
buf = (char *)kmalloc(sizeof(char) * count, GFP_KERNEL);
if(!copy_from_user(buf, string, count))
{
printk("input is %s \n", buf);
}
kernel_write(filp, buf, strlen(buf),&filp->f_pos);
//set_fs(fs);
filp_close(filp,NULL);
printk("testwrite end\n");
return 0;
}
- 添加系统调用函数申明:
asmlinkage long sys_testread(void);
asmlinkage long sys_testwrite(int count,char __user* string);
- 添加系统调用号:
442 common testread sys_testread
443 common testwrite sys_testwrite
- .c文件:
#include<unistd.h>
#include<stdio.h>
#include<string.h>
#include<sys/syscall.h>
#include<linux/kernel.h>
int main()
{
long int a;
printf("this is testwr execution\n");
char string[120];
scanf("%s",string);
int length=strlen(string)+1;
a = syscall(443,length,string);
printf("a=%li\n",a);
printf("testwr end\n");
printf("this is testwr execution\n");
a = syscall(442);
printf("a=%li\n",a);
printf("testwr end\n");
return 0;
}
-
- 测试结果与分析
(1)执行.c文件,并且输入字符串:
- 执行dmesg命令:
可看出文件读写系统调用执行的详细信息。
- 查看test.txt文件内容:
程序执行正确。