系统调用 -- 哈工大李治军操作系统实验2
实验环境是 实验楼的 地址https://www.shiyanlou.com/courses/115
首先解压oslab下的压缩包 执行 tar zxvf +压缩包名字
1.首先修改oslab/linux-0.11/include下的linux文件
添加两个extern:
1 2 | extern int sys_iaml extern int sys_whoami |
添加sys_call_table表项:
1 | sys_iam,sys_whoami |
注:fn_ptr是函数类型指针
在include/linux/sched.h中定义
1 | typedef int (fn_ptr*)(); |
sys_call_table是中断服务程序调用系统调用要查的表。表项是函数指针,长度为4字节。中断服务程序执行call来调用系统调用:
1 | call _sys_call_table(,%eax, 4 ) //a(,%eax,4)=a+4*eax , 每个表项4字节所以第i个系统调用的偏移是i*4 |
2.linux-0.11/kernel下的system_call.s,将nr_system_calls修改为74(添加了两个系统调用)
3.修改kernel下的makefile文件,修改两处
1)添加who.o
2)添加一行
1 2 3 4 | who.s who.o: who.c ../include/linux/kernel.h ../include/unistd.h //图错了!!!! //图中who.o后面少了个冒号!!!! |
4.系统调用编号使用的宏定义,例如在unistd.g中 :
1 | #define NR_CLOSE 6 //close是sys_call_table第7个 |
添加系统调用需要修改unistd.h文件,不能直接在机器中修改而是在虚拟机文件系统中修改
oslab下的hdc-0.11-new.img是0.11内核启动后的根文件系统镜像文件,相当于在bochs虚拟机里装载的硬盘。在Ubuntu上访问其内容的方法是
$ sudo ./mount-hdc
之后,hdc目录下就是和0.11内核一模一样的文件系统了,可以读写任何文件(可能有些文件要用sudo才能访问),卸载这个文件系统:
$ sudo umount hdc
所以切换到oslab目录下执行sudo ./mount-hdc,然后切换到hdc下就会看到和linux一样的文件目录结构了。
切换到hdc/usr/include下,vim unistd.h
1 2 3 | Tip: 1 .命令模式下/__NR ---->命令模式下 /+要查找的字符可以快速定位,n是下一个,N是上一个 2 . ' __NR ' 的_是shift加-,这里有两个 '_' |
然后添加:
1 2 | #define __NR_iam 72 #define __NR_whoami 73 |
然后在linux-0.11/kernel下添加who.c,包含两个 系统调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | #define __LIBRARY__ #include <unistd.h> #include <errno.h><br>#include <asm/segment.h> char temp[ 64 ]={ 0 }; int sys_iam( const char * name) { int i= 0 ; while (get_fs_byte(name+i)!= '\0' ) i++; if (i> 23 ){ return -EINVAL; } printk( "%d\n" ,i); i= 0 ; while ((temp[i]=get_fs_byte(name+i))!= '\0' ){ i++; } return i; }<br> int sys_whoami( char * name,unsigned int size) { int i= 0 ; while (temp[i]!= '\0' ) i++; if (size<i) return - 1 ; i= 0 ; while (temp[i]!= '\0' ){ put_fs_byte(temp[i],(name+i)); i++; } return i; } |
5.然后编写iam.c和whoami.c 放在 hdc下的任意位置
1)whoami.c:
2)iam.c
然后执行 sudo umount hdc 解除挂载
最后切换到oslab下执行make
切换到oslab下执行./run运行虚拟机
切换到iam.c和whoami.c的目录执行
1 2 | gcc iam.c -o iam gcc whoami.c -o whoami |
总结:

main将eax寄存器置72(系统调用编号),触发int 0x80中断 (实际是在库函数中做的)
int 0x80指令查IDT表(中断向量表,由内核初始化)发现DPL=3 ,而CPL = 3(用户态)可以执行
于是将这个IDT表项的段选择子CS 给CS寄存器(例如段选择子为8H=1000,后两位为CPL,特权级别CPL置0),入口函数偏移给IP寄存器
然后执行中断服务程序,中断服务程序调用sys_whoami
sys_whoami里此时可以访问内核态数据(访问100地址的数据)
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 继承的思维:从思维模式到架构设计的深度解析
· 如何在 .NET 中 使用 ANTLR4
· 后端思维之高并发处理方案
· 理解Rust引用及其生命周期标识(下)
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· Cursor预测程序员行业倒计时:CTO应做好50%裁员计划
· 想让你多爱自己一些的开源计时器
· 大模型 Token 究竟是啥:图解大模型Token
· 用99元买的服务器搭一套CI/CD系统
· 当职场成战场:降职、阴谋与一场硬碰硬的抗争