Download presentation
Presentation is loading. Please wait.
1
实验二:添加Linux系统调用及熟悉常见系统调用
助教:田成锦、汪睿、游翎璟 吴加禹、李佳伟、唐凯成
2
实验目的 学习如何添加Linux系统调用 熟悉Linux下常见的系统调用 2019/5/25
3
实验环境 主机:Ubuntu 32位 14.04 Linux内核版本:2.6.26 (内核版本最好是2.6.26,否则代码可能会有所不同)
本次实验是以实验一为基础,如有不熟悉的步骤,请重新浏 览实验一文档。 2019/5/25
4
实验内容——1.添加Linux系统调用 需要添加两个系统调用,与如下形式类似 void print_val(int a);
//通过printk在控制台打印如下信息(假设a是1234) // in sys_print_val: 1234 void str2num(char *str, int str_len, int *ret); //将一个有str_len个数字的字符串str转换成十进制数字,然后将结果写到ret指向的地址中 2019/5/25
5
实验内容——1.添加Linux系统调用 分配系统调用号
在Linux源代码根目录下,找到include/asm-x86/unistd_32.h,在文件 末尾仿照已分配的系统调用号新增自己的两个系统调用号。 #define __NR_utimensat 320 #define __NR_signalfd 321 #define __NR_timerfd_create 322 #define __NR_eventfd 323 #define __NR_fallocate 324 #define __NR_timerfd_settime 325 #define __NR_timerfd_gettime 326 //在此添加 2019/5/25
6
实验内容——1.添加Linux系统调用 修改系统调用表
为了让系统能根据系统调用号找到syscall_table中的相应表项,找到 arch/x86/kernel/syscall_table_32.s,仿照原格式添加系统调用号和调 用函数的对应关系。 注意系统调用函数名字应该以"sys_"开头。 long sys_timerfd_create .long sys_eventfd .long sys_fallocate .long sys_timerfd_settime /* 325 */ .long sys_timerfd_gettime //在此添加 2019/5/25
7
实验内容——1.添加Linux系统调用 实现系统调用函数
在include/linux/syscalls.h中声明新增的两个系统调用函数。注意 sys_str2num的声明中指针参数需要有"__user"宏. asmlinkage long sys_timerfd_gettime(int ufd, struct itimerspec __user *otmr); asmlinkage long sys_eventfd(unsigned int count); asmlinkage long sys_fallocate(int fd, int mode, loff_t offset, loff_t len); //在此添加 2019/5/25
8
实验内容——1.添加Linux系统调用 实现系统调用函数 在kernel/sys.c中实现新增的两个系统调用函数。
(注意:函数实现的头部与函数声明保持一致!) 提示:sys_str2num的实现中需要利用copy_from_user和copy_to_user 函数。(注意n的大小) unsigned long copy_from_user(void * to, const void __user * from, unsigned long n); unsigned long copy_to_user(void __user *to, const void *from, unsigned long n); 2019/5/25
9
实验内容——1.添加Linux系统调用 编译内核 执行下面命令编译内核 make i386_defconfig make 2019/5/25
10
实验内容——1.添加Linux系统调用 编写测试程序
创建一个简单的用户程序验证已实现的系统调用正确性,要求能够 从终端读取一串数字字符串,通过str2num系统调用将其转换成数字, 然后通过print_val系统调用打印该数字。执行用户程序后需要有如 下输出: 提示:通过syscall函数执行系统调用 Give me a string: in sys_print_val: 78234 long int syscall (long int sysno, ...); //sysno为系统调用号,后面跟若干个系统调用函数参数,参数个数与其原型一致 2019/5/25
11
实验内容——1.添加Linux系统调用 运行测试程序 利用实验一中的busybox生成根文件系统。 使用GCC静态编译用户程序
并将可执行文件test复制到busybox下的_install目录下,重新打包该 目录生成新的cpio.gz文件 运行qemu进入shell环境后,输入./test,执行用户程序。 gcc –static test.c –o test 2019/5/25
12
实验内容——2.熟悉常见的系统调用 熟悉以下系统调用的用法
pid_t fork(); //创建进程 pid_t waitpid(pid_t pid,int* status,int options); //等待指定pid的子进程结束 int execv(const char *path, char *const argv[]); //根据指定的文件名或目录名找到可执行文件,并用它来取代原调用进程的数据段、代码段和堆栈段,在执行完之后,原调用进程的内容除了进程号外,其他全部被新程序的内容替换了 int system(const char* command); //调用fork()产生子进程,在子进程执行参数command字符串所代表的命令,此命令执行完后随即返回原调用的进程 FILE* popen(const char* command, const char* mode); //popen函数先执行fork,然后调用exec以执行command,并且根据mode的值("r"或"w")返回一个指向子进程的stdout或指向stdin的文件指针 int pclose(FILE* stream); //关闭标准I/O流,等待命令执行结束 2019/5/25
13
实验内容——2.熟悉常见的系统调用 利用上面的系统调用函数实现一个简单的shell程序
每行命令可能由若干个子命令组成,如"ls -l; cat 1.txt; ps -a",由“;” 分隔每个子命令,需要按照顺序依次执行这些子命令。 每个子命令可能包含一个管道符号“|”,如"cat 1.txt | grep abcd"(这 个命令的作用是打印出1.txt中包含abcd字符串的行),作用是先执 行前一个命令,并将其标准输出传递给下一个命令,作为它的标准 输入。 最终的shell程序应该有类似如下的输出: OSLab2->echo abcd;date;uname -r abcd Mon Apr 8 09:35:57 CST OSLab2->cat 1.txt | grep abcd 123abcd abcdefg 2019/5/25
14
实验内容——2.熟悉常见的系统调用 利用上面的系统调用函数实现一个简单的shell程序 程序的大致的框架如下
int main(){ char cmdline[256]; while (1) { printf("OSLab2->"); //读取一行字符串并根据“;”将其划分成若干个子命令 for (i=0; i < cmd_num; i++) { if () { //处理包含一个管道符号“|”的情况,利用popen处理命令的输入输出转换 } else { //通常的情况,利用fork创建子进程并执行命令 } } } return 0; } 2019/5/25
15
验收方式 现场验收 实验内容一 实验内容二 向助教展示修改的文件以及测试程序 在qemu中运行测试程序 向助教展示编写的测试程序
2019/5/25
16
报告提交方式 将实验报告、自己修改的所有代码文件,打包为压缩包提交 (请勿打包整个内核文件)
邮件主题、文件名称、压缩包名称 均采用以下格式命名 x-学号-姓名(x:代表第x次实验) 例如张三的第1次实验命名为“1-PB 张三” 未按照规范命名的邮件会被忽略、删除 2019/5/25
Similar presentations