Linux操作系统:进程控制_进程的创建、终止、等待

news2024/12/26 22:53:45

一、进程创建

这一块我们在前篇都已经讲过,第一部分就简单带大家回顾一下之前的知识。

1.1 fork函数初识

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

#include<unistd.h>

pid_t fork(void);

返回值:自进程中返回0,父进程返回子进程id,出错返回-1

进程调用fork,当控制转移到内核中的fork代码后,内核做:

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

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

  运行结果为:

  这里看到了三行输出,一行before,两行after。进程15151先打印before消息,然后它有打印after。另一个after 消息有15152打印的。注意到进程15152        没有打印before,为什么呢?如下图所示 :

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

1.2 fork常规用法

  • 一个父进程希望复制自己,使父子进程同时执行不同的代码段。例如,父进程等待客户端请求,生成子进程来处理请求。
  • 一个进程要执行一个不同的程序。例如子进程从fork返回后,调用exec函数。

1.3 fork调用失败的原因

  • 系统中有太多的进程
  • 实际用户的进程数超过了限制

1.4 写时拷贝

  通常,父子代码共享,父子再不写入时,数据也是共享的,当任意一方试图写入,便以写时拷贝的方式各自一份副本。具体见下图:

   那为什么子进程要写入时,会写时拷贝一份副本,是因为父子进程之间是独立的,不能相互影响,并且写时拷贝避免了空间的浪费,做到了按需分配。

二、进程终止

2.1 终止是在做什么

  我们都知道,进程是内核数据结构加本身的代码和数据,在创建一个进程之前,操作系统会先将这个进程的内核数据结构创建好,但是页表并不会与代码和数据建立映射关系,等到将代码和数据放到内存里后再建立映射关系。

  既然我们创建进程需要创建内核数据结构和在内存中为代码和数据开辟对应的空间,那么,我们进程终止的时候要做的就是:

  • 释放曾经代码和数据所占用的空间
  • 释放内核数据结构 

  退出一个进程,首先我们已经确认它不会再被调度,所以可以直接将它的代码和数据所占用的空间释放掉,但是它的内核数据结构需要先维护起来,等待父进程的回收,此时等待父进程回收时该进程的状态就是Z:僵尸进程

2.2 退出码的介绍

  我们先来理一个关系,我们在写C/C++程序时,我们的主函数main经常要返回一个值:0,这也叫做退出码。那为什么要返会0呢?返回100可以吗?

  上述一个这么简单的代码,我们返回值是0,打印出来的结果也是没问题的。

  ppid是我们的bash进程,我们之前已经讲过,从命令行启动的进程的父进程都是bash.那我们把返回值改成100会不会有问题呢?

   返回值依然是没问题的

   所以这又能说明什么呢?

   我们直接看一个命令:echo $?   查看父进程bash获取到的最近一个进程的退出码

 

  这怎么有我们刚刚设定的返回值100。

  echo命令我们都知道,它是一个内建命令,打印的都是bash内部的变量数据,那意思是,我们的返回值是返回给bash了。那为什么要返回给bash?

  就好比,班主任派我去完成一件事,我完成之后肯定需要报告结果给班主任,所以,返回给bash,就是要告诉父进程bash,这个子进程事情完成的怎么样了

  在退出码中:

  • 0:表示成功
  • !0:表示失败

  成功不必多言,失败了肯定有失败的原因,你做一件事多次不成功,就有可能有多种原因,所以,!0的退出码一方面表示失败,另一方面也表示失败的原因。我们接下来看看不同的退出码对应的失败的原因。

  2.3 退出码对应的失败原因

  我们使用strerror函数打印每个退出码对应的失败原因

  strerror函数就是将退出码转化为失败描述:

   打印结果:

  下面还有很多,我这里只是截了一部分。

  每个退出码都对应一种失败原因,那么,bash知道进程的退出码就是为了知道失败原因?这里更重要的是,bash要为用户负责,因为用户想知道运行的进程为什么失败,bash要告诉用户原因! 

  2.4 进程终止的三种情况 

  经过2.3与2.4的学习,我们来进一步学习进程终止的三种情况:

  我们先说前两种,在上述学习部分也已经显露出来:

  • 代码跑完,结果正确
  • 代码跑完,结果失败

  正确或者不正确,我们都可以通过退出码观察出,结果失败的时候,我们也可以通过退出码去知道失败的原因。

  第三种情况,大家可能想到了:代码出现了异常,提前退出

  就比如说,我们在vs变编程运行的时候,崩溃了,是因为操作系统发现你的进程做了不该做的事情,杀死了进程

  我们先来看一种异常情况---野指针问题

   此时出现非法访问的情况,异常退出,这个错误其实就是我们平常做题时会出现的段错误。

 

  当一个进程因为异常退出时,已经跟退出码没有什么关系了,因为该进程已经提前退出了。

  那我们为什么会出现异常呢?首先是操作系统发现异常,进程出现异常退出,本质上就是进程收到了操作系统发给进程的信号。就比如上面到的“Segmentation fault”异常信号

  既然进程会被提前杀死,那我们之前讲过,我们想要退出进程有两种方式,一种是ctrl+c,另一种是命令kill.

  kill命令又有很多子命令:

  其中11就是与我们上面对应的异常信号,我们接下来将代码里的野指针问题去掉,我们在进程运行的时候,发送kiil -11 命令,就是相当于给这个进程发送了一个异常信号。

  可以看到,我们给进程发送了异常信号后进程退出。

  换句话说,当我们进程因为异常退出时,我们看退出信号是多少,就可以判断进程为什么异常了。

综上,衡量一个进程退出,我们只需要两个数字

  • 退出码
  • 进程信号

有了这两个中的任意一个,我们就可以判断出进程出现了什么错误,因为什么异常退出

2.5 进程常见退出方法

  1>正常退出

1、 return返回

  • 从main返回,就是进程终止
  • 从函数返回,表示函数结束

2. 代码调用exit函数,在代码的任意位置调用这个函数,都表示进程终止。

2>异常退出

ctrl+c,信号终止

三、进程等待

3.1 什么是等待

  任何子进程,再退出的情况下,一般必须被父进程进程进行等待,进程在退出的时候,如果父进程不管不顾,退出进程,那么子进程就会变成僵尸进程,造成内存泄露。

  所以,父进程需要通过等待,解决子进程退出的僵尸问题,回收系统资源,这个一定要考虑。另外,可以会获得子进程的退出信息,使其知道子进程是因为什么退出的。

3.2 如何等待

1、wait方法

  wait方法是等待任意进程,我们可以使用该方法来防止僵尸进程的产生。

  先看举例代码:

  在上述代码中,子进程退出之前,父进程一直在等待子进程,等到子进程退出,父进程受到子继承的退出信息,则等待成功。我们看一下运行结果 :

  当子进程退出时,父进程获取信息后也会立马退出。

  那我们让父进程也睡上十秒,也就是说,当子进程5秒退出后,父进程还要等5秒才能来回收它,那么在这5秒等待时,子进程就会出现僵尸状态。等待完毕后,父进程再等待并收到子进程的信息将它回收,僵尸状态消失。

    可以看到,子进程从僵尸状态退出。

  2、waitpid方法

 

  如果将第一个参数pid设置成-1,那么waitpid方法表达的也会是等待任意进程,如果我们想等待某个特定的的进程,那么就需要将进程的pid当作第一个参数

  wait和waitpid,都有一个status参数,该参数是一个输出型参数,由操作系统填充。如果传递NULL,表示不关心子进程的退出状态信息。否则,操作系统会根据该参数,将子进程的退出信息反馈给父进程。

  option参数设置成0,若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该子进 程的ID。

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

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

相关文章

MySQL数据库学习(持续更新ing)

1. 什么是数据库&#xff1f;什么是数据库管理系统&#xff1f;什么是SQL&#xff1f;他们之间的关系是什么&#xff1f; 数据库&#xff1a;Database&#xff0c; 简称DB。按照一定格式存储数据&#xff0c;一些文件的组合。 数据库管理系统&#xff1a;DataBaseManagement&…

电脑自动关机时间如何定?Wise Auto Shutdown 设置关机教程

在日常使用电脑的过程中&#xff0c;有时我们需要让电脑在特定的时间自动关机&#xff0c;比如在下载大文件完成后、执行长时间的任务结束时&#xff0c;或者只是单纯想在某个预定时间让电脑自动关闭以节省能源。这时候&#xff0c;Wise Auto Shutdown 这款软件就能派上大用场了…

【LeetCode热题100】队列+宽搜

这篇博客是关于队列宽搜的几道题&#xff0c;主要包括N叉树的层序遍历、二叉树的锯齿形层序遍历、二叉树最大宽度、在每个数行中找最大值。 class Solution { public:vector<vector<int>> levelOrder(Node* root) {vector<vector<int>> ret;if(!root) …

【数据结构】二叉树(2)

目录 1. 二叉树的遍历 前序遍历 中序遍历 后序遍历 2. 计算二叉树中的节点个数 3. 计算二叉树中叶子节点个数 4. 计算二叉树的深度 5. 计算二叉树第k层节点个数 6. 二叉树基础练习 7. 二叉树的创建 8. 二叉树的销毁 9. 层序遍历 10. 判断二叉树是否为完全二叉树 1…

mysql | limit X, -1 早已不可使用,本身也是一个错误

一、背景 需求&#xff1a;使用 mysql 时&#xff0c;需要获取第 X 条数据之后的所有数据。 这时&#xff0c;首先想到的就是利用 limit 来实现。 早期的部分文章或者资料中&#xff0c;提到可以使用&#xff1a; limit X,-1 例如&#xff0c;获取第一条后的所有数据&…

C++:探索AVL树旋转的奥秘

文章目录 前言 AVL树为什么要旋转&#xff1f;一、插入一个值的大概过程1. 插入一个值的大致过程2. 平衡因子更新原则3. 旋转处理的目的 二、左单旋1. 左单旋旋转方式总处理图2. 左单旋具体会遇到的情况3. 左单旋代码总结 三、右单旋1. 右单旋旋转方式总处理图2. 右单旋具体会遇…

开发一套ERP 第二弹

前后端分离 一起做,发现会有点问题,有时候分不太清楚 可以使用 naive ui admin 作为前端 menu 的配置在mock 中,在mock 中修改为自己需要的选项即可,mock 中返回的是前端需要测试的数据接口 同理自己需要的API也可以定义到 api 中&#xff0c;然后在mock 中配置返回的结果;然后…

cangjie (仓颉) vscode环境搭建

sdk下载 下载中心-仓颉编程语言官网 可选择半年更新版&#xff0c;不用申请。目前版本&#xff1a;0.53.13 &#xff0c;选择不同平台压缩包下载解压到任意位置即可 补充下载&#xff0c;vscode插件解压后&#xff0c;在vscode扩展中选择从vsix安装&#xff0c;安装后新增名为…

ES6 、ESNext 规范、编译工具babel

ES6 、ESNext 规范、编译工具简介 ES6ES&#xff08;ECMAScript&#xff09; vs JS常量进一步探讨 obj对象的扩展面试&#xff1a;使对象属性也不能更改——Object.freeze(obj) 解构deconstruction变量的解构赋值&#xff1a;数组解构赋值&#xff1a;对象解构赋值&#xff1a;…

SQL 语句执行计划中的连接方式

SQL 语句执行计划中的连接方式 join操作 join操作基本分为3大类&#xff1a;外连接&#xff08;细分为&#xff1a;左连接&#xff08;Left outer join/ left join&#xff09;、右连接&#xff08;right outer join/ right join&#xff09;、全连接&#xff08;full outer …

数据结构第一讲

数据结构定义 算法的定义 什么是好算法&#xff1f; 空间复杂度 时间复杂度 例子1 打印1到N之间的正整数 有递归和循环两种方法实现。 但是在数字变大后&#xff0c;递归的方法会导致内存占用过多而崩溃。 而循环则不会 例子2 写程序给定多项式在X处的值 从里往外算的算…

--- 文件IO java ---

文本文件和二进制文件 文件再底层其实就是以一段二进制数据的形式储存的&#xff0c;当我用记事本打开文件时&#xff0c;有些文件会出现乱码&#xff0c;这就是二进制文件&#xff0c;而有一些文件是特殊的&#xff0c;他以特定的编码方式&#xff08;比如ascll&#xff09;可…

洛谷 P1616 疯狂的采药 C语言 记忆化搜索

题目&#xff1a; https://www.luogu.com.cn/problem/P1616?contestId215526 完全背包问题&#xff0c;最后一个超出空间了。完全背包和就是无限次的拿&#xff0c;公式跟01背包差不多。 但是&#xff0c;只有当前能拿和拿不下&#xff0c;换下一个。注意要处理好边界条件。…

java基础概念37:正则表达式2-爬虫

一、定义 【回顾】正则表达式的作用 作用一&#xff1a;校验字符串是否满足规则作用二&#xff1a;在一段文本中查找满足要求的内容——爬虫 二、本地爬虫VS网络爬虫 2-1、本地爬虫 示例&#xff1a; 代码优化&#xff1a; public static void main(String[] args) {// 大…

多目标跟踪算法

文章目录 一、传统方法1. 基于卡尔曼滤波器的方法1.1 Kalman Filter(卡尔曼滤波器) 2. 基于数据关联的方法2.1 匈牙利算法 二、深度学习方法1. 基于检测的多目标跟踪1.1 SORT算法1.2 DeepSort1.3 BoT-SORT 2. 基于特征关联和增强的方法2.1 ByteTrack 3. 基于Transformer的方法3…

网络(TCP)

目录 TCP socket API 详解 bind(): 我们的程序中对myaddr参数是这样初始化的: listen(): accept(): 理解accecpt的返回值: 饭店拉客例子 connect tcp服务器和udp类似的部分代码 把套接字设置为监听状态&#xff08;listen&#xff09; 测试 查看端口号和IP地址&…

阿里云 DevOps 资源安全扫描实践

随着企业上云进程的加速&#xff0c;云资源的使用量日益增长&#xff0c;云环境中资源的安全性和稳定性成为了企业业务运营的关键要素 面对多样化的云资源和复杂的应用场景&#xff0c;传统的安全管理手段已无法完全满足企业日益严苛的安全需求。为了确保云上资源的安全性&…

WebGL进阶(十一)层次模型

理论基础&#xff1a; 效果&#xff1a; 源码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"vie…

vscode下面python调试报错ImportError: cannot import name ‘Literal‘ from ‘typing‘

1 问题描述 我在vscode下面编写python程序&#xff0c;这个程序是在一个英伟达anoconda环境下的项目。之前能运行能调试&#xff0c;最近发现只能运行ctlf5&#xff0c;但是使用f5进行调试时&#xff0c;报错“File “c:\Users\86137.vscode\extensions\ms-python.debugpy-202…

(免费送源码)计算机毕业设计原创定制:Java+JSP+HTML+JQUERY+AJAX+MySQL springboot计算机类专业考研学习网站管理系统

摘 要 大数据时代下&#xff0c;数据呈爆炸式地增长。为了迎合信息化时代的潮流和信息化安全的要求&#xff0c;利用互联网服务于其他行业&#xff0c;促进生产&#xff0c;已经是成为一种势不可挡的趋势。在大学生在线计算机类专业考研学习网站管理的要求下&#xff0c;开发一…