前面我们说明了进程等待的必要性,父进程通过进程等待,来回收子进程的资源,并且得知子进程的运行状态,下面我们接着谈谈wait和waitpid
我们先看看wait和waitpid的函数声明
- #include
/* 提供类型pid_t的定义*/ -
- #include
-
- int wait(int *status)
- #include
- #include
- 定义函数 pid_t waitpid(pid_t pid,int * status,int options);
这两个函数有相似的功能,我们以waitpid来举例说明
waitpid一共有三个参数
第一参数pid,它通常有两种赋值方式,-1,和pid > 0
-1就是等待该进程的任意一个子进程
> 0就是等待特定的进程,这个特定的进程也就是我们所要填入的pid值
第二个参数是status,它是一个输出型参数,主要是用来获取子进程的状态信息
如果子进程是正常跑完了它的代码,那么它的退出码是有意义的
如果子进程遇到了崩溃等其它情况,使它的代码没有跑完,那么它的退出码就没有意义,这时我们要看它的退出信号
上一篇文章已经说明过一种获取进程退出码和退出信号的方法了
接下来我们再说明另一种更加优雅的方式获取进程状态信息
使用两个宏函数来解决
WIFEXITED(status)
这个是用来检测子进程是否正常退出的,如果为true证明子进程是正常退出的,反之就没有正常退出
另一个宏函数是
WEXITSTATUS(status)
这个宏是用来获取子进程的退出码的
第三个参数options它也有两种赋值方式,0和WNOHANG
它默认是0,0代表着父进程阻塞式的等待子进程
换句话说是父进程不能再执行其它代码直到等待子进程退出
在操作系统上说是父进程被操作系统从运行队列上换下,放到阻塞队列或者等待被操作系统调度
这种方法是十分的不好的,创建子进程就没有什么意义了
另一种赋值方式就是WNOHANG这种方法就十分的好
它会检测子进程的退出状态,如果返回的是子进程的pid证明子进程已经退出
返回值是0证明子进程没有退出,还在运行
返回值是-1证明出错了
根据上面的解释也就是说,如果waitpid填入的是WNOHANG父进程调用一次检测一次子进程的状态,所以我们要不停的检测直到子进程退出或者其它情况。
在下一次调用waitpid的间隙,我们可以让父进程进行其他任务
下面有一个小例子
- #include
- #include
- #include
- #include
- #include
- #include
-
- using namespace std;
-
-
- typedef void (*handler_t)();
-
- std::vector<handler_t> handlers;
-
- void func_one()
- {
- std::cout << "这是临时任务1" << std::endl;
- }
-
- void func_two()
- {
- std::cout << "这是临时任务2" << std::endl;
- }
-
- void Load()
- {
- handlers.push_back(func_one);
- handlers.push_back(func_two);
- }
-
- int main()
- {
- pid_t id = fork();
-
- if(id < 0)
- {
- perror("fork");
- exit(1);
- }
- }
- else if(id == 0)
- {
- int cnt = 5;
- while(cnt--)
- {
- cout << "我是子进程" << cnt << getpid() << endl;
- sleep(1);
- }
- }
- else
- {
- int status = 0;
- int quit = 0;
- cout << "我是父进程" << endl;
- while(!quit)
- {
- cout << "父进程等待子进程中" << endl;
- pid_t res = waitpid(-1, &status, WNOHANG);
- if(res > 0)
- {
- cout << "等待子进程成功" << endl;
- cout << "子进程退出码为" << WEXITSTATUS(status) << endl;
- quit = 1;
- }
- else if(res == 0)
- {
- cout << "子进程还在运行" << endl;
- if(handlers.empty())
- {
- Load();
- }
-
- for(auto iter : handlers)
- {
- iter();
- }
- }
- else
- {
- cout << "出错了" << endl;
- quit = 1;
- exit(1);
- }
- sleep(1);
- }
- }
-
- return 0;
- }
以上就是今天要讲的内容,本文仅仅简单介绍了waitpid的使用。