APUE学习之---------------进程

       离职了,交接期也有足够的时间了,可以在好好的再看一下APUE,想想上次详细的看还是在两年之前,虽然中间也偶尔会翻出来看看,但是由于工作上交集相对比较少一直没有去细读一下。现在正好是一段空挡期可以好好看下书了。

       第八章之前是一些基础性的东西,如果需要的话可以在后面的文字中稍微提一下,主要还是从进程开始吧。进程的出现是必然的,看下计算机发展的过程可以发现,随着硬件性能的不断提升,我们也在不断改变软件的性能,这样两者的结合才能做到完美。单进程的模式在现在看来是无法想象的,多个软件不能并行的运行,只能一个一个的串行的运行,也就是说我在用一个看视频的时候没法使用浏览器进行上网。要是把现在的人拉到当时去感受一下单进程的话估计会疯掉。多进程的出现很完美的解决了这些问题。

      1.资源对多个进程是可用的。

      2.物理处理器可以在多个进程在切换以保证每个程序都在运行中。

      3.处理器和IO得到充分的利用。

Linus Torvalds写的Linux最初版本,只是打印AAA和BBB,让多个task同时工作充分理由计算机的硬件。最初的源码是汇编的我们也没必要去考证。现在的话我们还是来看看现在的Linux中关于一些多进程的模型以及IPC的方法吧。

1.Linux进程创建之fork, pid_t fork(void)

       从函数名字来看是一个很简单的名字那么执行这个函数之后做了写什么呢?首先子进程得到一个父进程的副本,这里的副本包括数据空间,堆和栈的副本,正文段的副本。fork之后子进程不是从main函数开始执行,而是从何父进程相同的位置执行(得到的父进程的副本里有一个指针指向当前执行的代码段),由于子进程没有执行fork,所以fork函数在克隆子进程,把子进程中返回的进程ID初始化成0。之后他们就是两个独立的进程了。

       不管是进程还是面向对象中的设计模式,你细细的看的话他的处理过程都来自于生活,感觉所有的过程都是在模拟和抽象一个人类具体生活过程,父进程子进程,父类子类,以及各种设计模式,在这里你多少都能看看到人的痕迹。有时候分析一个复杂的软件设计的时候我们可以从人是怎么处理类似的过程出发,然后抽象设计出这样的代码。

        继续回到进程相关的东西上,下面是一个简单的samplecode从这里的输出你可以看到父子进程的栈空间上的数据是相互独立的。

        int var = 88;
        pid_t pid = 0;
        
        if ((pid=fork()) < 0){
                printf("fork error");
        }
        else if (pid > 0){ //parent process
                var += 10;
                sleep(2);
                printf("value in parent process:%d\n", var);
        }       
        else {
                var -= 10;
                printf("value in child process:%d\n", var);     
        }
        return 0;

相应的输出为:

image

    2.父子进程之间的关系

   2.1 父进程先于子进程结束

         父进程的资源被释放,当前子进程的父进程设置init进程,这时的子进程也叫做孤儿进程(孤儿进程对系统是没有危害的)。下面是要给sample code。

        pid_t pid = 0;
        
        if ((pid=fork()) < 0){
                printf("fork error");
        }
        else if (pid > 0){ //parent process
                sleep(1); //child process execute first
        }       
        else {
                printf("befor parent exit ppid = %d\n", getppid());
                sleep(5);
                printf("after parent exit ppid = %d\n", getppid());
        }
        return 0;

     相应的输出为:

image

   2.2 子进程先于父进程结束

         子进程的资源被释放,但占用一个管理节点(用于父进程使用wait函数回收)。子进程给父进程发送SIGCHILD信号,如果父进程没有使用wait函数进行善后处理,那么这个进程就成了僵尸进程,他就永远的占用了系统的一些资源。下面是一个简单的sample code。使用ps可以查看到没有被回收的子进程的状态是Z(zombie)。

        pid_t pid = 0;
        
        if ((pid=fork()) < 0){
                printf("fork error");
        }
        else if (pid > 0){ //parent process
                sleep(100);
        }       
        else {
                printf("pid = %d\n", getpid());
        }
        return 0
相应的输出为:

          image

相应的如果使用wait函数了会是一个怎样的处理呢?

     如果一个进程已经终止,并且是一个僵尸进程,则wait立即返回并取得该进程的状态。否则wait使调用者阻塞直到一个子进程终止。如果有多个子进程的话可以考虑waitpid(pid_t pid, int *status, int option)。

posted on 2014-08-30 10:54  zkqian  阅读(587)  评论(0编辑  收藏  举报