exec函式族,vfork,程序退出,銷燬程序(殭屍程序 孤兒程序)
阿新 • • 發佈:2018-12-22
參考文章
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
exec
https://blog.csdn.net/zjwson/article/details/53337212
exec
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); } }
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;
}