LINUX C 语言--进程管理(一)

来源:互联网 发布:淘宝格子铺怎么入驻 编辑:程序博客网 时间:2024/05/01 01:18
子进程和父进程的开始与结束

     子进程结束的时候会向父进程发送信号,让父进程帮助回收进程

     父进程先结束的时候,子进程会过继到init进程下(即指定init进程为新的父进程)

     如果父进程因为各种原因没有收到子进程发送的信号,则无法回收子进程的资源,子进程会成为僵尸进程

子进程与父进程的资源
     
     进程的内存区划分:代码区、全局区,堆区,代码区
    
     子进程中的资源得到的是父进程的一份拷贝,(包括全局区,栈区,堆区) ,代码区与父进程共享

子进程资源的回收
     
     pid_t wait(int * status);

     相当于waitpid(-1,&status,0);

     pid_t waitpid(pid_t pid,int * status, int options);

    关于pid的参数
          < -1 等待所有组id等于pid的绝对值的子进程
          = -1 等待所有子进程
          = 0   等待所有组id等于父进程组id的子进程
          > 0   等待pid为pid的子进程
     关于options的参数
          WHONG          :如果没有子进程结束的话立刻返回
          WUNTRACED   :
          WCONTINUED
     返回值:
          正常返回pid
          错误返回-1 如果所有子进程都已经回收完毕 errno会被设置为    ECHILD

进程的创建
1.  fork  ():子进程拷贝父进程的数据段,代码段
    vfork ( ):子进程与父进程共享数据段
2.  fork ()父子进程的执行次序不确定
    vfork 保证子进程先运行,在调用exec 或exit 之前与父进程数据是共享的,在它调用exec
     或exit 之后父进程才可能被调度运行。
3.  vfork ()保证子进程先运行,在她调用exec 或exit 之后父进程才可能被调度运行。如果在
   调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。

进程的终止
     正常的终止方式
     a.在main函数中执行了return 0;
     b.调用exit()函数终止进程
     c.调用_exit()/_Exit()函数终止进程
     d.最后一个线程返回
     e.最后一个线程调用了pthread_exit()函数
     非正常的终止方式
     a.采用信号终止进程,ctrl+c
     b.最后一个线程被其他线程调用了pthread_cancel()取消

     atexit(void (* func)(void));注册一个在退出的时候执行的函数
     注册的函数将在exit或者return时调用
     如果使用_exit()/_Exit()时将不会调用注册的函数
    
进程管理
     wait 函数用于挂起当前正在运行的进程,进入阻塞状态,等待子进程的状态改变(终止)
     pid_t     wait(int * status)参数用于获取子进程改变的状态
     成功返回所等到的子进程的状态,失败返回-1


扩展
     调用fork的次数和生成的子进程数量为 2的n次方

     创建三个进程

     fork();
     if(0!=pid)
     {
          fork();
     }

     waitpid回收子进程,不包括子进程的子进程

     我们创建如下子进程

     pid_t p1,p2;
     p1 = fork();
     if(0 == p1)
     {
          printf("child of child ,pid is  %d\n",fork());
          _exit(0);
     }     
     if(0 == p2)
     {
            printf("child of child ,pid is  %d\n",fork());  
          _exit(0);
     }

     while(1){
          pid_t  pres = waitpid(-1,NULL,WNOHANG);
          if(pres < 0)
          {
               if(errno != ECHILD)
               {
                    perror("waitpid");
                    _exit(-1);
               }
               printf("all child was died\n");
          }
          else if(pres)
          {
              printf("child %d was died \n",pres); 
          }else
          {
               printf("do some thing....\n");
               sleep(1);
          }
     }

output:

输出结果可以得出只回收了有主进程创建的两个子进程,而由子进程创建的子进程并没有被回收
0 0