参考文章
waitpid和wait
https://www.cnblogs.com/LUO77/p/5804436.html
https://www.cnblogs.com/13224ACMer/p/6390702.html
https://blog.csdn.net/zhangxiao93/article/details/72859312
vfork和fork
https://blog.csdn.net/ValDC_Morning/article/details/77414826
https://www.cnblogs.com/lovemdx/p/3308057.html
exec
https://blog.csdn.net/zjwson/article/details/53337212
exec
void PID::fun1()
{
/*
exec函数族
在fork后的子进程中使用exec函数族,可以装入和运行其它程序(子进程替换原有进程,和父进程做不同的事)。
如果不调用exit就使用 父进程改变数据,会造成死锁
*/
cout<<"exec"<<endl;
char *arg[]={"ls","-al",NULL};
pid_t pid=fork();
if(pid==0)// 子进程
{
cout<<" 子进程中:"<<endl;
execv("/bin/ls", arg);
exit(0);
}
else if(pid>0)//父进程
{
cout<<" 父进程中:execl没有执行"<<endl;
execl("/bin/date", "/bin/date");
exit(1);
}
else
{
perror("创建进程失败\n");
exit(2);
}
}

vfork
void PID::fun2()
{
/*
vfork()函数用来创建一个新进程,而这个新进程的目的是exec一个新程序。
vfork创建的子进程与父进程共享地址空间,即子进程完全运行在父进程的地址空间上,子进程对虚拟地址空间的修改同样为父进程所见.
vfork保证子进程先运行,它调用exec或exit后父进程才能调度运行,fork的父子进程运行顺序不定,取决于内核的调度算法。
*/
cout<<"vfork()"<<endl;
int temp=0;
cout<<"vfork创建进程前 temp:"<<temp<<endl;
pid_t pid;
pid=vfork();
if(pid==0)
{
temp++;
cout<<"子";
}
else if(pid>0)
{
cout<<"父";
}
cout<<"进程,进程标示符:"<<getpid()<<" temp:"<<temp<<endl;
exit(0);
}

exit
void PID::fun3()
{
/*
exit 和 _exit 区别
*/
cout<<"exit pid"<<endl;
pid_t pid;
pid=fork();
if(pid==0)
{
cout<<"子进程"<<endl;
cout<<"子:缓冲区数据还在";
exit(0);
}
else if(pid>0)
{
cout<<"父进程"<<endl;
cout<<"父:缓冲区数据还在";
_exit(0);
}
}

void PID::fun4()
{
/*
僵尸进程:子进程终止了,但是父进程没有回收子进程的资源PCB。使其成为僵尸进程
孤儿进程:父进程先与子进程结束了,使得子进程失去了父进程,这个时候子进程会被1号进程init进程领养,成为孤儿进程
1) wait()函数用于使父进程(也就是调用wait()的进程)阻塞,直到一个子进程结束或者该进程接收到了一个指定的信号为止。如果该父进程没有子进程或者它的子进程已经结束,则wait()函数就会立即返回。
2) waitpid()的作用和wait()一样,但它并不一定要等待第一个终止的子进程(它可以指定需要等待终止的子进程),它还有若干选项,如可提供一个非阻塞版本的 wait()功能,也能支持作业控制。实际上,wait()函数只是 waitpid()函数的一个特例,在Linux 内部实现 wait()函数时直接调用的就是waitpid()函数。
*/
cout<<"wait &&waitpid"<<endl;
pid_t pid;
pid=fork();
if(pid<0)
{
perror("fork error\n");
exit(1);
}
else if(pid==0)
{
cout<<"child pid:"<<getpid()<<endl<<"child's dad:"<<getppid()<<endl;
//sleep(3);
//exit(0);
}
else
{
pid_t pid2;
//pid2=wait(NULL);//阻塞父进程 成功返回子进程pid
pid2=waitpid(pid,NULL,0);
cout<<"dad pid:"<<getpid()<<endl;
cout<<"wait pid:"<<pid2<<endl;//返回 -1 估计是mac自己把子进程解决掉了
}
exit(0);
}
void PID::fun4_2()//waitpid和wait类似 多了一个指定等待的进程 最后参数是阻塞方式
{
cout<<"wait &&waitpid"<<endl;
pid_t pid;
pid = fork();
if (pid < 0)
{
perror("fork failed");
exit(1);
}
if (pid == 0)
{//in child
int i;
for (i = 3; i > 0; i--) {
printf("This is the child %d\n",getpid());
sleep(1);
}
exit(3);//返回3,运行时可以看到
//子进程睡眠3秒之后就退出了
}
else
{//in parent
int stat_val;
waitpid(pid, &stat_val, 0);//以阻塞方式等待回收子进程,第三个参数0,表示阻塞方式
if (WIFEXITED(stat_val))//正常退出
printf("Child exited with code %d\n", WEXITSTATUS(stat_val));
else if (WIFSIGNALED(stat_val))//查看被什么信号关闭
printf("Child terminated abnormally, signal %d\n", WTERMSIG(stat_val));
}
};
全部程序
类的声明
//
// PID.hpp
// pid_charpter_7
//
// Created by 蓝猫 on 2018/11/3.
// Copyright 2018年 蓝猫. All rights reserved.
//
#ifndef PID_hpp
#define PID_hpp
#include <stdio.h>
namespace SYA
{
class PID
{
public:
void fun1();//exec函数族
void fun2();// vfork()
void fun3();//exit 和 _exit
void fun4();// 销毁进程
void fun4_2();
};
};
#endif /* PID_hpp */
类的实现
//
// PID.cpp
// pid_charpter_7
//
// Created by 蓝猫 on 2018/11/3.
// Copyright 2018年 蓝猫. All rights reserved.
//
#include "PID.hpp"
#include <sys/types.h>
#include <unistd.h>
#include <iostream>
using std::cout;
using std::endl;
using namespace SYA;
void PID::fun1()
{
/*
exec函数族
在fork后的子进程中使用exec函数族,可以装入和运行其它程序(子进程替换原有进程,和父进程做不同的事)。
*/
cout<<"exec"<<endl;
char *arg[]={"ls","-al",NULL};
pid_t pid=fork();
if(pid==0)// 子进程
{
cout<<" 子进程中:"<<endl;
execv("/bin/ls", arg);
exit(0);
}
else if(pid>0)//父进程
{
cout<<" 父进程中:execl没有执行"<<endl;
execl("/bin/date", "/bin/date");
exit(1);
}
else
{
perror("创建进程失败\n");
exit(2);
}
}
void PID::fun2()
{
/*
vfork()函数用来创建一个新进程,而这个新进程的目的是exec一个新程序。
vfork创建的子进程与父进程共享地址空间,即子进程完全运行在父进程的地址空间上,子进程对虚拟地址空间的修改同样为父进程所见.
vfork保证子进程先运行,它调用exec或exit后父进程才能调度运行,fork的父子进程运行顺序不定,取决于内核的调度算法。
*/
cout<<"vfork()"<<endl;
int temp=0;
cout<<"vfork创建进程前 temp:"<<temp<<endl;
pid_t pid;
pid=vfork();
if(pid==0)
{
temp++;
cout<<"子";
}
else if(pid>0)
{
cout<<"父";
}
cout<<"进程,进程标示符:"<<getpid()<<" temp:"<<temp<<endl;
exit(0);
}
void PID::fun3()
{
/*
exit 和 _exit 区别
*/
cout<<"exit pid"<<endl;
pid_t pid;
pid=fork();
if(pid==0)
{
cout<<"子进程"<<endl;
cout<<"子:缓冲区数据还在";
exit(0);
}
else if(pid>0)
{
cout<<"父进程"<<endl;
cout<<"父:缓冲区数据还在";
_exit(0);
}
}
void PID::fun4()
{
/*
僵尸进程:子进程终止了,但是父进程没有回收子进程的资源PCB。使其成为僵尸进程
孤儿进程:父进程先与子进程结束了,使得子进程失去了父进程,这个时候子进程会被1号进程init进程领养,成为孤儿进程
1) wait()函数用于使父进程(也就是调用wait()的进程)阻塞,直到一个子进程结束或者该进程接收到了一个指定的信号为止。如果该父进程没有子进程或者它的子进程已经结束,则wait()函数就会立即返回。
2) waitpid()的作用和wait()一样,但它并不一定要等待第一个终止的子进程(它可以指定需要等待终止的子进程),它还有若干选项,如可提供一个非阻塞版本的 wait()功能,也能支持作业控制。实际上,wait()函数只是 waitpid()函数的一个特例,在Linux 内部实现 wait()函数时直接调用的就是waitpid()函数。
*/
cout<<"wait &&waitpid"<<endl;
pid_t pid;
pid=fork();
if(pid<0)
{
perror("fork error\n");
exit(1);
}
else if(pid==0)
{
cout<<"child pid:"<<getpid()<<endl<<"child's dad:"<<getppid()<<endl;
//sleep(3);
//exit(0);
}
else
{
pid_t pid2;
//pid2=wait(NULL);//阻塞父进程 成功返回子进程pid
pid2=waitpid(pid,NULL,0);
cout<<"dad pid:"<<getpid()<<endl;
cout<<"wait pid:"<<pid2<<endl;//返回 -1 估计是mac自己把子进程解决掉了
}
exit(0);
}
void PID::fun4_2()//waitpid和wait类似 多了一个指定等待的进程 最后参数是阻塞方式
{
cout<<"wait &&waitpid"<<endl;
pid_t pid;
pid = fork();
if (pid < 0)
{
perror("fork failed");
exit(1);
}
if (pid == 0)
{//in child
int i;
for (i = 3; i > 0; i--) {
printf("This is the child %d\n",getpid());
sleep(1);
}
exit(3);//返回3,运行时可以看到
//子进程睡眠3秒之后就退出了
}
else
{//in parent
int stat_val;
waitpid(pid, &stat_val, 0);//以阻塞方式等待回收子进程,第三个参数0,表示阻塞方式
if (WIFEXITED(stat_val))//正常退出
printf("Child exited with code %d\n", WEXITSTATUS(stat_val));
else if (WIFSIGNALED(stat_val))//查看被什么信号关闭
printf("Child terminated abnormally, signal %d\n", WTERMSIG(stat_val));
}
};
main
//
// main.cpp
// pid_charpter_7
//
// Created by 蓝猫 on 2018/11/2.
// Copyright 2018年 蓝猫. All rights reserved.
//
#include <iostream>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <memory>
#include "PID.hpp"
using namespace std;
using SYA::PID;
int main(int argc, const char * argv[])
{
shared_ptr<SYA::PID> obj=make_shared<SYA::PID>();
//PID *obj;
//obj->fun1();
//obj->fun2();
//obj->fun3();
//obj->fun4();
obj->fun4_2();
return 0;
}
|