IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> linux中wait与waitpid -> 正文阅读

[系统运维]linux中wait与waitpid

进程

在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
杀死相应的子进程来查看状态

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-04-22 19:19:35  更:2022-04-22 19:20:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 20:48:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码