【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);

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI论文速读 | 【综述】城市计算中跨域数据融合的深度学习:分类、进展和展望

题目&#xff1a;Deep Learning for Cross-Domain Data Fusion in Urban Computing: Taxonomy, Advances, and Outlook 作者&#xff1a;Xingchen Zou, Yibo Yan, Xixuan Hao, Yuehong Hu, Haomin Wen&#xff08;温皓珉&#xff09;, Erdong Liu, Junbo Zhang&#xff08;张钧…

Latex公式太长换行标号

Latex中公式太长换行,且编号,可以采用align,不编号行公式用\nonumber,示例如下: \begin{align}\nonumber %第1行公式不编号&a+b+a+b+a+b+a+b+a+b+a+b+a+b+a\\&+c+d=m %第2行公式编号 \end{align}效果如下 原文件链接 公式不同命令的区别 \begin{align} 与 \…

element-plus upload上传

vue3 element-plus 2.4.3 <script> const submitUpload () > {// 单文件proxy.$refs["uploadRef"].submit(); }const uploadFile (options) > {let formData new FormData();formData.append("file", options.file)return uploadFileWith…

首发:鸿蒙面试真题分享【独此一份】

最早在23年华为秋季发布会中&#xff0c;就已经宣布了“纯血鸿蒙”。而目前鸿蒙处于星河版中&#xff0c;加速了各大互联网厂商的合作。目前已经有200参与鸿蒙的原生应用开发当中。对此各大招聘网站上的鸿蒙开发需求&#xff0c;每日都在增长中。 2024大厂面试真题 目前的鸿蒙…

从huggingface下载模型像本地加载但是UnicodeDecodeError

我自己是在Linux下出现了这个问题 原文&#xff1a;https://github.com/huggingface/transformers/issues/13674 The path for the AutoModel should be to a directory pointing to a pytorch_model.bin and to a config.json. Since you’re pointing to the .bin file dire…

Java多线程——synchronized、volatile 保障可见性

目录 引出synchronized、volatile 保障可见性Redis冲冲冲——缓存三兄弟&#xff1a;缓存击穿、穿透、雪崩缓存击穿缓存穿透缓存雪崩 总结 引出 Java多线程——synchronized、volatile 保障可见性 synchronized、volatile 保障可见性 原子性&#xff1a;在一次或者多次操作时…

实操keepalived(高可用)+Nginx(四层代理+七层代理),实现高可用、负载均衡以及动静分离

一 vrrp技术 VRRP 相关术语 VRRP能够在不改变组网的情况下&#xff0c;将多台路由器虚拟成一个虚拟路由器&#xff0c;i通过配置虚拟路由器的IP地址为默认网关&#xff0c;实现网关的备份。 协议版本: VRRPv2 (常用) 和VRRPv3:0 VRRPv2仅适用于IPv4网络&#xff0c;VRRPv3适用…

经典语义分割(二)医学图像分割模型UNet

经典语义分割(二)医学图像分割模型UNet 我们之前介绍了全卷积神经网络( FCN) &#xff0c;FCN是基于深度学习的语义分割算法的开山之作。 今天我们介绍另一个语义分割的经典模型—UNet&#xff0c;它兼具轻量化与高性能&#xff0c;通常作为语义分割任务的基线测试模型&#x…

hdu-2059(dp)

hdu-2059 龟兔赛跑 dp[i] 表示到第i个站所花费的最少时间&#xff0c;t[j][k]表示在第j个站充满电&#xff0c;直接开到第k个站所花的时间&#xff0c;那么状态转移为: dp[i] min(dp[i], dp[j] t[j][i]) 含义为&#xff0c;假设我们当前想知道到达第i个站的最少时间&#xff…

Java定时调度范式定时操作

在 Java 中&#xff0c;我们可以使用各种方法来执行定时操作。这些操作包括执行任务、调度任务、执行重复任务等。下面将介绍几种常见的 Java 定时调度范式。 1. Timer 和 TimerTask Java 提供了 Timer 和 TimerTask 类&#xff0c;用于执行定时任务。 示例代码&#xff1a;…

RK3568平台 USB数据包的收发格式

一.USB硬件拓扑结构 compound device &#xff1a;多个设备组合起来&#xff0c;通过HUB跟Host相连composite device &#xff1a;一个物理设备有多个逻辑设备(multiple interfaces) 在软件开发过程中&#xff0c;我们可以忽略Hub的存在&#xff0c;硬件拓扑图简化如下&#x…

【精品】集合list去重

示例一&#xff1a;对于简单类型&#xff0c;比如String public static void main(String[] args) {List<String> list new ArrayList< >();list.add("aaa");list.add("bbb");list.add("bbb");list.add("ccc");list.add(…