- 阻塞:顾名思义,就是进程或是线程执行到这些函数时必须等待某个事件的发生,如果事件没有发生,进程或线程就被阻塞,函数不能立即返回。
- 非阻塞:就是进程或线程执行此函数时不必非要等待事件的发生,一旦执行肯定返回,以返回值的不同来反映函数的执行情况,如果事件发生则与阻塞方式相同,若事件没有发生则持续返回一个值来告知事件未发生,进程或线程继续执行,直到事件发生才为最后一次返回。
- 这里我们就以waitpid()函数为例来解析阻塞与非阻塞:
- waitpid()函数原型为: pid_t waitpid(pid_t pid, int *status, int options);
- pid : 当pid>0时为要回收子进程的pid ; pid = -1 时回收所有子进程; pid = 0时回收进程组所有子进程。
- status : 进程的退出状态,如何退出的。一般我们设置为NULL,除非要知道退出状态才会去获取。
- options:调节waitpid函数为阻塞(0) 和非阻塞(WNOHANG)。
- 当为阻塞状态时 options 为 0,返回值 > 0 为回收的子进程 pid,返回值 < 0 则没有要回收的子进程。
- 当为非阻塞状态时,如果返回值 = 0 ,子进程处于运行状态,否则返回被回收子进程pid。
- waitpid()函数原型为: pid_t waitpid(pid_t pid, int *status, int options);
非阻塞代码:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<sys/stat.h>
void main()
{
int num = 3;
int i = 0;
pid_t pid;
for(; i < num; i++)
{
pid = fork();
if(pid == 0)
{
break;
}
}
if(i == 0)
{
printf("%d\n",getpid());
printf("hello\n");
exit(0);
}
else if(i == 1)
{
printf("%d\n",getpid());
printf("world\n");
exit(0);
}
else if(i == 2)
{
printf("%d\n",getpid());
printf("welcome\n");
exit(0);
}
else
{
pid_t wpid;
while((wpid = waitpid(-1, NULL, WNOHANG)) != -1)
{
printf("回收的子进程pid为:%d\n",wpid);
}
}
}
- 运行结果:
为0的都为非阻塞返回的,此时的子进程正在运行。
当我们将其换成阻塞运行时:
即改变为:while((waitpid = (-1, NULL, 0)) != -1)
此时的运行结果为:
可以看出,此时waitpid回收子进程时是等到其结束时才返回的,这与非阻塞的一直返回不同。
- 阻塞与非阻塞的区别就在与阻塞要等待事件发生才进行下一步动作,非阻塞不用等待,直接进行下一步动作。