Linux —— 进程控制

一、进程创建 —— fork

1.fork

fork:在调用时,创建子进程,父进程返回子进程pid,子进程返回0,出错返回-1

头文件:#include<unistd.h>

2.fork函数被调用时,CPU做了什么?

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

b.将父进程的部分数据和内容拷贝给子进程

c.添加子进程到系统进程列表中

d.fork返回,开始调度器调度

3.写时拷贝

父进程和子进程在不需要对数据进行操作时,它们的页表指向同一块区域,共享同一份代码和数据信息,只有当某一个进程中需要对这些信息进行修改操作时,系统才会去对这部分进行拷贝,额外分配空间去给该进程进行管理和操作,这就是写时拷贝

4.fork的常规用法

(1)希望子进程执行父进程的部分代码

(2)执行不同的程序

5.调用失败的原因

(1)系统中进程过多

(2)实际用户的进程次数超过了限制

二、进程终止

1.情况分类

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

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

(3)代码异常终止(崩溃了)

崩溃本质:进程因为某些原因,导致进程收到了来着操作系统的终止信号

2.退出方式

(1)main函数的返回return

(2)调用c库函数exit

(3)调用系统接口_exit

区别:exit在终止进程前,会干一系列的善后工作,例如刷新缓存区等等,最后再调用接口_exit,而_exit则是直接终止进程,因此通常推荐使用exit

3.退出码

退出码反映的是进程执行结束的一个结果,例如return 0中的0表示的就是程序正常执行结束的意思

exit函数中传的参数也是程序终止返回的退出码,退出码有相对应的一张表格,0表示程序正常退出,结果正确,其他数字则表示进程有问题,不同数字代表的内容不同

4.如何理解进程终止?

OS内少了一个进程,OS就要释放进程内对应的数据结构 + 代码和数据(如果有独立的)

三、进程等待

1.为什么要进程等待

(1)因为存在僵尸进程,所以为了避免内存泄露

(2)获取子进程执行结果

2.什么是?

等待就是通过系统调用,获取子进程的退出码或者退出信号的方式,顺便释放内存

3.如何做到?—— waitpid

pid_t waitpid(pid_t pid,int* status,int options);

作用

这个函数的作用就是等待子进程死亡,然后回收子进程,返回大于0的值表示成功,返回-1则表示失败

如果子进程已经退出,调用wait/waitpid时,wait/waitpid会立即返回,并且释放资源,获得子进程退 出信息。 如果在任意时刻调用wait/waitpid,子进程存在且正常运行,则进程可能阻塞。 如果不存在该子进程,则立即出错返回。

参数说明

第一个参数,pid:可以指定子进程的pid,当参数给-1时,则认为等待任一个子进程

第二个参数int* status:输出型参数,会返回子进程的状态值,该状态值包含着子进程结束后的退出码和信号,采用位图的方式返回,有效位置是后面16位

当进程正常终止时,8到15位表示的是退出状态(退出码),当进程被信号干掉(异常终止),则在0到7位记录着终止信号的信息


WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出) WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)

第三个参数options:在子进程执行时,父进程使用waitpid等待子进程结束,有两种等待方式,一种是阻塞等待,即父进程的内容停在waitpid那一行不再继续执行,直到回收子进程后,再继续执行,此时父进程被放到阻塞队列中,当子进程结束时,再找到父进程改变其状态,让其继续运行,而默认情况下,就是这种方式等待,还有一种等待方式是非阻塞轮询,即一边执行父进程的内容,一边对子进程进行时不时的状态检测,当子进程结束后进行回收,此时我们给第三个参数传参WNOHANG,就是非阻塞轮询等待

4.代码测试

阻塞等待

非阻塞轮询

四、进程替换

1.替换原理

前面说到,创建子进程的其中一个作用就是让子进程去执行其他的程序,而子进程和父进程共享同一份代码,如何能够做到让子进程单独的去执行其他的程序呢?

这里的进程替换就是,利用系统接口,让子进程去调用其他程序,此时会发生写时拷贝去确保进程之间的独立性,代码区会被替换,因此从这里可以看出来,写时拷贝替换的不只有数据,还有代码也可能被替换

在进程的角度,是子进程发生写时拷贝,并且替换了一部分代码,而在程序的角度看,就是程序被加载到了这个子进程里,因此这个过程也就是程序加载

当子进程使用进程替换后,会写时拷贝出独立的空间,此时,以接口为开始的后续所有代码都会被替换成被加载的程序,而不会继续执行,除非替换失败,因此在对程序替换函数的返回值是只有失败才返回,一旦检测到有返回值,则必定失败

2.加载器exec...

#include <unistd.h>

int execl(const char *path, const char *arg, ...);

int execlp(const char *file, const char *arg, ...);

int execle(const char *path, const char *arg, ...,char *const envp[ ]);

int execv(const char *path, char *const argv[ ]);

int execvp(const char *file, char *const argv[ ]);

int execvpe(const char* file,char* const argv[ ],char* const envp[ ]);

int execve(const char* filename,char* const argv[ ],char* const envp[ ]);

以上的接口都是用来实现程序替换的函数,最后一个标红的是真正的系统接口,其余六个都是根据不同情况对该接口的封装,实际的功能都是一样的,并且通过函数名的不同,使用的方式略微有些差异:

前缀都是exec,一般最多有三个参数

第一个参数位置一般是填写程序或者指令的名称或路径

第二个参数一般就是表示在使用这个程序或者指令时,要怎么使用,例如命令行参数等等

例:ls -a -l  ,需要将如何使用这个信息通过字符串数组或者列表的方式传参,注意要以NULL结尾

第三个参数就是指定传环境配置,若是不传参则会使用系统默认的环境配置

按照命名顺序来解释:

l和v :表示第二个参数传参的方式

l 可以看作为 list 列表,以列表的方式,直接在传参时,将一个个使用方式传过去

例如:想调用“ls -a -l”时,execl("/bin/ls","ls","-a","-l",NULL);

v 可以认为是vector 数组,以数组的方式传参,在c语言中,可以定义一个字符串数组(字符指针数组)去传参

例:char* arr[ ] = { "ls" , "-a" , "-l" , NULL};        execv("/bin/ls",arr);

p : 表示path,表示函数会自动搜索环境变量中配置好的路径

此时,传参的第一个参数中可以不带路径而是直接带指令名称即可,当然自己写的程序默认路径下找不到,也无法执行

因此有没有带p在使用者的角度区分,就是传路径还是传名称

例如:想调用“ls -a -l”时

execl("/bin/ls","ls","-a","-l",NULL);     

execlp("ls" , "ls","-a" ,"-l" , NULL);//注意前后两个"ls"的意义不同,尽可能不要省略

(前者表示第一个参数中的指令名称,后面一串中,表示的是该指令的使用方法)

e :表示允许自己传入自己配置的环境变量,不传则给一个NULL,系统会使用从父进程那继承的默认环境变量

因此,我们可以从这里理解,子进程是如何继承到父进程的环境变量,在系统可以用这个接口去调用子进程,将环境变量继承下去

从命名上去记忆这些函数以及使用方法,在了解上面的命名规则后,可以采用一些技巧去记忆

首先exec是同用的前缀,exe表示可执行程序的后缀,c表示该函数用c语言实现的

然后就是考虑在调用一个指令时的方法,采用列表传参还是数组传参,这个决定了下一个字母带l还是v

然后就是要如何找到这个指令(程序),希望是默认路径去找就带p,指定路径则不需要带

最后是环境变量,需要自己传环境配置则最后加e,若是不需要则不加e

总结

综上,我们整理了关于一个进程的创建,核心要掌握fork的理解和使用

还有进程的终止,终止的情况有正常和非正常,以及正常终止后的退出码信息如何获取等等

然后就是关于进程等待的理解,当子进程结束后,需要被父进程回收,父进程等待子进程结束的过程就是进程等待,分为阻塞等待和非阻塞轮询,以及相关的接口waitpid的理解和使用

最后讲到进程替换,也叫程序加载,理解程序是如何被加载到进程中的,以及对应的接口exec...的使用

根据对进程和这些接口的理解,我们可以尝试去写一个简易版的命令行解释器,下一篇将整理如何自己实现一个简易版的Linux命令行解释器

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

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

相关文章

使用SpringBoot3+Vue3开发公寓管理系统

项目介绍 公寓管理系统可以帮助公寓管理员更方便的进行管理房屋。功能包括系统管理、房间管理、租户管理、收租管理、房间家具管理、家具管理、维修管理、维修师傅管理、退房管理。 功能介绍 系统管理 用户管理 对系统管理员进行管理&#xff0c;新增管理员&#xff0c;修改…

【Leetcode】2923. 找到冠军 I

文章目录 题目思路代码复杂度分析时间复杂度空间复杂度 结果总结 题目 题目链接&#x1f517; 一场比赛中共有 n n n 支队伍&#xff0c;按从 0 0 0 到 n − 1 n - 1 n−1 编号。 给你一个下标从 0 0 0 开始、大小为 n ∗ n n * n n∗n 的二维布尔矩阵 g r i d grid gr…

【从零开始手搓12306项目】十九、增加网关模块

在train项目中增加一个maven模块gateway 在pom中增加网关依赖 gateway只有一个依赖&#xff0c;不能引入common&#xff0c;也不能引入starter-web gateway是基于netty的 在main下新建包com.jia.train.gateway.config 新建启动类GatewayApplication&#xff0c;添加并修改类…

window轻松使用k8s

Docker Desktop安装篇 1、win安装 1、下载安装包 https://www.docker.com/products/docker-desktop/ 官网下载安装包 2、配置win支持虚拟化 不勾选Hyper-V&#xff0c;它和Windows Subsystem for Linux (WSL) 是两套功能&#xff0c;这里不选他 3、安装WSL配置window支持lin…

Python可视化-matplotlib用法详解(一)

一、折线图绘制 import pandas as pds./../../data//unrate.csv unrate pd.read_csv(s) # 时间格式转换&#xff0c; unrate[DATE] pd.to_datetime(unrate[DATE]) print(unrate.head(12))DATE VALUE 0 1948-01-01 3.4 1 1948-02-01 3.8 2 1948-03-01 4.0 3 19…

企业数字化转型路径有哪些?

企业数字化转型是一个复杂而全面的过程&#xff0c;涉及到企业的多个方面&#xff0c;包括管理、运营、生产、销售等。企业数字化转型的路径可以概括为以下几个方面&#xff1a; 1、开展数字化评估 企业首先需要对自身的数字化基础水平、经营管理现状以及内外部转型资源进行全…

【C语言】每日一题,快速提升(2)!

&#x1f525;博客主页&#x1f525;&#xff1a;【 坊钰_CSDN博客 】 欢迎各位点赞&#x1f44d;评论✍收藏⭐ 题目&#xff1a;杨氏矩阵 有一个数字矩阵&#xff0c;矩阵的每行从左到右是递增的&#xff0c;矩阵从上到下是递增的&#xff0c;请编写程序在这样的矩阵中查找某个…

性能测试 Jmeter 非 GUI 模式 -CLI 命令详解

我们在使用Jmeter做性能测试的时候&#xff0c;大部分同学用的是图形化界面进行脚本编写和执行性能测试的。但是其实真正在公司执行性能测试的时候&#xff0c;我们基本上不会用图形化界面去执行测试&#xff0c;这是因为工具渲染这些图形本身会让Jmeter结果存在很多不稳定的因…

什么样的开放式耳机好用?五大红榜超值机型力荐!

今年&#xff0c;市场上涌现出众多备受瞩目的开放式耳机产品&#xff0c;面对如此众多的选择&#xff0c;如何挑选出一款性能卓越、音质出色的开放式耳机&#xff0c;无疑成为了消费者们关注的焦点。传统的入耳式耳机虽然有其优势&#xff0c;但长时间佩戴往往会导致耳朵红肿胀…

STM32的GPIO端口的八种模式解析

目录 STM32的GPIO端口的八种模式解析 一、上拉输入模式 二、下拉输入模式 三、浮空输入模式 四、模拟输入模式 五、推挽输出模式 六、开漏输出模式 七、复用推挽输出模式 八、复用开漏输出模式 STM32的GPIO端口的八种模式解析 在学习STM32的过程中&#xff0c;GPIO端口…

LeetCode——965. 单值二叉树

题目- 力扣&#xff08;LeetCode&#xff09; 如果二叉树每个节点都具有相同的值&#xff0c;那么该二叉树就是单值二叉树。 只有给定的树是单值二叉树时&#xff0c;才返回 true&#xff1b;否则返回 false。 示例 1&#xff1a; 输入&#xff1a;[1,1,1,1,1,null,1] 输出&a…

YOLO-World: Real-Time Open-Vocabulary Object Detection 简介+安装+运行+训练(持续更新)

前言 YOLO_WORLD太牛了&#xff01;&#xff01;众所周知&#xff0c;传统是视觉目标检测一旦训练好后&#xff0c;如果我们需要增加新的识别目标的话&#xff0c;必须得重新训练模型。在生产中如果经常要新增检测目标&#xff0c;对时效性影响很大&#xff0c;而且随着数据量…