【Linux】进程控制(创建、终止、等待、替换)

news2024/11/29 19:56:11

文章目录

  • 1. 进程创建
  • 2. 进程终止
  • 3. 进程等待
  • 4. 进程程序替换
    • 4.1 认识进程替换
    • 4.2 认识全部接口

在这里插入图片描述

1. 进程创建

如何创建进程我们已经在之前学习过了,无非就是使用fork(),它有两个返回值。创建成功,给父进程返回PID,给子进程返回0;创建失败,给父进程返回-1。

由于虚拟地址空间的存在,父子两进程各自独立,父子代码共享,父子在不修改时,数据也是共享的;当将fork的返回值进行写入时,便以写时拷贝的方式各自一份副本。具体见下图:
在这里插入图片描述
但是操作系统怎么知道要发生写时拷贝呢?

在调用fork时,父进程会先将页表中的执行权限全部改成只读。那么子进程继承下来的页表项,全部都是只读的。

当通过代码区对某些数据段就行写入时,会被页表识别到,并触发系统错误(缺页中断);只不过触发错误的时候,系统会判断是真的发生了错误,还是要发生写时拷贝!

fork常规用法

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

2. 进程终止

在我们以前写程序的时候,main函数总是会带一个返回值,但这个返回值有什么用处呢?它是给谁看的呢?- - 返回给父进程(bash)或者系统。

在下面的程序中,main函数返回了0

在这里插入图片描述

这个退出码有什么用呢? - - 表明错误的原因,一般用0表示成功,非0表示错误。

C/C++给我们提供了一些错误码,errno,perror,strerror等函数。

在这里插入图片描述

将退出码返回以后,可以供父进程或操作系统获得错误信息,所以这个错误码是给机器看的。

不同的系统,提供的错误码的种类和数量可能不同的;同时你也可以自己定义退出码。

进程终止的方式:

  1. mian函数 return 返回
  2. exit(),会刷新缓冲区,底层调用_exit()
  3. _exit(),不会刷新缓冲区,是一个系统调用接口
  • return vs exit()

在这里插入图片描述

  • exit vs _exit

在这里插入图片描述

3. 进程等待

在进程状态那里讲过,子进程退出,如果父进程不读取它,它会变成僵尸进程。
在这里插入图片描述
为了避免子进程进入僵尸状态,父进程该如何读取子进程,回收它呢?- - -使用wait方法。

在这里插入图片描述

一般而言,父进程创建了子进程,就要对子进程负责,就要等待子进程,直到子进程结束。如果子进程不退出,父进程就要阻塞在wait函数内部。

在这里插入图片描述
除了回收子进程外,父进程还需要知道子进程把任务完成的怎么样呢? - -使用waitpid()

pid_t waitpid(pid_t pid, int *status, int options);
  • waitpid的第一个参数pid

pid > 0:等待指定的子进程
pid == -1:等待任意一个子进程

在这里插入图片描述

那如何获得子进程的退出信息呢?

  • waitpid的第二个参数 status

在这里插入图片描述

子进程的退出码,是通过我们所传递的第二个参数带出来的,理想结果应该就是子进程的退出码1。
但是实际结果为什么是256呢?

在这里插入图片描述

这是因为status中不仅仅包含进程退出码,它还包括一些退出信息。
status不能简单的当作整形来看待,可以当作位图来看待,它有32个比特位,具体细节如下图(只研究status低16个比特位)
在这里插入图片描述

它的次低八位才是退出码

在这里插入图片描述

那低八位上的退出信号是干什么用的呢?

我们知道,进程退出有三次原因

  1. 代码跑完,结果对,return 0
  2. 代码跑完,结果错误,return 非0
  3. 进程异常

对于前两种原因,我们都可以通过退出码来识别错误;
对于第三种原因,进程异常直接会被操作系统使用信号终止,但是退出码是进程正常终止时由进程本身设置的,用于向父进程报告其结束状态或结果。然而,当进程因为接收到一个信号(如段错误、非法指令、用户中断等)而异常终止时,退出码就不再是一个可靠的指示器了。

所以,低七位上的会记录退出信号,第7位有其它作用,信号如下:

在这里插入图片描述
我们发现没有0号信号,因为0号信号标记着进程正常退出。

在这里插入图片描述

所以,当一个进程结束时,如果退出信号为0,则表示正常退出;但结果对不对,我们还需要再通过退出码来判断。

除了使用位运算来获取进程的退出信息,系统还提供了两个宏供我们使用:

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

在这里插入图片描述

  • waitpid的第三个参数option

options = 0 : 阻塞等待
options = WNOHANG:非阻塞等待。需要由你自己循环调用非阻塞接口,完成轮循检测,可以让调用方在轮循检测期间做更多自己的事情。

在这里插入图片描述

当option被设置为WNOHANG时,则函数有三个返回值:

  1. 返回值 > 0 : 非阻塞等待成功,返回子进程的PID
  2. 返回值 < 0 :非阻塞等待失败
  3. 返回值 = 0 :等待的进程尚未退出

所以,当函数的返回值 = 0时,可以让父进程执行一些其它的任务,然后轮循检测子进程是否退出。
在这里插入图片描述

4. 进程程序替换

4.1 认识进程替换

以往我们所创建出来的子进程,都是在执行和父进程相关的程序,那我能不能让子进程去执行一个全新的程序呢?下面展示的接口就是来完成程序替换的·

在这里插入图片描述
见一见进程替换

在这里插入图片描述

运行我们自己的程序发现,它去调用了系统的ls命令。也就是你main函数中没有代码,但是你去调用了人家ls的代码,这就是进程替换。

进程替换不是创建新的进程,仅仅是将代码和数据替换、页表映射修改一下,进程相关的PCB信息根本没有变化。

  • 参数

那这个execl函数的参数都是什么意思呢?
在这里插入图片描述
简而言之,path就是你要执行谁,后面的可变参数列表就是你想怎么执行它。

  • 返回值

这个execl的返回值是干什么用的呢?

在这里插入图片描述
只有调用execl时发生错误,该函数才会后返回-1;成功时没有返回值,因为调用成功后代码全被覆盖了,那它返回什么,所以只要它返回,它必定是失败的。

有了上面的理解后,我们做个简单的总结:

  1. 在进程替换的使用中,一般不会让当前进程去替换,而是创建一个子进程去替换。父进程只需看子进程表演,如果想获得子进程任务的执行情况,通过返回码判断。如果返回了,则替换失败;没有返回,替换成功。
    在这里插入图片描述
  2. 如果我不再将execl的参数写死,而是让用户输入,并且我给这段代码在套一个死循环,这不就是一个简单的命令行解释器吗?
  3. 在linux中,所有的进程都是由父进程创建的,那系统是怎么把我们的程序跑起来的呢?也无非就是先fork,然后进行程序替换。
  4. 所以进程创建时要先有内核数据结构,即:使用fork继承父进程的;然后再execl加载自己的代码和数据,这不就是一个新的程序了吗?
  5. 因此,用户所执行的所有程序,在操作系统看来全部都是进程。无非就是fork以后再执行程序替换

4.2 认识全部接口

进程替换一共有7个接口
在这里插入图片描述

第七个execve是系统调用,前6个都是C帮我们封装的函数,底层是调用的第七个。

  • execv vs execl

二者的区别就是execv将后面的参数,全部放在了一个vector里;execl是放在了一个list中

在这里插入图片描述
此时的vector数组,是不是就像main函数的命令行参数呢? - -就是这样,系统就是通过这个传递给main函数的。

execl函数内部也会将所传递的参数转化为上图所示的数组!

  • execlp vs execvp

在这里插入图片描述
带p(path)意味着:调用时无需指定路径,只需指定调用谁。v和l的区别还是vector与list

在这里插入图片描述

为什么不需要指定路径了呢?因为它会自己去path路径下找。

  • execvpe

在这里插入图片描述

除了告诉系统我要执行谁,怎么执行,我还可以给它传递新的环境变量,此时第三个参数就是环境变量。

当我们不传递时,替换的程序可以获得环境变量吗?- - 可以,通过全局指针变量envrion。
当我们传了,此时就会用我们所传递的,替换环境变量,程序使用全新的环境变量。
在这里插入图片描述

在这里插入图片描述

但是我不想改变整个环境变量表,仅仅想增加环境变量呢?

putenv()谁调用该函数,就将新的环境变量添加到它环境变量表当中!
如子进程添加环境变量,父进程的不变。
在这里插入图片描述

这些函数原型看起来很容易混,但只要掌握了规律就很好记。

  • l(list) : 表示参数采用列表
  • v(vector) : 参数用数组
  • p(path) : 有p自动搜索环境变量PATH
  • e(env) : 表示自己维护环境变量

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

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

相关文章

LLM大模型常见面试题汇总(含答案)

最近秋招正在如火如荼地进行中&#xff0c;看到很多人的简历上都包含大模型相关的工作&#xff0c;各家大厂和初创都很舍得给钱&#xff0c;动辄百万年包也变得不再稀奇。 因此在大模型纵横的这个时代&#xff0c;不仅大模型技术越来越卷&#xff0c;就连大模型相关的岗位和面…

零点校准说明

目录 注意&#xff0c;校准时电机不能带负载&#xff0c;否则校准容易出错。 零点校准 点击【零点校准】&#xff0c;显示“校准中…”, 如果是“High Current”类型电机&#xff0c;电机先“嘀”一声测量电阻电感&#xff08;耗时约5秒&#xff09;&#xff0c;然后再正转一圈…

【实战】Nginx+Lua脚本+Redis 实现自动封禁访问频率过高IP

大家好&#xff0c;我是冰河~~ 自己搭建的网站刚上线&#xff0c;短信接口就被一直攻击&#xff0c;并且攻击者不停变换IP&#xff0c;导致阿里云短信平台上的短信被恶意刷取了几千条&#xff0c;加上最近工作比较忙&#xff0c;就直接在OpenResty上对短信接口做了一些限制&am…

Vivado viterbi decoder license

Viterbi Decoder 打卡以上链接 添加后next后&#xff0c; 会发送lic文件到邮件&#xff0c;vivado导入lic即可

Latex技巧——参考文献中加入url和doi

有的期刊要求在参考文献里加入url或者doi, 例如下图中蓝色的字体。 在bib里编辑为下图中note行&#xff0c;也就是利用\href命令。\href后第一个{}内为网址&#xff0c;第二个{}为在参考文献中显示的蓝色文字。一般来说&#xff0c;两个{}内的文字相同。若遇到有些网址有下划线…

不是哥们,真有人拿 AI 来面试啊?

大家好&#xff0c;我是八哥。如今 AI 已经渗透到了我们的生活、求职、工作等方方面面。就拿求职来说&#xff0c;今年的美团校招&#xff0c;已经用上了 AI 来当面试官&#xff0c;降本增效。 我自己也当过面试官&#xff0c;其实对 AI 面试官还是挺好奇的。毕竟每个候选人的…

UOM无人机空域快速申请技术详解

UOM无人机空域快速申请技术详解主要包括以下几个步骤&#xff1a; 一、准备阶段 1. 实名登记&#xff1a;首先&#xff0c;您需要在相应的民航部门进行无人机的实名登记&#xff0c;这是合法飞行的前提。 2. 了解规定&#xff1a;熟悉并遵守当地关于无人机飞行的法律法规&am…

C语言:预编译过程的剖析

目录 一.预定义符号和#define定义常量 二.#define定义宏 三.宏和函数的对比 四、#和##运算符 五、条件编译 在之前&#xff0c;我们已经介绍了.c文件在运行的过程图解&#xff0c;大的方面要经过两个方面。 一、翻译环境 1.预处理&#xff08;预编译&#xff09; 2.编译 3…

SpringBoot在线教育系统:从零到一的构建过程

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理微服务在线教育系统的相关信息成为必然。开…

如何禁止电脑蓝牙?分享五个有效方法,快@企业老板来看! 内行人都在用的方法哦,不妨一试!

在现代办公环境中&#xff0c;电脑蓝牙功能的便捷性无可否认&#xff0c;但随之而来的安全风险也不容忽视。 尤其对于企业而言&#xff0c;蓝牙的开放可能引发数据泄露、未经授权的设备连接等一系列安全问题。 因此&#xff0c;如何有效地禁止电脑蓝牙&#xff0c;成为了许多…

终于有人把多模态大模型讲这么详细了

多模态大型语言模型&#xff08;Multimodal Large Language Models&#xff0c; MLLM&#xff09;的出现是建立在大型语言模型&#xff08;Large Language Models&#xff0c; LLM&#xff09;和大型视觉模型&#xff08;Large Vision Models&#xff0c; LVM&#xff09;领域不…

付费计量系统通用功能(14)

11.18 Function_Object功能目标 11.18.1 Function_Object definition功能目标定义 A Function_Object is an abstract notation of defining the attributes of a function. 功能目标是一个抽象的功能属性的定义 Definition of a function object should stat…

Linux plt表调用汇编代码分析

linux调用共享库中的函数时通过plt表和got表实现位置无关代码&#xff0c;过程中涉及到lazy binding&#xff0c;即在第一调用外部函数时解析被调用的函数地址并将地址写入到got表&#xff0c;后续调用则不需要解析函数地址&#xff0c;具体过程如下 1.c程序如下 #include &l…

基于Node2Vec的图嵌入实现过程

目录 一、引言二、Node2Vec&#xff08;原理&#xff09;2.1 随机游走&#xff08;Random Walk&#xff09;2.2 嵌入学习2.3 Node2Vec 的优势 三、使用 Node2Vec 进行图嵌入&#xff08;实践&#xff09;3.1 读取和转换 JSON 文件为 Graph 对象3.2 训练 Node2Vec 模型3.3 二维嵌…

Python+Django微信小程序前后端人脸识别登录注册

程序示例精选 PythonDjango微信小程序前后端人脸识别登录注册 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对《PythonDjango微信小程序前后端人脸识别登录注册》编写代码&#xff0c;代码整…

2024年10月6日历史上的今天大事件早读

23年10月06日西汉“新莽政权”领袖王莽被刺身亡 1866年10月06日清政府批准筹设天津机器局 1905年10月06日俄国爆发铁路工人大罢工 1913年10月06日中、英西姆拉会商“西藏问题” 1927年10月06日阿尔-乔尔森主演第一部有声电影 1940年10月06日新四军获黄桥决战胜利 1949年1…

字节跳动员工玩转 AI 的 100 种办法

今年&#xff0c;字节跳动在国内上线了 AI 应用开发平台——扣子。用户可以根据自己的想法在扣子上创建 chat bot&#xff08;聊天机器人&#xff09;&#xff0c;甚至能利用扣子 API 上线一个产品。 扣子上有丰富的插件工具&#xff0c;如果用户希望 bot 具备某个功能&#x…

sql-labs靶场第九关测试报告

目录 一、测试环境 1、系统环境 2、使用工具/软件 二、测试目的 三、操作过程 1、寻找注入点 2、注入数据库 ①寻找注入方法 ②爆库&#xff0c;查看数据库名称 ③爆表&#xff0c;查看security库的所有表 ④爆列&#xff0c;查看users表的所有列 ⑤成功获取用户名…

2024年,现在做全职的AI产品经理,时机对不对?

就在最近&#xff0c;Chatgpt又更新了&#xff0c;推出了新版本名字叫做canvas。 这个版本可以支持对AI的对话内容进行编辑了&#xff0c;也就是以前prompt一次性生成的结果总是很难控制输出结果&#xff0c;新版新增了可以在结果内容与用户进行交互的产品入口&#xff0c;最终…

(20)MATLAB使用卡方(chi-square)分布生成Nakagami-m分布

文章目录 前言一、使用卡方分布函数生成Nakagami分布随机变量二、MATLAB仿真1.仿真代码2.运行结果 前言 Nakagami分布随机变量的生成&#xff0c;可以使用gamma分布实现&#xff0c;也可以使用卡方&#xff08;chi-square&#xff09;分布随机变量生成。使用伽马&#xff08;g…