exec函数族,vfork,进程退出,销毁进程(僵尸进程 孤儿进程)

参考文章

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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值