【Linux】详谈 进程控制

目录

一、进程是什么

二、task_struct

三、查看进程

四、创建进程

4.1 fork函数的认识

4.2 2. fork函数的返回值

五、进程终止

5.1. 进程退出的场景

5.2. 进程常见的退出方法

5.2.1 从main返回

5.2.1.1 错误码

 5.2.2 exit函数

5.2.3 _exit函数

5.2.4 缓冲区问题补充(为什么_exit不刷新缓冲区)

六、进程等待

6.1. wait和waitpid等待回收子进程 

6.2 阻塞与非阻塞


Linux专栏:传送门!

一、进程是什么

在操作系统中,进程是资源分配和独立运行的基本单位。它是程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位。单纯的只看一个定义很难理解什么是进程

我们磁盘中的可执行程序,CPU要想拿到并且执行,代码和数据要先放在内存中。操作系统是一个软件在内存中,当磁盘中的可执行程序被内存拿到,可执行程序的代码和数据会被内存拿到,内存中的操作系统会对代码和数据进行描述然后组织为数据结构(先组织在描述)形成内核数据结构对象,对进程的管理就变成了对数据结构对象的增删查改。 内核数据结构对象可以称为PCB,也叫做进程控制块。

内核数据结构对象通过指针指向本身的代码和数据也指向下一个结构体,进而形成真正的进程。进程=内核数据结构对象+自己的代码和数据。 这个数据结构就是进程列表。CPU对进程列表进行调度

二、task_struct

在Linux中描述进程的结构体叫做task_struct。
task_struct是Linux内核的⼀种数据结构,它会被装载到RAM(内存)里并且包含着进程的信息。

  • 标示符: 描述本进程的唯一标示符,用来区别其他进程。
  • 状态: 任务状态,退出代码,退出信号等。
  • 优先级: 相对于其他进程的优先级。
  • 程序计数器: 程序中即将被执行的下一条指令的地址。
  • 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
  • 上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]。
  • I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
  • 记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
  • 其他信息

三、查看进程

进程的信息可以通过/proc 系统文件夹查看
如:要获取PID为1的进程信息,你需要查看/proc/1 这个文件夹。

大多数进程信息同样可以使用top和ps这些用户级工具来获取

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{while(1){sleep(1);}return 0;
}

通过系统调用获取进程标示符

• 进程id(PID)
• 父进程id(PPID)

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{printf("pid: %d\n", getpid());printf("ppid: %d\n", getppid());return 0;
}

四、创建进程

4.1 fork函数的认识

在linux中fork函数非常重要, 它从已存在的进程中创建一个新的进程, 新进程为子进程,而原进程为父进程。

#include<unistd.h>
pid_t fork(void);
返回值:子进程中返回0, 父进程中返回子进程id, 出现错误则返回-1

进程调用fork,当控制转移到内核中的fork代码后, 内核会做下面几件事情:

  1. 分配新的内存块和内核数据结构给子进程
  2. 将父进程部分数据结构内容拷贝至子进程
  3. 添加子进程到系统进程列表中
  4. fork返回, 开始调度器调度

当一个进程调用fork()之后,就有两个二进制代码相同的进程。而且他们都运行到相同的地方。但每个进程都将可以开始他们自己的旅程。

这里我们看到了三行输出, 一行before, 两行after,父进程先打印before消息,然后它又打印after,另一个after消息有子进程打印的,但是子进程没有打印before,为什么呢?

所以, fork()之前父进程独立执行,fork()之后,父子两个执行流分别执行,注意,fork之后,谁先执行由调度器决定。

4.2 2. fork函数的返回值

子进程返回0,父进程返回的是子进程的pid。

父进程与子进程是一对多的关系,父进程:子进程=1:N。对于子进程来说它只有一个父进程,对于父进程来说他有多个父进程。为了管理这些进程,所有父进程返回子进程的PID具有唯一性。子进程要想找到父进程肯定更方便。

为什么有两个返回值, 因为fork之后是两个不同的进程, 而返回值也是给不同的进程。

#include <stdio.h>  
#include <stdlib.h>  
#include <unistd.h>  int main() {  pid_t pid = fork();  // 执行 fork()  if (pid < 0) {       // 处理 fork 失败的情况  perror("fork failed");  exit(EXIT_FAILURE);  } else if (pid == 0) { // 子进程执行  printf("This is the child process (PID: %d)\n", getpid());  } else {              // 父进程执行  printf("This is the parent process (PID: %d, Child PID: %d)\n", getpid(), pid);  }  return 0;            // 所有进程执行完毕  
}

执行fork函数,会为子进程创建一个和父进程一样的PCB。但是他们所指向的代码都是一样的,所以他们的代码共享。也就是说父进程和子进程共享代码中return,都执行return。

五、进程终止

本质:释放系统资源, 就是释放进程申请的相关内核数据结构和对应的代码和数据。

5.1. 进程退出的场景

  • 代码运行完毕, 结果正确
  • 代码运行完毕,结果不正确
  • 代码异常终止

5.2. 进程常见的退出方法

5.2.1 从main返回

除了main函数的返回值表示进程结束,其它函数的return都表示函数结束。

5.2.1.1 错误码

main函数的返回值是返回给父进程或者系统的,命令行中获取最近一个进程的返回值我们可以使用echo $?来获取

对于返回值,0表示成功, 非0表示错误,为什么会失败呢?系统提供了不同的错误码信息记录了错误的原因, 也可以自己约定错误码。

那么什么是错误码呢?

举个栗子:

如果想要查看错误码, 我们可以使用errno函数, 使用man可以查看命令详情。

man 3 errno

如果想知道具体的错误内容, 可以使用strerror函数,参数传递错误码。

man 3 strerror

 5.2.2 exit函数

在代码的任何地方, 让进程直接结束。参数就是返回的错误码。

如果使用exit, 如果缓冲区有数据, 则会被刷新出来。

5.2.3 _exit函数

是系统层的进程终止调用

如果使用_exit, 缓冲区的数据则不会被刷新出来。

5.2.4 缓冲区问题补充(为什么_exit不刷新缓冲区)

exit属于是语言级别的,在三号手册, 而_exit是系统级别的,在二号手册。

_exit本质上是系统调用

所以我们上面的_exit实际上是绕过了语言层, 直接进行了系统调用, 而刚刚的缓冲区是语言级别的, fflush也是语言级别的。

六、进程等待

首先我们可以查看一下fork的返回值, 如果fork失败, 则错误码会被设置。

6.1. wait和waitpid等待回收子进程 

一般而言, 父进程创建的子进程, 父进程就要等待子进程进行回收, 如果子进程一直不退出, 则父进程就会阻塞在wait内部。

wait的作用,等待任意的子进程(参数可以传nullptr表示不获取status)

常用:
waitpid的作用:第一个参数 pid>0表示等待指定的一个进程,pid == -1表示等待任意一个子进程

看一下他们的返回值, 如果等待成功则返回对应的子进程,如果等待失败则返回-1.

举个栗子

等待任何一个子进程

当然, 我也可以修改id的参数,比如更换为刚刚子进程id,这里就不展示了。

waitpid的第二个参数,它会帮助父进程获取子进程的退出信息,通过参数的方式给我们带出来。输出型参数

但是这里的退出信息却是256,为什么不是1呢?

其实,status这个参数包含的信息并不只是退出码,它的本质是一个位图, 它的结构中前八位是退出状态,有256种状态 ,低七位是终止信号, 还有一个标志位。

如果想要提取退出状态则需要进行位运算,如下

小问题: 那我们可不可以不使用status来获取状态码,而是用一个全局变量呢?

不可以, 因为进程具有独立性,子进程修改父进程看不到,会发生写时拷贝。

6.2 阻塞与非阻塞

waitpid的第三个参数就是关于阻塞等待与非阻塞等待

首先waitpid的返回值, 如果>0表示,返回目标进程pid, 如果 == 0, 等待成功,但是子进程没有退出, <0 等待失败.

参数如果传0表示阻塞等待, 如果传WNOHANG表示非阻塞等待

举个栗子:

总结

进程控制是操作系统中的一个重要主题,主要涉及如何管理和调度进程以确保计算机系统的高效运行!


本篇完,下篇见!

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

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

相关文章

Visonpro 检测是否有缺齿

一、效果展示 二、上面是原展开工具CogPolarUnwrapTool&#xff1b; 第二种方法&#xff1a; 用Blob 和 CogCopyRegionTool 三、 用预处理工具 加减常数&#xff0c;让图片变得更亮点 四、圆展开工具 五、模板匹配 六、代码分解 1.创建集合和文子显示工具 CogGraphicCollec…

RabbitMQ介绍以及基本使用

文章目录 一、什么是消息队列&#xff1f; 二、消息队列的作用&#xff08;优点&#xff09; 1、解耦 2、流量削峰 3、异步 4、顺序性 三、RabbitMQ基本结构 四、RabbitMQ队列模式 1、简单队列模式 2、工作队列模式 3、发布/订阅模式 4、路由模式 5、主题模式 6、…

服务器租用:虚拟化技术都包含哪些内容?

服务器作为常见的网络设备&#xff0c;有着物理服务器、云服务器和虚拟服务器等多种类型&#xff0c;其中虚拟服务器主要是依靠虚拟化技术将物理服务器划分成多个虚拟机&#xff0c;以此来充分利用服务器资源&#xff0c;那虚拟化技术都包含了哪些内容呢&#xff1f; 硬件虚拟化…

基于JAVA的幼儿园管理系统的设计与实现源码(springboot+vue+mysql)

项目简介 幼儿园管理系统实现了以下功能&#xff1a; 基于JAVA的幼儿园管理系统的设计与实现的主要使用者管理员可以管理系统基本信息&#xff1b;管理轮播图、系统简介、教师管理、课程管理、幼儿活动管理、餐饮管理、留言管理等功能&#xff1b;前台用户注册登录&#xff0…

sql难点

一、 假设你有一个查询&#xff0c;需要根据 id 是否为 null 来动态生成 SQL 条件&#xff1a; xml复制 <select id"getResources" resultType"Resource">SELECT * FROM resources<where><if test"id ! null">and id <!…

《Operating System Concepts》阅读笔记:p13-p16

《Operating System Concepts》学习第 4 天&#xff0c;p13-p16 总结&#xff0c;总计 4 页。 一、技术总结 1.storage 指令只能在 memory 上执行&#xff0c;所以要执行程序&#xff0c;那么就要加载到内存上。 2.primary storage primary storage 包含下面这些分类&…

最新国内 ChatGPT Plus/Pro 获取教程

最后更新版本&#xff1a;20250202 教程介绍&#xff1a; 本文将详细介绍如何快速获取一张虚拟信用卡&#xff0c;并通过该卡来获取ChatGPT Plus和ChatGPT Pro。 # 教程全程约15分钟开通ChatGPT Plus会员帐号前准备工作 一个尚未升级的ChatGPT帐号&#xff01;一张虚拟信用卡…

Python中使用Minio实现图像或视频文件的存储

目录 一、Minio的基本介绍1.Minio是什么2.Minio的优势 二、使用步骤1.启动Minio2.创建桶3.在Python中使用Minio3.1安装并导入minio包3.2创建mino_utils工具类 三、操作演示1.引入minio_utils工具类2.上传视频文件3.获取视频文件 总结 一、Minio的基本介绍 1.Minio是什么 Mini…

[JVM篇]虚拟机性能监控、故障处理工具

虚拟机性能监控、故障处理工具 基础故障处理工具 jps&#xff08;JVM Peocess Status Tool - 虚拟机进程状况工具&#xff09; jstat(JVM Statistics Monitoring Too - 虚拟机统计信息监视工具) jinfo( Configuration info for Java - Java配置信息工具) jmap(Memory Map for…

【数据结构】(9) 优先级队列(堆)

一、优先级队列 优先级队列不同于队列&#xff0c;队列是先进先出&#xff0c;优先级队列是优先级最高的先出。一般有两种操作&#xff1a;返回最高优先级对象&#xff0c;添加一个新对象。 二、堆 2.1、什么是堆 堆也是一种数据结构&#xff0c;是一棵完全二叉树&#xff0c…

快速设置 Docker 网络代理配置

Docker Client - 代理访问远程的 Docker Daemon 在 Client 端设置代理其实就是设置 Linux 系统的代理&#xff0c;从而让系统的命令行可以通过代理连接到外部的网络。一般只需要配置 HTTP_PROXY 与 HTTPS_PROXY 这两个即可。 临时生效&#xff1a; 在命令行中执行下面的命令&…

Vript-Hard——一个基于高分辨率和详细字幕的视频理解算法

一、概述 多模态学习的最新进展促进了对视频理解和生成模型的研究。随之而来的是&#xff0c;对高分辨率视频和详细说明所建立的高质量数据集的需求激增。然而&#xff0c;由于时间因素的影响&#xff0c;视频与文本的配对不像图像那样容易。准备视频和文本配对是一项困难得多…

记录阿里云CDN配置

网站接入CDN全流程&#xff0c;共4步&#xff01;-阿里云开发者社区 1、开通阿里云CDN服务 2、添加加速域名 3、验证域名归属权 4、域名添加CDN生成的CNAME解析 按照官网描述增加。细节点&#xff1a; 1. 域名和泛域名区别 2.开启https,要用nginx的证书&#xff0c;和项…

FFmpeg源码:url_find_protocol函数分析

一、url_find_protocol函数的定义 url_find_protocol函数定义在FFmpeg源码&#xff08;本文演示用的FFmpeg源码版本为7.0.1&#xff09;的源文件libavformat/avio.c中&#xff1a; static const struct URLProtocol *url_find_protocol(const char *filename) {const URLProt…

DeepSeek 助力 Vue 开发:打造丝滑的无限滚动(Infinite Scroll)

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…

【区块链】零知识证明基础概念详解

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 零知识证明基础概念详解引言1. 零知识证明的定义与特性1.1 基本定义1.2 三个核心…

蓝桥杯篇---IAP15F2K61S2串口

文章目录 前言简介串口通信的基本参数1.波特率2.数据位3.停止位4.校验位 串口相关寄存器1.SCON2.SBUF3.PCON4.TMOD5.TH1/TL1 串口使用步骤1.配置波特率2.配置串口模式3.使能串口中断4.发送数据5.接收数据6.处理中断 示例代码&#xff1a;串口发送与接收示例代码&#xff1a;串口…

「vue3-element-admin」Vue3 + TypeScript 项目整合 Animate.css 动画效果实战指南

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall ︱vue3-element-admin︱youlai-boot︱vue-uniapp-template &#x1f33a; 仓库主页&#xff1a; GitCode︱ Gitee ︱ Github &#x1f496; 欢迎点赞 &#x1f44d; 收藏 ⭐评论 …

MyBatis:动态SQL高级标签使用方法指南

一、引言 目前互联网大厂在搭建后端Java服务时&#xff0c;常使用Springboot搭配Mybatis/Mybatis-plus的框架。Mybatis/Mybatis-plus之所以能成为当前国内主流的持久层框架&#xff0c;与其本身的优点有关&#xff1a;支持定制动态 SQL、存储过程及高级映射&#xff0c;简化数…

untiy3D 让角色动起来,角色动画的使用

1.untiy 商店下载动画模型 2.导入项目 模型拖入到场景中 3.创建动画器控制器 4.动画控制器挂载到plarer上 5.把动画idle和pickup拖入到动画器 6.右键动画创建过渡效果(Make Transition) 6.设置参数用条件控制 7.当选中参数时启动过渡 运行效果 119 (二)用脚本控制动画…