这个程序调用了一个函数getpid(),用于获取当前进程的ID号。
|
2. getpid()是什么?在哪里声明?在哪里实现?
(1)getpid()是一个POSIX标准的API,用于用户程序从用户态进入到内核态,在内核态读取当前进程的(tack_struct)的Pid,然后
返回给用户态的程序。
(2)getpid()函数在/usr/include/unistd.h里面声明。你可以试着找到这个声明。
(3)getpid()函数在glibc函数库里面实现。gcc 编译程序时,会到glibc函数库里面寻找getpid()的实现代码,然后编译。
[是所有API都要进入内核态吗?NO.比如字符串函数strcpy()就不会进入内核态。要请求操作系统服务的API才进入内核态。]
3. getpid()是怎么使cpu进入内核态的?getpid()往内核传递了什么信息?从内核获得了什么信息?
(1)getpid()是通过软中断的方式使程序进入内核态的。getpid()编译成汇编代码时,里面会有条这样的指令:int 0x80,当执行到这条
指令时,getpid()的工作暂停,内核开始工作。
(2)getpid()的功能是返回当前进程的ID,它本身是不能完成的,必须请求操作系统服务,让操作系统把当前进程的ID告诉给getpid().
操作系统能够提供很多服务,那么,getpid()就得告诉操作系统提供什么服务,所以,getpid()给内核一个参数__NR_getpid(系统调用号),
把__NR_getpid这个服务号(系统调用号),放在了一个寄存器eax里面。内核就从eax这个寄存器里面取出值,就明白了:哦!原来getpid()是让
我提供__NR_getpid这个服务啊。[当API请求服务时,可能会告诉内核多个参数,这时就要把这些参数放在:
ebx --- 置第一个参数
ecx --- 置第二个参数
edx --- 置第三个参数
esi --- 置第四个参数
edi --- 置第五个参数
ebp --- 置第六个参数 (系统调用最大参数个数为6) [kjpioo注:实现在"include/asm-i386/unistd.h的“#define _syscall6 (......”处] ]
(3)getpid()自然从内核得到当前进程的ID号,因为内核已经把ID号放在了getpid()的堆栈里面。
getpid()是在glibc里面实现的。实现过程大概入下:
|
4. 内核是如何为getpid()提供服务的?具体过程是什么?
|
5. getpid()在eax寄存器栈单元里面取出pid,给用户程序。一切ok!