进程、孤儿进程、僵尸进程、fork、wait简介

news2024/11/7 1:45:51

 进程相关概念

        程序和进程
程序:是指编译好的二进制文件,在磁盘上,占用磁盘空间, 是一个静态的概念.
进程:一个启动的程序, 进程占用的是系统资源,如:物理内存,CPU,终端等,是一个动态的概念

进程状态

        进程基本的状态有5种。分别为初始态,就绪态,运行态,挂起态与终止态。其中初始态为进程准备阶段。

PCB:进程控制块

        进程控制块(Process Control Block,PCB)是操作系统中用于管理和控制进程的重要数据结构。每当操作系统创建一个新进程时,它会为该进程分配一个 PCB,其中包含了与该进程相关的所有信息。Linux内核的进程控制块是task_struct结构体。
       
        vim /usr/src/linux-headers-6.8.0-45/include/linux/sched.h  #6.8.0-45linux版本替换成自己的电脑上的版本   进入这个文件可以查看task_struct结构体的定义。

        task_struct结构体内部成员有很多,我们重点掌握以下部分即可:
进程id。系统中每个进程有唯一的id,在C语言中用pid_t类型表示,其实就是一个非负整数。
进程的状态,有就绪、运行、挂起、停止等状态。
描述虚拟地址空间的信息。
进程切换时需要保存和恢复的一些CPU寄存器。
文件描述符表,包含很多指向file结构体的指针。
用户id和组id。
进程可以使用的资源上限(Resource Limit):使用ulimit -a 命令可以查看

并行和并发

        并发,在一个时间段内, 是在同一个cpu上, 同时运行多个程序。
        如:若将CPU的1S的时间分成100个时间片,每个进程执行完一个时间片必须无条件让出CPU的使用权,这样1S中就可以执行100个进程。高并发可以简单理解为是在有限时间内,系统能够处理尽可能多的进程或请求。
        并行指两个或两个以上的程序在同一时刻发生(需要有多颗cpu,现在我们电脑的cpu都是多核)。就是说,有多个cpu上同时运行着不同程序。

孤儿进程

        孤儿进程的概念:若子进程的父进程已经终止,而子进程还在运行,这个进程就成了孤儿进程。
        为了保证每个进程都有一个父进程,孤儿进程会被init进程(
进程标识符(PID)为1)领养,init进程成为了孤儿进程的养父进程,当孤儿进程退出之后,由init进程完成对孤儿进程的回收。

僵尸进程

        僵尸进程的概念:若子进程终止,父进程还在运行, 但是父进程没有调用wait或waitpid函数完成对子进程的回收,则该子进程就成了僵尸进程。
        
如何解决僵尸进程?
        由于僵尸进程是一个已经终止的进程,所以不能使用kill命令将其杀死

        通过kill其父进程的方法可以消除僵尸进程。

终止掉其父进程后,这个僵尸进程会被init进程领养,由init进程完成对僵尸进程的回收。

fork函数

        函数作用:创建子进程
原型: pid_t fork(void);
使用时需要包含头文件:#include <unistd.h>
函数参数:无
返回值:调用成功:父进程返回子进程的PID,是一个大于0的数;
              子进程返回0。
注意:不是fork函数在一个进程中返回两个值,而是在父子进程各自返回一个值。
fork函数原理图:(PCB在上边有介绍)

子进程创建成功后,代码的执行位置?
        
进程会从 fork() 调用后的下一行代码开始继续执行。这意味着,在 fork() 后面有条件判断或逻辑分支,可以通过检查 fork() 的返回值来确定当前是在父进程还是在子进程中。
如何区分父子进程?
        
通过fork函数的返回值
父子进程的执行顺序?
        
不一定,哪个进程先抢到CPU,哪个进程就先执行。
fork函数代码简单实例:调用fork函数创建子进程,分别打印出子进程pid和父进程pid等。代码里用到了getpid和getppid函数,比较简单,这里不在介绍。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>

int main(void)
{
	printf("before fork,pid[%d]\n",getpid());
	pid_t pid = fork();
	printf("test\n");
	if(pid<0)
	{
		perror("fork error");
		return -1;
	}
	else if(pid>0)
	{
		printf("father:[%d],pid =[%d],fpid=[%d]\n",pid,getpid(),getppid());
	}
	else if(pid==0)
	{	
		printf("child:pid =[%d],fpid=[%d]\n",getpid(),getppid());
	}
	printf("after fork,pid:[%d]\n",getpid());

	return 0;

}

运行结果如下:

其次,父子进程对某个变量进行修改时需要注意,父进程若修改某个变量的值,子进程中这个变量的值不会改变,试想,如果子进程中某个变量的值能跟随父进程中对应变量的值进行变化,就相当于进行了父子间进程通信!显然,在这份代码中并没有做到。
 

//fork函数测试
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

#include <sys/wait.h>

int test = 6;

int main()
{
	//创建子进程
	pid_t pid = fork();
	if(pid<0) //fork失败的情况
	{
		perror("fork error");
		return -1;
	}
	else if(pid>0)//父进程
	{
		printf("parent: [%d], pid=[%d], fpid=[%d]\n", pid, getpid(),getppid());
		test += 2;
		printf("parent:[%p]\n", &test);
		printf("parent: test==[%d]\n",test);
        //wait(NULL);
	}
	else if(pid==0) //子进程
	{
		sleep(2); //为了避免父进程还没有执行, 子进程已经结束了
		printf("[%p]\n", &test);
		printf("child: pid==[%d], fpid==[%d]\n", getpid(), getppid());
		printf("child: test==[%d]\n", test);
	}
	
	return 0;
}

执行结果:这里父进程结束后,子进程的fpid是1(init进程的pid为1),这个进程(就是孤儿进程最上边有解释)会被init进程领养,由init进程完成对孤儿进程的回收。但是执行完并没有自动退出终端,如果想让其自动退出终端,把上述代码的wait注释去掉。

wait函数

        pid_t wait(int *_Nullable wstatus);
函数作用:阻塞并等待子进程退出、回收子进程残留资源、获取子进程结束状态(退出原因)。

返回值:
        成功:清理掉的子进程ID;
        失败:-1 (没有子进程
);

wstatus参数:子进程的退出状态 --
传出参数

  • WIFEXITED(wstatus):为非0        → 进程正常结束
  • WEXITSTATUS(wstatus):获取进程退出状态
  • WIFSIGNALED(wstatus):为非0 → 进程异常终止
  • WTERMSIG(status):取得进程终止的信号编号。
    wait函数实例:实现父进程调用wait函数完成对子进程的回收
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <sys/wait.h>
    
    int main()
    {
    	//创建子进程
    	pid_t pid = fork();
    	if(pid<0) //fork失败的情况
    	{
    		perror("fork error");
    		return -1;
    	}
    	else if(pid>0)//父进程
    	{
    		printf("father: [%d], pid==[%d], fpid==[%d]\n", pid, getpid(),getppid());
    		int wstatus;
    		pid_t wpid = wait(&wstatus);
    		printf("wpid==[%d]\n", wpid);
    		if(WIFEXITED(wstatus)) //正常退出
    		{
    			printf("child normal exit, wstatus==[%d]\n", WEXITSTATUS(wstatus));
    		}
    		else if(WIFSIGNALED(wstatus)) //被信号杀死
    		{
    			printf("child killed by signal, signo==[%d]\n", WTERMSIG(wstatus));
    		}
    		
    	}
    	else if(pid==0) //子进程
    	{
    		
    		printf("child: pid==[%d], fpid==[%d]\n", getpid(), getppid());
    		sleep(10);
    		return 9;
    	}
    
    	return 0;
    }
    

    结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2229035.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

已解决:VS2022一直显示编译中但无法运行的情况

本问题已得到解决&#xff0c;请看以下小结&#xff1a; 关于《VS2022一直显示编译中但无法运行的情况》的解决方案 记录备注报错时间2024年报错版本VS2022报错复现突然VS2022不能启动&#xff0c;一直显示编译中&#xff0c;取消重试无效&#xff0c;重新生成解决方案无效报错…

12. MapReduce全局计数器

一. 计数器概述 在执行MapReduce程序时&#xff0c;控制台的输出中一般会包含如下内容。 这些输出就是MapReduce的全局计数器的输出信息。计数器是用来记录job的执行进度和状态的&#xff0c;它的作用可以理解为日志&#xff0c;方便用户了解任务的执行状况&#xff0c;辅助…

Springboot集成阿里云通义千问(灵积模型)

我这里集成后&#xff0c;做成了一个工具jar包&#xff0c;如果有不同方式的&#xff0c;欢迎大家讨论&#xff0c;共同进步。 集成限制&#xff1a; 1、灵积模型有QPM(QPS)限制&#xff0c;每个模型不一样&#xff0c;需要根据每个模型适配 集成开发思路&#xff1a; 因有…

今年双11,拼多多吹“新”风

文 | 螳螂观察 作者 | 陈小江 这届双11真变了。 以前提到双11&#xff0c;不管平台、商家全都盯着价格。但今年不一样。这届双11给出了新解法——平台不再把“我的价格比你低”挂在嘴边&#xff0c;转而更关心消费者体验和为商家减负。 双11这艘大船&#xff0c;在航行到第…

005 IP地址的分类

拓扑结构如下 两台主机处于同一个网关下&#xff0c;通过ping命令检测&#xff0c;可以连通 &nbps; 拓扑结构如下 使用ping 检查两台电脑是否相通, 因为网络号不一样&#xff0c;表示两台电脑不在同一个网络&#xff0c;因此无法连通 拓扑结构如下 不在同一网络的PC要相…

记本地第一次运行seatunnel示例项目

前置 静态源码编译通过&#xff1a;https://blog.csdn.net/u011924665/article/details/143372464 参考 seatunnel官方的开发环境搭建文档&#xff1a;https://seatunnel.incubator.apache.org/zh-CN/docs/2.3.5/contribution/setup 安装scala 下载scala 去官网下载&…

《暗河传》 顺利杀青,苏棋演绎“千面鬼”慕婴引期待

近日&#xff0c;由龚俊、彭小苒、常华森、杨雨潼等一众优秀演员出演的古装武侠剧《暗河传》顺利杀青&#xff0c;00后小花苏棋饰演的“千面鬼”慕婴一角也收获了许多关注的目光。 《暗河传》凭借其精彩的剧情和庞大的粉丝基础&#xff0c;自开拍起便备受关注。在剧中&#xff…

推荐一个没有广告,可以白嫖的产品宣传册转换翻页电子书的网站

​随着数字化时代的到来&#xff0c;传统的纸质宣传册逐渐被电子书所取代。为了满足企业和个人对高效、便捷的电子宣传册制作需求&#xff0c;许多在线平台应运而生。今天&#xff0c;就让我为您推荐一个无需广告干扰、完全免费使用的在线宣传册转换翻页电子书网站——【FLBOOK…

QT 从ttf文件中读取图标

最近在做项目时&#xff0c;遇到需要显示一些特殊字符的需求&#xff0c;这些特殊字符无法从键盘敲出来&#xff0c;于是乎&#xff0c;发现可以从字体库文件ttf中读取显示。 参考博客&#xff1a;QT 图标字体类IconHelper封装支持Font Awesome 5-CSDN博客 该博客封装的很不错…

[Linux关键词]unmask,mv,dev/pts,stdin stdout stderr,echo

希望你开心&#xff0c;希望你健康&#xff0c;希望你幸福&#xff0c;希望你点赞&#xff01; 最后的最后&#xff0c;关注喵&#xff0c;关注喵&#xff0c;关注喵&#xff0c;大大会看到更多有趣的博客哦&#xff01;&#xff01;&#xff01; 喵喵喵&#xff0c;你对我真的…

人工智能与伦理:我们应该如何平衡科技与人性?

内容概要 在这个瞬息万变的时代&#xff0c;人工智能的迅猛发展让我们面对前所未有的伦理困境。科技进步带来了便利&#xff0c;但同时也亟需我们反思如何对待人性。尤其是在实现算法透明性时&#xff0c;我们要确保每一个决策背后都能被理解与追溯&#xff0c;这不仅是对技术…

聚水潭数据集成到MySQL的技术实操与解决方案

聚水潭数据集成到MySQL的技术案例分享 在现代企业的数据管理过程中&#xff0c;如何高效、可靠地实现不同系统之间的数据对接是一个关键问题。本案例将聚焦于“聚水谭-仓库查询单-->BI邦盈-仓库表”的数据集成方案&#xff0c;详细探讨如何通过轻易云数据集成平台&#xff…

Mybatis-03.入门-配置SQL提示

一.配置SQL提示 目前的Springboot框架在mybatis程序中编写sql语句并没有给到任何的提示信息&#xff0c;这对于开发者而言是很不友好的。因此我们需要配置SQL提示。 配置SQL提示 这样再去写SQL语句就会有提示了。 但是会发现指定表名时并没有给出提示。这是因为&#xff1a…

计算机视觉中的点算子:从零开始构建

Hey小伙伴们&#xff01;今天我们要聊的是一个非常基础但极其重要的计算机视觉技术——点算子&#xff08;Point Operators&#xff09;。点算子主要用于对图像的每个像素进行独立的处理&#xff0c;比如亮度调整、对比度增强、灰度化等。通过这些简单的操作&#xff0c;我们可…

计算机网络:网络层 —— IPv4 协议的表示方法及其编址方法

文章目录 IPv4IPv4的表示方法IPv4的编址方法分类编址A类地址B类地址C类地址可指派的地址数量一般不使用的特殊IPv4地址 划分子网编址子网掩码默认子网掩码 无分类编址方法地址掩码斜线记法无分类域间路由选择 CIDR IPv4 IPv4&#xff08;Internet Protocol version 4&#xff…

excel自定义导出实现(使用反射)

前言 项目中接到需求&#xff0c;需要对导出的字段进行自定义导出 &#xff0c;用户可在前端选择自定义导出的字段&#xff08;如图&#xff09;&#xff0c;实现过程做以下记录&#xff0c;仅供参考&#xff1b; 思路 跟前端约定好所有要导出的字段名称(headName)跟对应的…

练习LabVIEW第十七题

学习目标&#xff1a; 刚学了LabVIEW&#xff0c;在网上找了些题&#xff0c;练习一下LabVIEW&#xff0c;有不对不好不足的地方欢迎指正&#xff01; 第十七题&#xff1a; 编写一个程序,用labview的信号生成函数产生一个三角波并显示在chart上,在编写例外一个程序读出数据…

【论文阅读】PGAN

1. WHY 问题 图像超分辨率一直是一个热门研究课题&#xff0c;具有重要的应用价值。基于生成对抗网络GAN的单幅图像超分辨率方法显示重建图像与人类视觉特征更一致。因此&#xff0c;基于 GAN 的网络优化已成为图像超分辨率的主流。然而&#xff0c;一些最新研究表明&#xf…

江协科技STM32学习- P28 USART串口数据包

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​…

C# Retry库

比如网络访问或硬件参数设置需要重试&#xff0c;可引用gunet上的Polly库。 同步方式&#xff08;每次重试有不同的时间间隔&#xff09; var polly Policy.Handle<Exception>().WaitAndRetry(new[] { new TimeSpan(0, 0, 1), new TimeSpan(0, 0, 2), new TimeSpan(0, …