进程控制的学习

目录

1.进程创建

1.1 fork函数

1.2 fork函数返回值

1.3 写时拷贝

1.4 fork 常规用法

1.5 fork 调用失败的原因

2. 进程终止

2.1 进程退出场景

2.2 进程常见退出方法

2.2.1 从main 返回

2.2.2 echo $? 查看进程退出码

2.2.2.1 我们如何得到退出码代表的含义

2.2.2.1 可以按照我们的要求去定制我们的退出结果

2.2.2.2 一旦进程出现异常,进程的退出码就没有意义了

2.2.3 exit 函数

2.2.4 _exit 函数

exit(status)  VS    _exit(status)

2.2.5 return退出

3. 进程等待

3.1 进程等待的必要性(为什么?)

3.2 进程等待是什么?

3.3 进程等待的代码

3.3.1 wait

3.3.2 waitpid

3.4 拿到对应的退出信息  status

正确的写法

进程退出码,即main返回值

无异常

异常

退出信息应该存在哪里?

3.5 阻塞等待与非阻塞等待

4. 进程程序替换

4.1 快速看程序替换的效果

4.2 替换原理   --    fork

4.3 程序替换相关接口

4.3.1 execl

4.3.1.1

4.3.1.2

4.3.1.3

4.3.2 execlp

4.3.3  execv

4.3.4  execvp

4.3.5  execvpe

新增式导入

1.直接putenv

2. exec*p,put();environ;


1.进程创建

1.1 fork函数

fork 从已经存在的进程中创建一个新进程,新进程为子进程原进程为父进程

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

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

1)分配新的内存块和内核数据结构给子进程

2)将父进程部分数据内容拷贝至子进程

3)添加子进程到系统进程列表当中

4)fork返回,开始调度器调度

fork之前父进程独立执行,fork之后父子两个执行流分别执行

fork之后谁先调度完由调度器决定

1.2 fork函数返回值

子进程返回0

父进程返回的是子进程的pid

1.3 写时拷贝

父子进程代码共享,父子在不写入时,数据也是共享的

当一方试图写入时,就用写时拷贝的方式各自一份副本

因为有写时拷贝,所以父子进程得以彻底分离,完成了进程独立性

当我们创建子进程时,OS除了给我们创建子进程之外,基本上会把我们页表的项目都改成只读的。拿到虚拟地址,OS可以知道我们是代码段还是数据段。我们修改写入时,发现是数据段是只读的,OS就会出错,让os知道我们在访问只读的数据区,就会触发写实拷贝

写实拷贝是最精细的内存控制

减少创建时间

减少内存浪费

1.4 fork 常规用法

1)一个父进程希望复制自己使父子进程执行不同的代码段

eg:父进程等待客户端请求,生成子进程来处理请求

2)一个进程要执行一个不同的程序

eg:子进程从fork返回后,调用exec函数

1.5 fork 调用失败的原因

1)系统中有太多的进程

2)实际客户的进程数超过了限制

2. 进程终止

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

2.1 进程退出场景

1)代码运行完毕,结果正确         

2)代码运行完毕,结果不正确 

3)代码异常终止

2.2 进程常见退出方法

2.2.1 从main 返回

int main();

main函数的返回值通常表明我们程序的执行情况

而这里的情况有两种

1)代码运行完毕,结果正确          return 0

2)代码运行完毕,结果不正确       return !0  (1,2,3...)--> 在计算机上用不同的值表明不同的                                                                                                      出错原因

返回值是通过寄存器完成的

2.2.2 echo $? 查看进程退出码

./code   是一个进程 父进程为bash

父进程bash要获得子进程退出的退出码

echo $?   打印最近一个程序(进程)退出时的退出码

main函数的返回值我们称之为进程的退出码

进程的退出码是要写到进程的task_struct内部的,task_struct里面保存的是进程的所有属性信息

2.2.2.1 我们如何得到退出码代表的含义

我们这里要实现错误码就是对应的错误描述

因为我们没有这个文件/目录,所有打开失败,就是2

2)

根据退出码来判断当前程序的执行结果

运行结果是否正确由我们进程的退出码决定,0代表正确,非0有不同的退出错误原因

2.2.2.1 可以按照我们的要求去定制我们的退出结果

2.2.2.2 一旦进程出现异常,进程的退出码就没有意义了

进程的退出码不是 66 

一旦进程出现异常,进程的退出码就没有意义了

进程一旦出现异常,一般是进程收到了信号

main函数结束,表示进程结束

2.2.3 exit 函数

1)

(忘记写头文件了)

2)

在任何地方调用exit,表示进程结束,并且返回子进程的退出码给父进程bash

一旦调用exit,程序立马结束,函数后续代码不执行,进程直接退出

2.2.4 _exit 函数

谁调用我们就退出谁

exit(status)  VS    _exit(status)

是我们C语言的      是系统的

如果进程退出的时候, exit() ,进程退出的时候,会进行缓冲区的刷新

如果进程退出的时候,_exit() ,进程退出的时候,不会进行缓冲区的刷新

库函数和系统调用是上下层关系

exit底层封装了_exit

本来就是系统调用

底层调用了_exit

所以我们之前谈论的缓冲区一定不是操作系统内部的缓冲区,它应该是在库缓冲区(C语言·提供的缓冲区)

2.2.5 return退出

return退出是一种更常见的退出进程的方法。

执行 return n 等同于执行  exit(n),因为调用 main 的运行时函数会将 main 的返回值当作 exit 的参数

进程退出的具体做法

1)main 函数里 return

2)exit(status)

             控制进程的退出码

3. 进程等待

3.1 进程等待的必要性(为什么?)

1)子进程退出,父进程不管,就可能会造成僵尸进程的问题,进而造成内存泄漏

2)进程一旦变成僵尸状态,kill-9 也没有办法,谁也没有办法杀死一个已经死去的进程

3)我们需要知道父进程派给子进程的任务完成得如何

      子进程运行完成,结果正确还是不正确,是否正常退出

4)父进程通过进程等待得方式,回收子进程资源,获取子进程退出信息

(通过等待来解决僵尸内存泄漏问题)

3.2 进程等待是什么?

父进程创建子进程,必须通过相关的接口来等待子进程

这种用wait或waitpid来等待子进程的方式就叫作进程等待

3.3 进程等待的代码

3.3.1 wait

wait 这个接口是等待任意一个退出的进程

等待成功返回的是目标进程的pid

等待失败返回-1

3.3.2 waitpid

等待成功返回的是目标进程的pid

等待失败返回-1

3.4 拿到对应的退出信息  status

wait和waitpid都有一个status参数,这个参数是一个输出型参数,由操作系统填充

如果传递NULL,表示不关心进程的退出状态信息

否则,OS会根据该参数,将子进程的退出信息反馈给父进程

status不能简单地当作整型来看待,当作位图来看待

status 并不是直接一个整数,是被划分成若干区域的

int 整型变量32个bit位,高16位我们不考虑,低16位高8位是退出状态

我们刚刚写的1就是00000001

但是后面还有八位,就是0000000100000000,就是2^8,256

我们要拿到正确的就要右移8位,踢掉低8位

正确的写法

父进程是无法拿到子进程的退出信息的,子进程退出信息是会修改的,定义在全局不能够实现,拿到子进程的退出信息必须通过系统调用

进程退出码,即main返回值

1)运行完毕,结果正确

2)运行完毕,结果不正确

3)代码异常终止

                  status

代码异常终止,保存异常时对应的信号编号

没有异常?

1.低7个bit位,0

2.一旦低7个bit位 !0,异常退出,退出码无意义

无异常

异常

1)

2)

怎么做到的?

退出信息应该存在哪里?

3.5 阻塞等待与非阻塞等待

options默认为0,表示阻塞等待

非阻塞轮询

非阻塞的效率往往要高一点

阻塞等待

定义:当一个操作需要等待某个条件完成才能继续执行时,如果当前线程被挂起,无法执行其他               任务,这种状态就称为阻塞

特点:在阻塞状态下,程序会一直等待,直到等待的条件满足,操作完成并返回结果后,才能继               续执行后续任务

非阻塞等待

定义:非阻塞是指即使某个操作尚未完成,当前线程也不会被挂起,可以继续执行其他任务

特点:在非阻塞模式下,程序不会等待某个操作的完成,而是会立即返回一个结果或者状态,表

           明该操作正在进行中或者已经失败

           适用于需要同时处理多个任务或提高资源利用率的场景

           可以提高整体执行效率

对比

阻塞等待时,线程被挂起;非阻塞等待时,线程继续执行其他任务

阻塞等待可能导致资源闲置;非阻塞等待可以提高资源利用率

4. 进程程序替换

4.1 快速看程序替换的效果

在程序替换的过程中并没有创建新的进程,只是把当前进程的代码和数据用新的程序的代码和数据进行替换

1)一旦替换成功,就去执行新代码了,原始代码的后半部分已经不存在了,是不会去执行的

前半部分是我们的printf,后半部分就是ls的结果

这个指令可以跑系统的命令

整个替换过程只替换当前的代码和数据

(默认是覆盖掉的)

把我们要替换的对应的指令所对应的代码和数据覆盖式地替换到我们当前的代码和数据

2)exec系列的函数,只有失败返回值没有成功返回值

exec系列的函数不用做返回值判断,只要返回就是失败

替换失败我们设置为1

4.2 替换原理   --    fork

用fork创建子进程后执行的是和父进程相同的程序,子进程往往要调用一种exec函数去执行另一个程序,当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行

调用exec并不创建新进程,所以调用exec前后该进程的id不会改变

4.3 程序替换相关接口

4.3.1 execl

4.3.1.1

我们可以创建一个子进程,让子进程执行程序的替换不影响父进程的执行

进程具有独立性

数据代码发生写时拷贝

4.3.1.2

现在我们来实现替换我们自己写的程序

我们今天就想要用我们的C程序来把other程序调起来

4.3.1.3

验证程序替换不会创建新的进程

4.3.2 execlp

4.3.3  execv

4.3.4  execvp

4.3.5  execvpe

要求被替换的子进程使用全新的env表

而我们如果要新增子进程?方法(把环境变量传给子进程;新增式导入)

新增式导入
1.直接putenv

谁调用它就在谁那里创建环境变量

2. exec*p,put();environ;

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

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

相关文章

数据结构与算法分析:专题内容——人工智能中的寻路7之AlphaBeta(代码详解)

一、算法描述 在考虑到对手的可能走法之后,Minimax算法能够较为恰当地找出玩家的最优走法。但是,在生成博弈树时,这个信息却没有使用!我们看看早先介绍的BoardEvaluation评分函数。回忆一下下图Minimax的探测: 这是从…

12、本地缓存分布式缓存(未完待续)

1、哪些数据适合放入缓存? 即时性、数据一致性要求不高的访问量大且更新频率不高的数据(读多,写少) 2、本地缓存 1、本地缓存,如果是单体项目,部署到一台服务器上,就不存在什么问题&#xff…

Linux——网络基础(1)

文章目录 目录 文章目录 前言 一、文件传输协议 应用层 传输层 网络层 数据链路层 数据接收与解封装 主机与网卡 数据传输过程示意 二、IP和MAC地址 定义与性质 地址格式 分配方式 作用范围 可见性与可获取性 生活例子 定义 用途 特点 联系 四、TCP和UDP协…

免费GPU算力,不花钱部署DeepSeek-R1

在人工智能和大模型技术飞速发展的今天,越来越多的开发者和研究者希望能够亲自体验和微调大模型,以便更好地理解和应用这些先进的技术。然而,高昂的GPU算力成本往往成为了阻碍大家探索的瓶颈。幸运的是,腾讯云Cloud Studio提供了免…

阿里前端开发规范

文章目录 1. 为什么前端写代码要规范?一、代码规范的必要性二、 规范带来的好处 2. 资源一、推荐 1. 为什么前端写代码要规范? 一、代码规范的必要性 可维护性 统一的代码风格便于理解和修改减少代码维护成本降低项目交接难度 团队协作 提高团队开发效…

Linux 小火车

1.添加epel软件源 2.安装sl 3. 安装完成后输入: sl

高效流式大语言模型(StreamingLLM)——基于“注意力汇聚点”的突破性研究

论文地址:https://arxiv.org/pdf/2309.17453 github地址:https://github.com/mit-han-lab/streaming-llm 1. 研究背景与挑战 随着大语言模型(LLMs)在对话系统、文档摘要、代码补全和问答等领域的广泛应用,如何高效且准…

STM32-时钟树

STM32-时钟树 时钟 时钟

日志收集Day007

1.配置ES集群TLS认证: (1)elk101节点生成证书文件 cd /usr/share/elasticsearch ./bin/elasticsearch-certutil cert -out config/elastic-certificates.p12 -pass "" --days 3650 (2)elk101节点为证书文件修改属主和属组 chown elasticsearch:elasticsearch con…

使用Python和Qt6创建GUI应用程序---GUI的一个非常简短的历史

GUI的一个非常简短的历史 图形用户界面有着悠久而可敬的历史,可以追溯到20世纪60年代。斯坦福大学的NLS(在线系统)引入了鼠标和Windows概念于1968年首次公开展示。接下来是施乐PARC的Smalltalk系统GUI 1973,这是最现代的基础通用g…

如何建设一个企业级的数据湖

建设一个企业级的数据湖是一项复杂且系统化的工程,需要从需求分析、技术选型、架构设计到实施运维等多个方面进行综合规划和实施。以下是基于我搜索到的资料,详细阐述如何建设企业级数据湖的步骤和关键要点: 一、需求分析与规划 明确业务需…

xxl-job分布式定时任务

1 前言 1.1 业务场景 业务数据同步 ( 线上数据同步到线下,新平台老平台数据的同步 ) ,消息通知,业务数据的补偿。 1.2 什么是定时任务 定时任务是指基于给定的时间点,给定的时间间隔或者给定执行次数自动的执行程序。 任务调度…

FLTK - FLTK1.4.1 - demo - adjuster.exe

文章目录 FLTK - FLTK1.4.1 - demo - adjuster.exe概述笔记根据代码,用fluid重建一个adjuster.fl 备注 - fluid生成的代码作为参考代码好了修改后可用的代码END FLTK - FLTK1.4.1 - demo - adjuster.exe 概述 想过一遍 FLTK1.4.1的demo和测试工程,工程…

Cursor的简单使用

目录 一、下载与配置 1.1、下载 1.2、汉化 1.3、模型选择 1.4、规则设置 二、Chat(聊天)和Composer(编写助手) 三、快捷键 3.1、tab(代码自动补全) 3.2、CtrlL、CtrlI 3.3、系列 3.4、预防、检测、回滚 四、无限登录 …

剥离情绪的内耗

情绪的内耗,指的是我们内心对于某些情绪的过度反应、反复纠结,或者对情感的压抑所产生的心理消耗。这种内耗通常会让我们感到疲惫、焦虑、无力,甚至影响到我们的行为和决策。要真正剥离情绪的内耗,核心在于如何认识、接受并合理处…

android的gradle

资料: GitHub - ChenSWD/CopyGradleInAction: 备份《Gradle IN Action》书中的源码,添加了部分注释 //github上一个开源项目,外加pdf书 Gradle User Manual gradle官网 讲的挺好的博客 Gradle之重新认识Gradle(项目结构、命令行、tas…

Python 之 Excel 表格常用操作

示例文件 test.xlsx 将各个表单拆分成单独的 Excel 文件 import os.pathimport openpyxl import pandasdef handle_excel(file_path):dirname os.path.dirname(file_path)basename os.path.basename(file_path).split(".")[0]wb openpyxl.load_workbook(file_pat…

【C语言系列】深入理解指针(4)

深入理解指针(4) 一、回调函数是什么?二、qsort使用举例2.1使用qsort函数排序整型数据2.2使用qsort排序结构数据 三、qsort函数的模拟实现四、总结 一、回调函数是什么? 回调函数就是一个通过函数指针调用的函数。 如果你把函数的…

计算机网络 (56)交互式音频/视频

一、定义与特点 定义:交互式音频/视频是指用户使用互联网和其他人进行实时交互式通信的技术,包括语音、视频图像等多媒体实时通信。 特点: 实时性:音频和视频数据是实时传输和播放的,用户之间可以进行即时的交流。交互…

FFmpeg 头文件完美翻译之 libavcodec 模块

前言 众所周知,FFmpeg 的代码开发上手难度较高,源于官方提供的文档很少有包含代码教程相关的。要想熟练掌握 FFmpeg 的代码库开发,需要借助它的头文件,FFmpeg 把很多代码库教程都写在头文件里面。因此,熟读头文件的内…