fork 与竞争条件

2014-08-05 07:16:08   最后更新: 2014-08-05 07:16:08   访问数量:817




当多个进程都企图对共享数据进行某种处理,而最后的结果又取决于进程运行的顺序,则我们认为这发生了“竞争条件”,可以参考:进程间通信(IPC)

如果 fork 调用之后的某种逻辑显式或隐式地依赖于在 fork 之后是父进程先运行还是子进程先运行,那么 fork 函数很可能会引起竞争条件,因为通常情况下,我们不能预料哪一个进程先运行,即使知道哪个进程先运行,但那之后发生的事也依赖于系统负载及内核的调度算法

 

如下面的代码中

/* * file: wait.c * author: 龙泉居士 * date: 2013-05-27 14:00 */ #include "../apue.2e/include/apue.h" #include <sys/wait.h> int main () { pid_t pid; if ((pid = fork()) < 0) err_sys ("fork error"); else if (pid == 0) { if ((pid = fork()) < 0) err_sys ("fork error"); else if (pid > 0) exit(0); sleep(2); printf ("second child, parent pid = %d\n", getppid()); exit (0); } if (waitpid (pid, NULL, 0) != pid) err_sys ("waitpid error"); exit(0); }

 

 

这段代码通过两次调用 fork 避免了僵死进程,并且通过让子进程休眠以使父进程先运行

但是这之后父进程是否先运行这依然是不确定的,这就是一个潜在的竞争条件

如果第二个子进程在第一个子进程之前运行,则其父进程将会是第一个子进程,但是如果第一个子进程先运行,并且有足够的时间到达并执行exit,则第二个子进程的父进程就是init,但是这样的问题在大部分时间是不会出现的,所以很难排除

避免这个问题的方法可以是:

  1. 如果一个进程需要等待一个子进程终止,则他必须调用一种 wait 函数
  2. 如果一个子进程需要等待其父进程终止,则可以使用下面的循环:
while (getppid() != 1) sleep(1);

 

 

这种形式的循环称为“轮询”,但是这样的轮询浪费了CPU时间

为了避免竞争条件和轮询,在多个进程之间需要有某种形式的信号发送和接收的方法,在 UNIX 中可以使用信号机制,也可以使用各种形式的进程间通信(IPC)

 






读书笔记      技术帖      龙潭书斋      apue      unix环境高级编程      进程间通信      进程      fork      竞争条件      ipc     


京ICP备15018585号