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

「Linux」进程等待与替换

在这里插入图片描述

💻文章目录

  • 📄前言
  • 进程等待
    • 进程等待的概念
    • 进程等待的方法
  • 进程替换
    • 进程替换的概念
    • 替换方式
  • 📓总结


📄前言

在如今的时代,多进程编程已经变成了必不可少的一部分,而进程等待、进程替换这两个概念都是作为多进程编程所必不可少的知识,为了掌握多进程编程,今天就从进程等待与替换开始吧。

进程等待

进程等待的概念

我们知道linux中进程拥有多种状态,例如僵尸状态、阻塞状态、运行状态等,而其中僵尸状态就是因为父进程没有接受到子进程的退出码而导致的状态,僵尸状态意味着系统无法对进程pcb的资源进行回收,过多的僵尸程序将导致系统内存泄漏、反应卡顿,严重时甚至会让系统挂死。所以,一个正常的多进程程序,父进程必须要接收完所有子进程的退出码,而这个接收的过程就是进程等待 <T_T。

进程等待的方法

进程等待的方式分为两种:

  • 阻塞等待:如同字面的意思,在等待子进程退出码的时候停止(阻塞)父进程的运行。
  • 非阻塞等待:在子进程运行的同时,父进程也运行代码,但是得不时对子进程的退出情况进行检查。

在C语言中,等待进程的函数为 waitwaitpid,它们的差别在与参数的不同。

#include<sys/types.h>
#include<sys/wait.h>

pid_t wait(int*status);
/*
返回值:
 成功返回被等待进程 pid,失败返回-1。
参数:
 输出型参数,获取子进程退出状态,不关心则可以设置成为NULL
*/

pid_ t waitpid(pid_t pid, int *status, int options);
/*
返回值:
	正常返回时返回子进程的pid,如果调用失败返回-1;
	注意:如果options设置成了非阻塞等待,子进程没有退出时返回0;
参数:
	pid:
 		Pid=-1,等待任一个子进程。与wait等效;
	 	Pid>0.等待其进程ID与pid相等的子进程;
 
 	status:
 		WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出);
 		WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码);
 
 	options:
 		WNOHANG: 若pid指定的子进程没有结束,程序返回0,父进程继续执行代码,在一段时间再次调用确定子进程退出;
*/
  • 阻塞等待
    阻塞等待意味着父进程在等待期间是什么都不做的,所以期间只有子进程在运行。
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main()
{
	pid_t id = fork();		//在linux系统中使用fork来生成子进程
	if(id < 0)
        _exit(1);	//子进程生成异常
	
	if(id == 0) //分流
	{	//子进程
        printf("child is run, pid is:%d\n",getpid());
        sleep(3);
        exit(0);
	}
	else
	{	//父进程
        int status = 0;
        pid_t ret = waitpid(-1, &status, 0);  //阻塞等待
        if(WIFEXITED(status) && ret == id)
            printf("wait child 5s success, child return code is :%d.\n",WEXITSTATUS(status));
        else  
        {
            printf("wait child failed, return.\n");
            return 1;
        }
    }
	return 0;
}

在这里插入图片描述

  • 非阻塞等待
    非阻塞等待只需把 waitpid 最后的参数改为WNOHANG即可
int main()
{
	pid_t id = fork();		//在linux系统中使用fork来生成子进程
	if(id < 0)
        _exit(1);	//子进程生成异常
	
	if(id == 0) //分流
	{	//子进程
        printf("child is run, pid is:%d\n",getpid());
        sleep(3);
        exit(0);
	}
	else
	{	//父进程
        int status = 0;
        pid_t ret;
        do 
        {
            ret = waitpid(-1, &status, WNOHANG);  //非阻塞等待
            if (ret == 0)
            {
                printf("child is running\n");
            }
            sleep(1);
        }while (ret == 0);

        if(WIFEXITED(status) && ret == id)
            printf("wait child 5s success, child return code is :%d.\n",WEXITSTATUS(status));
        else  
        {
            printf("wait child failed, return.\n");
            return 1;
        }
    }
	return 0;
}

在这里插入图片描述

进程替换

进程替换的概念

进程替代是指程序在运行期间执行另一个程序,但这个替换是把整个程序从头到尾都换成了新的程序(pcb还是同样的,所以进程id不变),即使替换的程序结束完毕,也不会回到原有的代码继续执行,所以一般都是由子进程来进行进程替换。

在这里插入图片描述

替换方式

C语言的进程替换函数

/*函数如果执行成功将会替换成新的程序,如果执行失败则返回-1*/
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ...,char *const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);

虽然函数很多,但其实它们都有着一套很好记得命名规范:

  • l (list):指使用列表参数,即可变参数列表(arg…)
  • v(vector):指使用使用数组来传递参数
  • p(path):指自动搜寻环境变量
  • e(env):指自己维护环境变量

在这里插入图片描述

替换实例

int main()
{
		pid_t id = fork();		
    if(id == 0)
    {	//子进程
        execlp("exa", "exa", "--icons", NULL);		//p代表自动搜索环境变量,无需使用绝对路径
        printf("child is exit\n");	//如果execlp执行成功不会打印
        exit(1);
    }
    else 
    {	//父进程
        printf("i'am father, pid:%d\n", getpid());
    }
	return 0;
}

在这里插入图片描述

📓总结

📜博客主页:主页
📫我的专栏:C++
📱我的github:github


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

相关文章:

  • 前端请求后端php接口跨域 cors问题
  • Django基础用法+Demo演示
  • 【嵌入式开发】单片机CAN配置详解
  • AWS认证SAA-C0303每日一题
  • 【QT】QSS
  • ❤React-React 组件通讯
  • Linux 上的容器技术
  • Linux服务器初次使用需要的环境配置
  • LASSO vs GridSearchCV
  • 12.03 二叉树简单题2
  • LeetCode刷题---路径问题
  • Hdoop学习笔记(HDP)-Part.08 部署Ambari集群
  • 如何获取唐诗三百首中的名句列表接口
  • 面试篇算法:(一:排序算法)
  • bean依赖属性配置
  • 常见的攻击防护
  • 正是阶段高等数学复习--函数极限的计算
  • Javaweb之Vue组件库Element案例异步数据加载的详细解析
  • HelpLook可以作为wordpress的替代品,帮助企业快速搭建博客
  • pikachu靶场:php反序列化漏洞
  • Mac下更新python
  • 后端Long型数据传到前端js后精度丢失的问题
  • 02.PostgreSQL 查询处理期间发生了什么?
  • 单片机学习11——矩阵键盘
  • 【无标题】我们只能用成功来摧毁我们,原来的自己只会破败自己的事情。
  • redis实现消息延迟队列