【Linux基础(二)】进程管理

学习分享

  • 1、程序和进程
    • 1.1、程序
    • 1.2、进程和进程ID
  • 2、Linux下的进程结构
  • 3、init进程
  • 4、获取进程标识
  • 5、fork系统调用
    • 5.1、fork函数实例分析
  • 6、进程的特性
  • 7、在Linux下进程指令
    • 7.1、终止进程指令
    • 7.2、查看进程指令:
    • 7.3、以树状图列出进程
  • 8、多进程运行异常情况
    • 8.1、孤儿进程
    • 8.2、僵尸进程
    • 8.3、解决方案
      • 8.3.1、wait和waitpid函数
        • 8.3.1.1、wait函数
        • 8.3.1.2、waitpdi函数
        • 8.3.1.3、wait和waitpid的区别
      • 8.3.2、wait函数解决孤儿进程
      • 8.3.3、wait函数解决僵尸进程
    • 8.4、进程退出码传递示例
  • 9、子进程结束的方式

1、程序和进程

1.1、程序

程序(program)是存放在磁盘文件中的可执行文件。

1.2、进程和进程ID

程序的执行实例被称为进程(process)。本书的每一页几乎都会使用这一术语。内核观点:分配系统资源(CPU,内存)的实体。

每个linux进程都一定有一个唯一的数字标识符,称为进程PID(process ID)。进程ID总是一非负整数。

使用指令:ps ajx

在这里插入图片描述

2、Linux下的进程结构

在这里插入图片描述

操作系统将.exe文件从磁盘搬到内存后被CPU处理,os内可能存在多个进程,此时操作系统就要管理好这些进程。操作系统将可执行程序的各种数据提取出来,在创建一个结构体把数据存进去,由于同时会存在多个进程,所以操作系统使用链表或其他数据结构将它们链接在一起。

PCB(进程控制块)是这个结构体的总称,在Linux系统下,PCB具体叫做:struct task_struct‘

3、init进程

进程ID为1通常是init进程,在自举过程结束时由内核调用。
init进程绝不会终止。
它是一个普通的用户进程(与交换进程不同,它不是内核中的系统进程),但是它以超级用户特权运行。

4、获取进程标识

在这里插入图片描述

#include <iostream>
#include <sys/types.h>
#include <unistd.h>
using namespace std;

int main()
{
	pid_t pid =getpid();
	
	while(1)
	{
		cout<<"pid = "<<pid<<endl;
		sleep(1);
	}
	return 0;
]

5、fork系统调用

在这里插入图片描述
在这里插入图片描述

由fork创建的新进程被称为子进程( child process)。
该函数被调用一次,但返回两次。两次返回的区别是子进程的返回值是0,而父进程的返回值则是子进程的进程ID。
一般来说,在f o r k之后是父进程先执行还是子进程先执行是不确定的。这取决于内核所使用的调度算法。

在这里插入图片描述

#include <iostream>
#include <sys/types.h>
#include <unistd.h>
using namespace std;

int main()
{
	pid_t pid;
	int number =0 ;
	cout <<"main 函数主进程 pid = "<<getpid()<<endl;
	//创建新的子进程
	pid =fork();
	if(pid ==0)
	{
		while(1)
		{
			cout<<"pid = "<<pid<<"自己 getpid ="<<getpid()<<"父进程为:"<<getppid()<<end;
			number++;
			cout<<"number"<<number<<endl;
			sleep(1);
		}
	}
	else if(pid > 0)
	{
		while(1)
		{
			cout<<"pid = "<<pid<<"getpid ="<<getpid()<<end;
			numbe++;
			cout<<"number"<<number<<endl;
			sleep(1);
		}
	}
	return 0;
]

5.1、fork函数实例分析

#include <iostream>
#include <sys/types.h>
#include <unistd.h>
using namespace std;

int main()
{
	pid_t pid;
	forint i =0;i<2;i++{
		pid =fork();
		cout<<"pid = "<<pid <<"当前进程 ID = "<<getpid()<<endl;
	}
	return 0;
]

在这里插入图片描述

6、进程的特性

1、操作系统分配资源的基本单位
2、一个操作系统下的多个进程是同时运行
3、多个进程的运行,是随机的,代码无法决定进程执行顺序,只能做到进程创建、结束
4、多个进程之间不会相互影响,它们各自有属于自己的PCB(代码段、数据段、堆栈段)
5、多个进程之间不能共享数据(IPC技术才能解决数据互通、共享)

7、在Linux下进程指令

7.1、终止进程指令

在我们的程序运行时,可以在运行的地方按CTRL+C来结束进程,但是还有一种方法可以结束进程:

使用指令:kill -9 要杀掉的进程ID

(注:这里的-9是信号参数,直接使用即可)

7.2、查看进程指令:

ps -aux

7.3、以树状图列出进程

pstree

8、多进程运行异常情况

8.1、孤儿进程

父进程比子进程先结束,这个子进程称为孤儿进程。
孤儿进程的父进程统一转变为1号进程,这个1号进程实际上就是操作系统本身!


#include <iostream>
#include <sys/types.h>
#include <unistd.h>
using namespace std;

int main()
{
	pid_t pid;
	cout <<"main 函数主进程 pid = "<<getpid()<<endl;
	//创建新的子进程
	pid =fork();
	if(pid ==0)
	{
		for(int i=0;i<30;i++)
		{
			cout<<"自己 getpid ="<<getpid()<<" i= "<<i<<end;
			sleep(1);
		}
	}
	else if(pid > 0)
	{
		for(int i=0;i<15;i++)
		{
			cout<<"父进程 getpid ="<<getpid()<<"i = "<<i<<end;
			sleep(1);
		}
	}
	return 0;
]

8.2、僵尸进程

子进程比父进程先结束,子进程逻辑走完,但是占用资源(资源还没有释放)。

  • 若一个进程长期处于z状态(僵尸状态),不及时回收,此时会有内存泄漏的风险!

当一个子进程结束运行时,它与其父进程之间的关联还会保持到父进程也正常地结束运行或者父进程调用了wait才告终止。
进程表中代表子进程的数据项是不会立刻释放的,虽然不再活跃了,可子进程还停留在系统里,因为它的退出码还需要保存起来以备父进程中后续的wait调用使用。它将称为一个“僵尸进程”。


#include <iostream>
#include <sys/types.h>
#include <unistd.h>
using namespace std;

int main()
{
	pid_t pid;
	cout <<"main 函数主进程 pid = "<<getpid()<<endl;
	//创建新的子进程
	pid =fork();
	if(pid ==0)
	{
		for(int i=0;i<15;i++)
		{
			cout<<"自己 getpid ="<<getpid()<<" i= "<<i<<end;
			sleep(1);
		}
	}
	else if(pid > 0)
	{
		for(int i=0;i<30;i++)
		{
			cout<<"父进程 getpid ="<<getpid()<<"i = "<<i<<end;
			sleep(1);
		}
	}
	return 0;
]

8.3、解决方案

  • 子进程exit 父进程wait

8.3.1、wait和waitpid函数

当一个进程正常或异常终止时,内核就向其父进程发送SIGCHLD信号。因为子进程终止是个异步事件(这可以在父进程运行的任何时候发生),所以这种信号也是内核向父进程发的异步通知。父进程可以忽略该信号,或者提供一个该信号发生时即被调用执行的函数(信号处理程序)。对于这种信号的系统默认动作是忽略它。
wait函数用于使父进程阻塞,直到一个子进程结束或者该进程接收到一个指定信号为止。

在这里插入图片描述

8.3.1.1、wait函数

函数说明
在这里插入图片描述
wait返回状态检测
在这里插入图片描述

8.3.1.2、waitpdi函数

函数说明
在这里插入图片描述

8.3.1.3、wait和waitpid的区别

在这里插入图片描述

8.3.2、wait函数解决孤儿进程


#include <iostream>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
using namespace std;

int main()
{
	int status =0;
	pid_t pid;
	cout <<"main 函数主进程 pid = "<<getpid()<<endl;
	//创建新的子进程
	pid =fork();
	if(pid ==0)
	{
		for(int i=0;i<30;i++)
		{
			cout<<"自己 getpid ="<<getpid()<<" i= "<<i<<end;
			sleep(1);
		}
	}
	else if(pid > 0)
	{
		for(int i=0;i<15;i++)
		{
			cout<<"父进程 getpid ="<<getpid()<<"i = "<<i<<end;
			sleep(1);
		}
		wait(&status);
	}
	return 0;
]

8.3.3、wait函数解决僵尸进程


#include <iostream>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
using namespace std;

int main()
{
	int status =0;
	pid_t pid;
	cout <<"main 函数主进程 pid = "<<getpid()<<endl;
	//创建新的子进程
	pid =fork();
	if(pid ==0)
	{
		for(int i=0;i<15;i++)
		{
			cout<<"自己 getpid ="<<getpid()<<" i= "<<i<<end;
			sleep(1);
		}
		exit(0);
	}
	else if(pid > 0)
	{
		wait(&status);//阻塞函数  等待某一个事件发生   等待子进程exit传递退出码
		for(int i=0;i<30;i++)
		{
			cout<<"父进程 getpid ="<<getpid()<<"i = "<<i<<end;
			sleep(1);
		}
		
	}
	return 0;
]

8.4、进程退出码传递示例


#include <iostream>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
using namespace std;

int main()
{
	int status =0;
	pid_t pid;
	cout <<"main 函数主进程 pid = "<<getpid()<<endl;
	//创建新的子进程
	pid =fork();
	if(pid ==0)
	{
		for(int i=0;i<15;i++)
		{
			cout<<"自己 getpid ="<<getpid()<<" i= "<<i<<end;
			sleep(1);
		}
		exit(0);
	}
	else if(pid > 0)
	{
		wait(&status);//阻塞函数  等待某一个事件发生   等待子进程exit传递退出码
		cout<<"status="<<status<<endl;
		//判断子进程是否结束
		if(WIFEXITED(status)>0)
		{
			cout<<"退出码"<<WEXITSTATUS(status)<<endl;
		}
		for(int i=0;i<30;i++)
		{
			cout<<"父进程 getpid ="<<getpid()<<"i = "<<i<<end;
			sleep(1);
		}
		
	}
	return 0;
]

9、子进程结束的方式

  • 1、return;
  • 2、break;
  • 3、exit(0);

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Spring云原生系列】Spring Cloud Stream:消息驱动架构(MDA)解析,实现异步处理与解耦合!

&#x1f389;&#x1f389;欢迎光临&#xff0c;终于等到你啦&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;持续更新的专栏《Spring 狂野之旅&#xff1a;从入门到入魔》 &a…

2024年抖店新商家自学全套教程,完整版店铺操作流程,如下!

我是王路飞。 想做一个项目的话&#xff0c;就要先了解其完整的流程是怎样的。 做抖店也不例外&#xff0c;没开店的就先了解下抖店的基本信息和大概运营流程&#xff1b;开过店的就先让自己入门并把流程跑通&#xff0c;如此才有承接后续渠道和资源的能力。 今天这篇文章专…

计算机网络:应用层知识点汇总

文章目录 一、网络应用模型二、域名系统&#xff08;DNS&#xff09;三、文本传输协议&#xff08;FTP&#xff09;四、电子邮件五、万维网和HTTP协议 一、网络应用模型 p2p也就是对等模型 二、域名系统&#xff08;DNS&#xff09; 我们知道&#xff0c;随着人们建立一个网站…

【机器学习】【决策树】分类树|回归树学习笔记总结

决策树算法概述 基本概念 决策树&#xff1a;从根节点开始一步步走到叶子节点&#xff0c;每一步都是决策过程 对于判断的先后顺序把控特别严格 一旦将判断顺序进行变化则最终的结果将可能发生改变 往往将分类效果较佳的判断条件放在前面&#xff0c;即先初略分在进行细节分…

python中的文件操作2

文件遍历 在Python中&#xff0c;遍历文件通常指的是逐行读取文件中的内容。这种方式对于处理大型文件特别有用&#xff0c;因为它不需要一次性将整个文件加载到内存中。下面是几种常见的遍历文件内容的方法&#xff1a; 1. 使用with语句和for循环 这是最推荐的方式&#xf…

[Java安全入门]三.URLDNS链

一.前言 在初步学习java的序列化和反序列化之后&#xff0c;这里学习java反序列化漏洞的一个利用链&#xff0c;也是比较基础的一条链。 由于URLDNS不需要依赖第三方的包&#xff0c;同时不限制jdk的版本&#xff0c;所以通常用于检测反序列化的点。 二.代码展开分析 构造链 …

appium解锁android真机系统的屏幕

在使用appium进行app自动化操作的过程中&#xff0c;经常遇到的第一个难题就是如何解锁系统屏幕&#xff0c;也就是亮屏解锁。 实际上解决办法如下&#xff1a;在desired_capabilities中增加两个参数unlockType和unlockKey&#xff0c;类似的示例代码如下&#xff1a; desire…

2024年腾讯云优惠政策_腾讯云服务器特价购买活动入口

腾讯云优惠活动2024新春采购节活动上线&#xff0c;云服务器价格已经出来了&#xff0c;云服务器61元一年起&#xff0c;配置和价格基本上和上个月没什么变化&#xff0c;但是新增了8888元代金券和会员续费优惠&#xff0c;腾讯云百科txybk.com整理腾讯云最新优惠活动云服务器配…

Express学习(二)

Express路由 路由的概念 现实生活中的 路由&#xff1a;例如我们在拨打10086的时候&#xff0c;会让我们按指定的按键选择对应的服务&#xff0c;这里的路由就是按键和服务之间的映射关系。 Express中的路由 在Express中&#xff0c;路由指的是客户端的请求与服务器处理函数…

基于STC系列单片机实现PNP型三极管S8550驱动共阳数码管或NPN型三极管S8050驱动共阴数码管功能

Digitron.c #include "Digitron.h" //#include "Key.h" #define uchar unsigned char//自定义无符号字符型为uchar #define uint unsigned int//自定义无符号整数型为uint //uchar code DigitronBitCodeArray[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x…

AOP理解

AOP就是面向特定的方法进行编程&#xff0c;在不改动原始方法的基础上&#xff0c;可以增强原始方法的功能&#xff0c;或者改变某些功能&#xff0c;我们可以通过AOP记录数据库的操作日志 AOP的底层实现就是动态代理技术&#xff0c;在执行原始方法前&#xff0c;生成一个代理…

【Linux】开始使用gdb吧!

开始使用gdb吧&#xff01; 1 下载安装2 开始使用3 实践运用补充一下 print 的 功能 &#xff08;类似监视窗口的作用&#xff09;和显示堆栈的功能Thanks♪(&#xff65;ω&#xff65;)&#xff89;谢谢阅读&#xff01;&#xff01;&#xff01;下一篇文章见&#xff01;&am…

JavaScript基础4之原型的原型继承、原型链和理解对象的数据属性、访问器属性

JavaScript基础 原型原型继承问题解决 原型链isPrototypeOf()Object.getPrototypeOf() 理解对象数据属性访问器属性 原型 原型继承 继承是面向对象编程的另一个特征&#xff0c;通过继承进一步提升代码封装的程度&#xff0c;JavaScript中大多是借助原型对象实现继承的特性。…

计算机基础专升本笔记十四-计算机网络基础(一)

计算机基础专升本笔记十四-计算机网络基础&#xff08;一&#xff09; 一、计算机网络的发展历程 第一代计算机网络&#xff08;数据通信&#xff09; 以数据通信为主的第一代计算机网络。主要是指美国军方用于防控系统的一种联机系统。它只是计算机网络的雏形。 第二代计算…

2022年浙江省职业院校技能大赛信息安全管理与评估 理论题答案

培训、环境、资料 公众号&#xff1a;Geek极安云科 网络安全群&#xff1a;775454947极安云科专注于技能提升&#xff0c;赋能 2024年广东省高校的技能提升&#xff0c;在培训中我们的应急响应环境 成功押题成功&#xff0c;知识点、考点、内容完美还原大赛赛题环境&#xff0c…

比肩Gen-2,全新开源文生视频模型

著名开源平台Stability.ai在官网宣布&#xff0c;推出全新文生视频的扩散模型Stable Video Diffusion&#xff0c;已开源了该项目并公布了论文。 据悉&#xff0c;用户通过文本或图像就能生成高精准&#xff0c;14帧和25帧的短视频。目前&#xff0c;Stable Video Diffusion处…

Vue+SpringBoot打造校园电商物流云平台

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 商品数据模块2.3 快递公司模块2.4 物流订单模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 商品表3.2.2 快递公司表3.2.3 物流订单表 四、系统展示五、核心代码5.1 查询商品5.2 查询快递公司5.3 查…

基于YOLOv5的驾驶员疲劳驾驶行为​​​​​​​检测系统

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文主要内容:详细介绍了疲劳驾驶行为检测整个过程&#xff0c;从数据集到训练模型到结果可视化分析。 博主简介 AI小怪兽&#xff0c;YOLO骨灰级玩家&#xff0c;1&#xff09;YOLOv5、v7、v8优化创新&#xff0c;轻松涨点和模型轻量…

一次简单操作代替所有异常处理

一、背景 在服务端处理前端发过来的响应的时候&#xff0c;开发者不可能穷尽用户的所有奇怪的操作。除此之外&#xff0c;我们还需要应付前端人员对我们的无情吐槽&#xff0c;你对XXXX请求返回的为啥是奇怪的响应数据呢&#xff1f;于是全局异常处理应运而生&#xff0c;一次处…

高级控件

1.下拉列表 package com.tiger.chapter08;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Spinner;public class Spi…