关于Linux多进程

时间:2021-12-13 11:33:44

    今天看了《Linux高级程序设计》中有关进程的部分,在这里仅写一下自己的理解,望大家多多指教。总体感觉跟Windows上的进程不太一样,初次学习时甚至搞不懂程序是怎么运行的,其中最让我不能理解的是父、子进程竟然在一个函数中运行。其中有这样一个例子:
    int main(void)
    {
        pid_t pid = fork();
        if (pid == -1)
        {
            printf("fork error");
        }
        else if (pid == 0)
        {
            printf("in the child process");
        }
        else
        {
            printf("in the parent process");
        }
        return 0;
    }
    在上面的程序中,通过fork函数创建了一个进程,但并没有像Windows程序中通过CreateProcess创建进程那样启动另外一个新的程序,而是在fork后开始有两个进程在运行同一份代码,上面程序只是通过fork的返回值判断该运行父进程还是子进程的代码。之前在Linux的多进程时,就被这一点给弄糊涂了,硬是没搞懂程序是怎么运行的,通过亲手编写代码测试后才真正理解这是怎么一回事。
    在fork函数之前,只有一个进程(即父进程)在运行,当调用fork成功后,就会出现新的进程(即子进程)从fork的下一句代码开始执行,而父进程则继续原来的执行,也是fork的下一句代码。fork只是创建的一个进程,无法控制该进程去执行特定的代码,所以在程序中通常通过fork的返回值来判断下一步该执行什么操作。在父进程中,fork将返回新创建的子进程的PID,而在子进程中,这个返回值为0。子进程创建成功后,会复制父进程的几乎所有信息,包括副进程的代码段、数据段、堆、栈以及PCB等信息。我的理解是,栈中在fork函数之前的所有数据在父子进程中都是相同的,从fork开始,即fork的返回值,父子进程就拥有了各自独立的进程空间了。对于一些内核对象的句柄,如打开的文件、SOCKET、管道等,同样会复制到子进程中,而且父子进程中的句柄指向内核中相同的对象,对于文件,它们共享文件指针、偏移、权限等,且在父子进程中需要分别关闭这些句柄。这些特性是在Windows上使用CreateProcess无法做到的。
    另外,Linux提供了exec系列的函数,如execl、execp等,它们用来在进程中运行新代码,即运行其他的程序,这一点似乎和Windows的CreateProcess相同。但是,CreateProcess是创建一个新的进程来运行新程序,可以选择等待新进程退出或继续执行本程序代码。而exec系列函数并不创建新进程,而仅仅将新程序的资源加载到内核中并执行新的代码,新程序的代码运行结束后才会回到原有程序继续执行,即exec函数的下一句代码。如果要实现CreateProcess类似的功能,则需要使用fork函数创建一个新进程,然后在子进程中调用exec系列函数执行新的程序。
    进程退出后,会自动释放用户控件的所有资源,如执行退出处理函数、刷新流缓冲区等,但是进程内核控件的资源,如PCB,并没有释放,它只能由父进程完成,在父进程中调用wait、waitpid等待所有或指定进程退出,并回收子进程的内核进程资源。如果父进程比子进程早退出,那么子进程的父进程会更改为系统的init进程,它会在子进程退出时回收子进程的内核空间资源。

本文出自 “Jsl_mes” 博客,请务必保留此出处http://jslmes.blog.51cto.com/5008224/1196081