进程
在linux中利用fork创建子进程,当子进程结束的时候,会产生僵尸进程,该僵尸进程会有保留一些内核的数据结构,供父进程查看子进程的状态;因此就有了wait与waitpid
wait(int *status)
用于父进程等待子进程,当子进程结束的时候,父进程才会被使用,相当于父进程被阻塞了;,同时其status用于父进程查询子进程当前是什么状态
wait获取staus后检测处理
宏定义 描述
WIFEXITED(status) 如果进程子进程正常结束,返回一个非零值
WEXITSTATUS(status) 如果WIFEXITED非零,返回子进程退出码
WIFSIGNALED(status) 子进程因为捕获信号而终止,返回非零值
WTERMSIG(status) 如果WIFSIGNALED非零,返回信号代码
WIFSTOPPED(status) 如果进程被暂停,返回一个非零值
WSTOPSIG(status) 如果WIFSTOPPED非零,返回信号代码
waitpid(pid_t pid,int *status,int options)
用于等待指定的子进程,当子进程结束的时候,父进程才会被调用
- pid > 0; 不用管其他子进程,只要该pid还没有结束,父进程就不会结束;
- pid = -1; 等待任何一个子进程,此时waitpid和wait的作用一模一样
- 等待同一个进程组中的任何子进程,如果子进程已经加入了别的进程组,waitpid不会对它做任何理睬。
- pid<-1时,等待一个指定进程组中的任何子进程,这个进程组的ID等于pid的绝对值。
options允许改变waitpid的行为,最有用的一个选项是WNOHANG,它的作用是防止waitpid把调用者的执行挂起 返回值:成功返回等待子进程的pid,失败返回-1
wait使用
#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
using namespace std;
int main()
{
int i = 0;
cout<<"before fork"<<endl;
pid_t pid = fork();
cout<<"after fork"<<endl;
if(pid < 0)
{
cout<<"error"<<endl;
return 1;
}
else if(pid == 0)
{
cout<<"fork sucess, this is son process"<<endl;
while(i < 10)
{
i += 1;
cout<<"this is son process, i = "<<i<<endl;
sleep(1);
}
}
else
{
int flag;
pid_t p = wait(&flag); // 当子进程结束的时候,父进程才会调用,或者有信号来的时候父进程才会调用
cout<<"fork sucess, this is father process, son process pid="<<pid<<endl;
while(i < 10)
{
i += 2;
cout<<"this is father process i="<<i<<endl;
sleep(2);
}
i = WEXITSTATUS(flag); // 判断是否存在
cout<<"i:"<<i<<"flag:"<<flag<<"p:"<<p<<endl;
}
cout<<"process destroy"<<endl;
return 0;
}
运行结果, 等待父进程结束才运行
before fork
after fork
after fork
fork sucess, this is son process
this is son process, i = 1
this is son process, i = 2
this is son process, i = 3
this is son process, i = 4
this is son process, i = 5
this is son process, i = 6
this is son process, i = 7
this is son process, i = 8
this is son process, i = 9
this is son process, i = 10
process destroy
fork sucess, this is father process, son process pid=5170
this is father process i=2
this is father process i=4
this is father process i=6
this is father process i=8
this is father process i=10
i:0flag:0p:5170
process destroy
waitpid
先举个例子,当创建多个进程的时候,多个子进程与主进程同时运行
#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <vector>
using namespace std;
pid_t create_fork()
{
int i = 0;
pid_t pid = fork();
if(pid == 0) // 此时为子进程的内容
{
cout<<"fork sucess, this is son process, pid="<<getpid()<<endl;
while(i < 2)
{
i += 1;
cout<<"this is son process, i = "<<i<<" pid = "<<getpid()<<endl;
sleep(1);
}
exit(1); // 子进程运行完之后直接结束
}
else if(pid > 0)
{
//wait(NULL); // 先结束子进程中的内容
return pid;
}
else
{
perror("error");
}
}
int main()
{
pid_t p;
for(int i = 0; i < 4; ++i)
{
create_fork();
}
int i = 0;
while(i < 10)
{
i += 2;
cout<<"this is father process i="<<i<<endl;
sleep(2);
}
cout<<"process destroy"<<endl;
return 0;
}
运行内容如下:
fork sucess, this is son process, pid=6662
this is son process, i = 1 pid = 6662
fork sucess, this is son process, pid=6663
this is son process, i = 1 pid = 6663
this is father process i=2
fork sucess, this is son process, pid=6664
this is son process, i = 1 pid = 6664
fork sucess, this is son process, pid=6665
this is son process, i = 1 pid = 6665
this is son process, i = 2 pid = 6662
this is son process, i = 2 pid = 6663
this is son process, i = 2 pid = 6664
this is son process, i = 2 pid = 6665
this is father process i=4
this is father process i=6
this is father process i=8
this is father process i=10
process destroy
此时没有使用waitpid,接下来修改相应的内容,当指定的子进程结束之后主进程才会运行。
修改每一个进程的睡眠时间,该内容让主进程保持第一个进程的pid,只有当第一个进程结束之后,主进程才会可以运行;
#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <vector>
using namespace std;
pid_t create_fork(int time)
{
int i = 0;
pid_t pid = fork();
if(pid == 0) // 此时为子进程的内容
{
cout<<"fork sucess, this is son process, pid="<<getpid()<<endl;
while(i < 2)
{
i += 1;
cout<<"this is son process, i = "<<i<<" pid = "<<getpid()<<endl;
sleep(time);
}
cout<<"fork destroy pid = "<<getpid()<<endl;
exit(1); // 子进程运行完之后直接结束
}
else if(pid > 0)
{
//wait(NULL); // 先结束子进程中的内容
return pid;
}
else
{
perror("error");
}
}
int main()
{
pid_t p;
for(int i = 0; i < 5; ++i)
{
pid_t temp = create_fork(i);
if(i == 0)
{
p = temp;
}
}
if(waitpid(p, NULL, 0))
{
int i = 0;
while(i < 10)
{
i += 2;
cout<<"this is father process i="<<i<<endl;
sleep(2);
}
}
cout<<"process destroy"<<endl;
return 0;
}
结果如下,可以发现第一个经常destroy之后,主进程就开始了运行;
fork sucess, this is son process, pid=6769
this is son process, i = 1 pid = 6769
this is son process, i = 2 pid = 6769
fork destroy pid = 6769
fork sucess, this is son process, pid=6770
this is son process, i = 1 pid = 6770
fork sucess, this is son process, pid=6771
this is son process, i = 1 pid = 6771
this is father process i=2
fork sucess, this is son process, pid=6772
this is son process, i = 1 pid = 6772
fork sucess, this is son process, pid=6773
this is son process, i = 1 pid = 6773
this is son process, i = 2 pid = 6770
fork destroy pid = 6770
this is son process, i = 2 pid = 6771
this is father process i=4
this is son process, i = 2 pid = 6772
fork destroy pid = 6771
this is son process, i = 2 pid = 6773
this is father process i=6
fork destroy pid = 6772
this is father process i=8
fork destroy pid = 6773
this is father process i=10
process destroy
接下来修改代码,也就是说当最后一个进程执行完之后,主进程才会执行;
if(i == 4 ) // 将i 该为4
{
p = temp;
}
运行结果如下
fork sucess, this is son process, pid=6823
this is son process, i = 1 pid = 6823
this is son process, i = 2 pid = 6823
fork destroy pid = 6823
fork sucess, this is son process, pid=6824
this is son process, i = 1 pid = 6824
fork sucess, this is son process, pid=6825
this is son process, i = 1 pid = 6825
fork sucess, this is son process, pid=6826
this is son process, i = 1 pid = 6826
fork sucess, this is son process, pid=6827
this is son process, i = 1 pid = 6827
this is son process, i = 2 pid = 6824
this is son process, i = 2 pid = 6825
fork destroy pid = 6824
this is son process, i = 2 pid = 6826
fork destroy pid = 6825
this is son process, i = 2 pid = 6827
fork destroy pid = 6826
fork destroy pid = 6827
this is father process i=2
this is father process i=4
this is father process i=6
this is father process i=8
this is father process i=10
process destroy
其中参数的使用
int temp1 = WIFEXITED(flag);
cout<<"WIFEXITED: 如果子进程正确结束返回一个非0值"<<temp1<<endl;
if(temp1 != 0)
{
cout<<"如果子进程正常结束,返回子进程退出码"<<WEXITSTATUS(flag)<<endl;
}
if(WIFSIGNALED(flag) != 0)
{ // 不为0,表示因为捕获信号而终止
cout<<"如果是因为捕获信号而终止的,返回相应的信号代码"<<WTERMSIG(flag)<<endl;
}
if(WIFSTOPPED(flag) != 0)
{
// 如果进程被暂停,返回一个非0值
cout<<"如果因为暂停,返回相应的信号代码"<<WSTOPSIG(flag)<<endl;
}
可以加长子进程的工作时间,利用正常结束进程或者是 kill -9 pid 杀死相应的子进程来查看状态
|