使用库函数 API 和 C 代码中嵌入汇编代码两种方式使用同一个系统调用。
1、阅读学习教材「庖丁解牛Linux 分析 」第5章,有问题优先使用chatgpt等AI工具。或者到蓝墨云班课中提问,24小时内回复,鼓励解答别人问题,提问前请阅读「如何提问」。
2、教材深入学习关注豆列「Linux内核及安全」。
3、学习蓝墨云班课中第五周视频「扒开系统调用的三层皮?(上)」,并完成实验楼上配套实验四。
1.直接调用库函数API
首先,进入github的torvalds/linux页面进行查看syscall_32.tbl文件。该文件即是系统调用列表文件,包含了一系列的定义,例如系统调用的编号、名称、参数列表和实现方法等等内容。在本实验,选择了getpid和getppid系统调用来实现直接调用库函数API。
getpid
是一个在Unix和类Unix操作系统上常见的系统调用,用于获取当前进程的进程ID(Process ID)。进程ID是一个唯一标识符,用于在系统中识别和管理不同的进程。通过调用 getpid
函数,程序可以获得它自己的进程ID,然后可以在进程间通信、进程管理等方面使用这个标识符。
C语言程序,直接调用getpid系统调用函数:
#include <stdio.h>
#include <unistd.h>
int main() {
pid_t pid, ppid;
// 获取当前进程的进程ID
pid = getpid();
// 获取当前进程的父进程ID
ppid = getppid();
printf("当前进程ID:%d\n", pid);
printf("父进程ID:%d\n", ppid);
return 0;
}
2.使用C代码中嵌入汇编代码
根据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;
asm volatile("mov $0x14, %%eax\n\t"
"int $0x80\n\t"
"mov %%eax, %0\n\t"
: "=r" (pid) :: "%eax");
asm volatile("mov $0x40, %%eax\n\t"
"int $0x80\n\t"
"mov %%eax, %0\n\t"
: "=r" (ppid) :: "%eax");
printf("pid=%d ppid=%d\n", pid, ppid);
return 0;
}
3、总结
在这个实验中,我们通过两种方式使用了同一个系统调用,具体来说是 getpid
系统调用。我们分别使用了库函数 API 和 C代码中嵌入汇编代码两种方式来调用这个系统调用。
-
使用库函数 API:
我们首先使用了标准C库提供的 API,即 getpid
函数。这种方式非常简单,只需包含相应的头文件 <unistd.h>
并调用 getpid()
函数即可。这种方式是高层次的抽象,隐藏了系统调用的底层实现细节,使得代码更加清晰和可读。
-
使用嵌入汇编代码:
其次,我们采用了一种更底层的方式,通过在C代码中嵌入汇编代码直接调用系统调用。这样做需要了解系统调用的调用约定和寄存器的使用,因为在汇编层面我们要手动设置寄存器来传递参数和获取返回值。
在实际开发中,通常会优先选择使用库函数 API,除非有特殊的需求需要直接操作底层。了解和掌握两种方式都有助于全面理解软件开发的不同层次。