什么是进程?进程是一个运行中的程序实体,拥有独立的堆栈、内存空间和逻辑控制流。函数
这是标准的进程概念。让咱们经过操做系统的fork
函数看看这个抽象的概念是怎么在进程的实现中体现出来的。操作系统
建立一个进程,须要进程体、进程表和数据空间。指针
进程体在C代码中对应一个函数,编译成二进制代码后就是一组指令。code
进程表用来记录进程的进程ID、进程名称、寄存器快照空间。简单说,当中断发生时,会保存此刻CPU的状态,而后记录到进程表中。进程
进程表的做用就是用来存储进程快照。内存
进程堆栈的做用是什么?存储进程中函数的参数,存储进程运行过程当中的局部数据。字符串
数据空间呢?先看一段简单的代码。编译
char *f(int a, int b); int main(int argc, char **argv) { f(5, 6); return 0; } char *f(int a, int b) { int c = a + b; char *str = "Hello, World!"; return str; }
char *str
指向的内存中的数据STR存储在进程的数据空间中。为何STR不是存储在进程的堆栈中呢?class
函数f的返回值是STR的内存地址。执行这段代码,咱们会发现:调用函数f能正确得到STR。变量
试想一下,假如STR存储在进程的堆栈中,当f执行结束后,堆栈中的数据会被清空,咱们调用函数f是不能正确得到STR的。
STR存储在进程的数据空间中,存储在进程堆栈中的只是存储STR的内存空间的内存地址。
进程A调用fork新建进程B,A是B的父进程,B是A的子进程。
fork执行结束后,若是能成功建立B进程,B进程的数据空间、堆栈和进程表和A进程的这些要素彻底相同。
B进程毕竟是不一样于A进程的独立进程,因此:
猜猜看,子进程的堆栈是在进程表中仍是在数据空间中?
回答是:在进程的数据空间中。
在前面,咱们虽然把堆栈和数据空间分开说,那是为了强调两个要素在保存数据时的差别。堆栈中的数据随时变化,例如,进程中的一个函数执行结束,堆栈中的数据就会发生变化。
进程的数据空间呢?我觉得,当进程结束执行的时候,进程的数据空间中的数据才会消失。这是个人猜想,暂时不知道怎么去验证。
认为堆栈保存在数据空间中的依据是什么?由于寄存器ss
中的选择子指向的描述符描述的那段内存空间就是数据空间。
进程的ds、es、ss
的选择子相同,指向相同的数据空间。
每一个进程都有一个LDT。LDT存储在进程的进程表中。
在进程的进程表中,有一个LDT选择子。根据LDT选择子,能从GDT中找到指向LDT的描述符。
有点绕。连起来再说一次:经过进程表中的LDT选择子,从GDT中找到指向LDT的描述符,根据描述符找到LDT,LDT也在进程表中。