1.进程标识符

  每个进程都有一个非负整数表示的唯一ID,叫做PID,用getpid()函数获取自身的进程标识符,调用getppid获取父进程的标识符

2.父进程、子进程

  进程A创建了进程B:那么A进程叫做父进程,B叫做子进程,父子进程是相对的概念,理解为人类中的父子进程。

  pid_t fork(void)函数:

    返回值:调用成功,在父进程中,子进程的PID作为函数的返回值。在子进程中,0作为函数的返回值。如果调用失败,则返回-1。

    fork调用之前,只有一个线程执行,调用之后,剩余的代码就是两个线程在执行了,fork函数调用一次,可以返回两次。

      返回值:1.在父进程中,fork返回新创建子进程的进程ID

          2.在子进程中,fork返回0

          3.如果出现错误,fork返回一个负值

3.fork的实际使用场景:

  一个父进程希望复制自己,使父子进程同时执行不同的代码段,在网络服务进程中是常见的---父进程等待客户端的服务请求。当这种请求到达时,父进程调用fork,使子进程处理此请求。父进程则继续等待下一个服务请求到达。

  一个进程要执行一个不同的程序。这对shell是常见情况。在这种情况下,子进程从fork返回后立即调用exec。

4.进程共享

  读时共享写时复制原则:父子进程间遵循读时共享写时复制的原则

 

5.孤儿进程、僵尸进程

  孤儿进程:父进程先于子进程结束,则子进程成为孤儿进程,子进程的父进程成为init进程,称为init进程领养孤儿进程。

  僵尸进程:子进程终止,父进程没有及时回收,子进程残留资源(PCB)存放于内核中,变成僵尸进程。

  如何解决:此时杀死父进程,父进程转变为init。init发现子进程是僵尸,自动回收。

6.wait/waitpid(注意:一次wait或者waitpid调用只能清理一个子进程,清理多个子进程应使用循环)

  一个进程在中止时会关闭所有文件描述符,释放在用户空间分配的内存,但他的pcb还保留着,内核在其中保存了一些信息:如果是正常中止则保存者退出状态,如果是异常终止则保存者导致该进程中止的信号是哪个。这个进程的父进程可以调用wait或waitpid获取这些信息,然后彻底清除掉这个进程。

  pid_t  wait(int  *status)函数原型及作用:

    1.阻塞等待子进程退出

    2.回收子进程残留资源

    3.获取子进程结束状态(退出原因)

    返回值:成功:清理掉的子进程ID;失败:-1.

7.宏函数判断中止原因:

  WIFEXITED(status)  红判断为真,表示程序正常退出

  WEXITSTATUS(status) 上一个宏判断为真 则返回状态值

  WIFSIGNALED(status) 宏判断为真 表示程序异常退出

  WTERMSIG(status) 上一个判断为真 则返回状态值

8.waitpid函数

  作用同wait,但可以指定pid进程清理,可以不阻塞。

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

  成功:返回清理掉的子进程ID;失败返回-1

  参数:

    pid:-1等待任一子进程;>0 等待其进程ID与pid相等的子进程; pid ==0 等待其组ID等于调用进程组ID任一子进程;PID <-1 等待其组ID等于pid绝对值的任一子进程。

    status:是一个整形数指针,非空:子进程退出状态放在它所指向的地址中。空:不关心退出状态

    option: WCONTINUED:若实现支持作业控制,那么由pid指定的任一子进程在暂停后已经继续,但其状态尚未报告,则返回其状态

        WNOHANG:若由pid指定的子进程并不是立即可用的,则waitpid不阻塞,此时其返回值为0

        WUNTRACED:若某实现支持作业控制,而由pid指定的任一子进程已处于暂停状态,并且其状态自暂停以来还未报告过,则返回其状态。WIFSTOPPED宏确定返回值是否对应于一个暂                                停子进程

 

   kill -9 父进程号    暴力回收子进程

9.exec函数族

  fork创建子进程后执行的是和父进程相同的程序,子进程往往要调用一种exec函数以执行另一个程序。当京城调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动历程开始执行。调用exec并不会创建新进程,所以调用exec前后该进程id并未改变。