当前位置: 首页 > article >正文

Webserver(2.4)进程控制

目录

  • 进程退出
  • 孤儿进程
  • 僵尸进程
  • wait函数
  • waitpid函数

进程退出

exit 刷新IO缓冲区
_exit

孤儿进程

父进程运行结束,但子进程还在运行,这样的子进程称为孤儿进程。
每当出现一个孤儿进程的时候,内核就把孤儿进程的父进程设置为init,而init进程会循环地wait()它的已经退出的子进程。init进程会在孤儿进程结束后处理它的善后工作,因此孤儿进程并不会有什么危害

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

int main(){

    //创建子进程
    pid_t pid=fork();

    //判断,判断是父进程还是子进程
    if(pid>0){

        //如果大于0,返回的是创建的子进程的进程号,当前是父进程
        printf("i am parent process,pid :%d,ppid:%d\n",getpid(),getppid());
    }else if(pid==0){
        sleep(1);
        //当前是子进程
        printf("i am child process,pid:%d,ppid:%d\n",getpid(),getppid());
        
    }

    //for循环
    for(int i=0;i<3;i++){
        printf("i:%d,pid:%d\n",i,getpid());
    }


    return 0;
}

子进程的父进程的Id变成了1,孤儿进程的父进程会给进程号为1 的Init
在这里插入图片描述
那为什么又出现终端信息了呢?
因为父进程结束之后,切换到前台,然后子进程还有输出,继续输出出来,

僵尸进程

相对于无害的孤儿进程,僵尸进程比较麻烦和可怕
每个进程结束之后,都会释放自己地址空间中的用户区数据,内核区的PCB没有办法自己释放掉,需要父进程去释放。
进程终止时,父进程尚未回收,子进程残留资源(PCB)存放于内核中,变成僵尸进程
僵尸进程不能被kill -9杀死
这样就会导致一个问题,如果父进程不调用wait()或waitpid()的话,那么保留的那段信息就不会释放,但是系统所能使用的进程号是有限的,如果大量的产生僵尸进程,将因为没有可用的进程号而导致系统不能产生新的进程,此即为僵尸进程的危害,应当避免
因此父进程必须去释放子进程的资源。
僵尸进程是子进程都死了,父进程没有去回收资源

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

int main(){

    //创建子进程
    pid_t pid=fork();

    //判断,判断是父进程还是子进程
    if(pid>0){
        while(1){
            //如果大于0,返回的是创建的子进程的进程号,当前是父进程
            printf("i am parent process,pid :%d,ppid:%d\n",getpid(),getppid());
            sleep(1);
        }

        
    }else if(pid==0){

        //当前是子进程
        printf("i am child process,pid:%d,ppid:%d\n",getpid(),getppid());
        
    }

    //for循环
    for(int i=0;i<3;i++){
        printf("i:%d,pid:%d\n",i,getpid());
    }


    return 0;
}

在这里插入图片描述
Z+的状态就是僵尸进程,仍占据一个进程号,然而进程号是有限的
在这里插入图片描述
僵尸进程无法被kill -9 进程号杀死,因为他不是一个正常的进程
父进程用ctrl+c结束,杀死
在这里插入图片描述
而在正式的开发中,无法这样结束父进程,一般调用wait()和waitpid()函数来结束

wait函数

父进程通过wait得到它的退出状态同时彻底清除掉这个进程
等待子进程结束之后,回收它的资源

#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(){

    //有一个父进程,创建5个子进程(兄弟)
    pid_t pid;

    
    for(int i=0;i<5;i++){
        pid=fork();
        if(pid==0){
            break;
        }
    }
    if(pid>0){
        //父进程
        while(1){
            printf("parent,pid=%d\n",getpid());
            int st;
            int ret =wait(&st);
            

            if(ret==-1){
                break;
            }

            if(WIFEXITED(st)){
                //是不是正常退出
                printf("退出的状态码:%d\n",WEXITSTATUS(st));
            
            }
            if(WIFSIGNALED(st)){
                //是不是异常终止
                printf("被那个信号干掉了:%d\n",WTERMSIG(st));
            }
            printf("child die,pid=%d\n",ret);
            sleep(1);
        }
        
    }else if(pid==0){
        //子进程
        // while(1){
        printf("child,pid=%d\n",getpid());
        sleep(1);
        //}
        exit(0);
        
    }
    return 0;
}

在这里插入图片描述
目前有5个僵尸进程
wait函数就是会阻塞在那,如果有一个进程被回收了,会运行一次,然后继续运行。
在这里插入图片描述

waitpid函数

阻塞就是在等待某些条件触发之后再运行
使用了waitpid之后,即使子进程未执行完,父进程仍可以执行自己的业务逻辑,但是wait的话,父进程就会暂停等到子进程回收之后再继续运行一次。

#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(){

    //有一个父进程,创建5个子进程(兄弟)
    pid_t pid;

    
    for(int i=0;i<5;i++){
        pid=fork();
        if(pid==0){
            break;
        }
    }
    if(pid>0){
        //父进程
        while(1){
            printf("parent,pid=%d\n",getpid());
            sleep(1);
            int st;
            int ret =waitpid(-1,&st,WNOHANG);
            

            if(ret==-1){
                break;
            }

            if(ret==0){
                //说明还有子进程存在
                continue;
            }else if(ret>0){
                if(WIFEXITED(st)){
                //是不是正常退出
                printf("退出的状态码:%d\n",WEXITSTATUS(st));
            
            }
                if(WIFSIGNALED(st)){
                    //是不是异常终止
                    printf("被那个信号干掉了:%d\n",WTERMSIG(st));
                }
                printf("child die,pid=%d\n",ret);
                

            }
            

            
        }
        
    }else if(pid==0){
        //子进程
        while(1){
            printf("child,pid=%d\n",getpid());
            sleep(1);
        }
        exit(0);
        
    }
    return 0;
}


http://www.kler.cn/a/376455.html

相关文章:

  • 如何实现指针值的原子操作
  • Servlet 3.0 注解开发
  • RabbitMQ最全教程-Part1(基础使用)
  • 履带式排爆演习训练机器人技术详解
  • 老电脑不能装纯净版windows
  • 【网络】HTTP(超文本传输协议)详解
  • 2024 手机解压缩软件评测与推荐
  • 【ROS2】文档、教程、源码汇总
  • Android——横屏竖屏
  • 视频怎么进行格式转换?6款视频转换MP4格式的免费软件!
  • 【sqlmap使用手册-持续更新中】
  • 安装xtrabackup备份mysql
  • python项目实战 查询手机号码归属地源码
  • Node.js:Express 服务 路由
  • 工控一体机行业前景:智能化、自动化与高效能
  • 针对Hmaster启动后很快停止
  • 【大数据学习 | kafka】producer的参数与结构
  • NeurIPS - Ariel Data Challenge 2024
  • Maven讲解从基础到高级配置与实践
  • 恋爱脑学Rust之Box与RC的对比
  • ChatGPT新体验:AI搜索功能与订阅支付指南
  • layui 自定义验证单选框必填
  • CSS3新增边框属性(五)
  • Java基于微信小程序的私家车位共享系统(附源码,文档)
  • Vim的简单使用
  • 到底要不要用SAP Screen Personas