实验四:使用库函数 API 和 C 代码中嵌入汇编代码两种方式使用同一个系统调用
一、直接调用库函数API
此处的系统调用文件是在目录/home/shiyanlou/LinuxKernel/linux-3.18.6/arch/x86/syscalls下的syscall_32.tbl。使用vim状态打开查看系统调用名以及对应的id
此处选择getpid系统调用函数
在c语言中直接使用getpid()函数获取对应相关的pid
#include <stdio.h>
int main(){
int pid=getpid(),ppid=getppid();
printf("pid=%d ppid=%d\n",pid,ppid);
}
对main20222806.c文件进行编译,直接运行可以看到获得了正确的pid
二、在C代码中嵌入汇编代码调用
使用asm volatile内嵌汇编调用系统函数,之前查询可知getpid()系统调用函数id是20,其对应十六进制数为0x14,因此需要将0x14赋值给eax寄存器,触发系统调用后执行第20号系统调用函数getpid(),并且将得到的结果复制给外面的变量ans
#include <stdio.h>
int main(){
int ans=-1;
asm volatile(
"mov $0x14,%%eax\n\t"
"int $0x80"
:"=r"(ans)
);
printf("pid=%d\n",ans);
}
可以看到结果上成功输出了pid号
三、实验结果分析:系统调用函数getpid分析
getpid的用处返回当前进程的pid,getpid()是一个POSIX标准的API,用于用户程序从用户态进入到内核态,在内核态读取当前进程的(tack_struct)的Pid。
getpid()是通过软中断的方式使程序进入内核态的。getpid()编译成汇编代码时,里面会有条这样的指令:int 0x80,当执行到这条指令时,getpid()的工作暂停,内核开始工作。返回给用户态的程序。getpid()的功能是返回当前进程的ID,它本身是不能完成的,必须请求操作系统服务,让操作系统把当前进程的ID告诉给getpid().操作系统能够提供很多服务,那么,getpid()就得告诉操作系统提供什么服务,所以,getpid()给内核一个参数__NR_getpid(系统调用号),把__NR_getpid这个服务号(系统调用号),放在了一个寄存器eax里面,内核就从eax这个寄存器里面取出值。