2023-2024-1 20232831《Linux内核原理与分析》第五周作业
目录
- 一、扒开系统调用的三层皮(上)
- 二、实验过程
- 1.直接调用库函数API
- 2.使用C代码中嵌入汇编代码
- 三、Chatgpt帮助
- 总结
1、阅读学习教材「庖丁解牛Linux 分析 」第5章,有问题优先使用chatgpt等AI工具。
2、教材深入学习关注豆列「Linux内核及安全」。
3、学习蓝墨云班课中第五周视频「扒开系统调用的三层皮?(上)」,并完成实验楼上配套实验四。
一、扒开系统调用的三层皮(上)
利用库函数 API 和 C 代码中嵌入汇编代码两种方式使用同一个系统调用。
二、实验过程
1.直接调用库函数API
首先,进入github的torvalds/linux页面进行syscall_32.tbl文件的查看。该文件即是系统调用列表文件,包含了一系列的定义,例如系统调用的编号、名称、参数列表和实现方法等等内容。在本实验,选择了getpid和getppid系统调用来实现直接调用库函数API。
getpid用于获取调用进程的进程标识号(Process ID,PID),而getppid用于获取调用进程的父进程的进程标识号(Parent Process ID,PPID)。getpid可以帮助进程识别自己的PID,以便执行特定的操作,如进程间通信、文件操作;而getppid允许进程了解其父进程的PID,这对于进程关系和进程间通信非常有用。
接下来直接编写一个C语言程序,直接调用getpid和getppid系统调用函数。代码如下所示:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(){
pid_t pid=getpid();
pid_t ppid=getppid();
printf("pid=%d ppid=%d\n",pid,ppid);
}
运行结果如下:
2.使用C代码中嵌入汇编代码
下面将进行C语言中使用asm volatile内嵌汇编代码来进行调用系统函数。根据上图的syscall_32.tbl文件可知,getpid和getppid的系统调用函数ID分别是20和64,对应十六进制数分别为0x14和0x40。因此可以进行代码修改,新建立一个C文件。
代码如下:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main() {
pid_t pid, ppid;
// 获取当前进程的PID(使用getpid)
asm volatile("mov $0x14, %%eax\n\t" // getpid 的ID为20
"int $0x80\n\t"
"mov %%eax, %0\n\t"
: "=r" (pid) :: "%eax");
// 获取当前进程的父进程的PID(使用getppid)
asm volatile("mov $0x40, %%eax\n\t" // getppid 的ID为64
"int $0x80\n\t"
"mov %%eax, %0\n\t"
: "=r" (ppid) :: "%eax");
printf("pid=%d ppid=%d\n", pid, ppid);
return 0;
}
同时运行2种方式的系统函数调用,发现结果类似,都得出了正确答案。
三、Chatgpt帮助
通过Chatgpt更深层次了解了getpid和getppid两个系统调用函数。
总结
本次实验通过两种方法——使用库函数 API 和内嵌汇编代码两种方法获取了进程的PID和父进程的PID(ppid)。库函数 API方法使用标准C库函数来调用系统调用,因为它封装了底层系统调用的细节,所以调用更加简单和高级。内嵌汇编方法通过内嵌汇编代码来手动执行系统调用,它通过程序员自行编写汇编代码,提供了对CPU指令的细粒度控制,更加复杂、困难一些。但两种方法都实现了相同的目标。
对系统调用的理解:系统调用是用户空间程序与操作系统内核之间的接口,允许用户程序请求内核执行特权操作,如文件操作、进程管理和网络通信。通过这次实验,让我加深了对系统函数调用的印象,它是用户程序与操作系统内核之间的通信桥梁。
普通网友: 写的很好,细节很到位!【我也写了一些相关领域的文章,希望能够得到博主的指导,共同进步!】
普通网友: 文章内容通俗易懂,适合不同层次的读者。【我也写了一些相关领域的文章,希望能够得到博主的指导,共同进步!】
普通网友: 干货满满,细节很到位!【我也写了一些相关领域的文章,希望能够得到博主的指导,共同进步!】
全栈小5: 欢迎学习交流
20232831袁思承: