详解 Linux 系统下的进程(下)

news2024/9/22 19:48:31

目录

一.进程控制

1.进程创建

a.Linux 系统中,如何创建一个进程?

b.进程创建成功后,Linux 底层会为其做些什么?

2.进程终止

a.什么是进程终止?

b.进程终止的方法有哪些?

c.exit 与 _exit的区别

3.进程等待

a.什么进程等待? 

b.为什么要进程等待?

c.如何进行进程等待?

① wait

② waitpid 

二.进程替换

1.单进程版的程序替换

execl

2.理解和掌握程序替的原理

a.单进程的程序替换原理

b.多进程程序替换原理

3.了解程序替换的各函数接口

a. execlp

b. execle

c. execv

d. execvp

4.xshell 父子进程架构和进程替换机制

三.命令行参数和环境变量

1.环境变量

a.环境变量简介

b.常见的环境变量

c.环境变量的全局属性——子进程可继承

d.查看环境变量的方式

e.有关环境变量的指令

2.命令行参数


一.进程控制

1.进程创建

a.Linux 系统中,如何创建一个进程?

① 运行一个可执行程序,就相当于创建了一个新的进程,如:

② 执行 xshell 中的指令(内建命令除外),就相当于在 bash 进程中创建子进程,所以,我们在 xshell 命令行中输入的指令,都相当于创建了一个新的进程,如:

③ fork() 函数创建子进程,该过程会在下文详细讲解。

b.进程创建成功后,Linux 底层会为其做些什么?

Linux 需要对创建出来的进程进行管理,如何管理?先描述,在组织!

即,Linux 会先创建出一个 task_struct 结构体,该结构体内存有相关进程的属性信息,如:进程pid、进程优先级、进程地址空间的入口地址...等。而后将该 task_struct 结构体放入指定的数据结构中,如:运行队列、等待队列...等,等待Linux系统对其进行下一步操作。

与此同时,系统会为进程创建许多额外的资源,如:进程地址空间、用户级页表、文件描述符表...等。

2.进程终止

a.什么是进程终止?

简单来说,就是让进程的状态变成死亡状态,让父进程读取它的状态码和退出信息,而后将进程所占用的资源释放掉,这就是进程终止。

b.进程终止的方法有哪些?

① main() 函数中的 return 0 操作,0 是错误码,表示进程正常结束.

② 任何函数中的 _exit(0) 操作,表示终止整个进程,不再继续执行后续代码!

③ 任何函数中的 exit(0) 操作,表示终止整个进程,不再继续执行后续代码!

④ 在命令行中,用 Ctrl + c,相当于向前台进程发送二号信号,来杀死前台进程。

⑤ 在命令行中,用 kill -9 + pid,相当于向指定进程发送九号信号,来杀死前台进程。

c.exit 与 _exit的区别

1.exit 是库函数,_exit 是系统调用接口。

2.exit 终止进程的时候,会自动刷新缓冲区;_exit 终止进程的时候,不会自动刷新缓冲区。

小知识:exit() 函数在系统调用层面,封装的是 _exit(),而_exit() 执行的是 Linux 内核级别的操作,所以,exit() 终止进程时,所自动刷新的“缓冲区”,绝对不再 Linux 内核中。

至于该缓冲区是啥、又在哪里?博主会在后续的文章中陆续讲到~~

3.进程等待

a.什么进程等待? 

--- 通过 wait/waitpid 的方式,让父进程对子进程进行资源回收的等待过程,称为进程等待。

b.为什么要进程等待?

① 可以解决子进程僵尸状态带来的内存泄漏问题;

② 通过进程等待的方式,获取子进程的退出信息

c.如何进行进程等待?

① wait

pid_t  wait(int* status) 

父进程调用 wait() 函数,如果子进程还没有退出,父进程就需要在wait上进行阻塞等待,直到子进程变成僵尸状态,wait自动回收,然后返回!

参数详解,int* stauts:父进程需要通过两个信号即终止信号和退出信号得知子进程的运行状态和退出信息,而status负责得到这两个信号。

status 是一个输出型参数,它是如何获取异常信号和退出信号的?

status是一个int类型的整数,32bit,只考虑该int整数的低16位。当一个进程异常了(收到信号),表示该进程执行过程出错,它的退出信息就不重要了。

如何判断有没有收到异常信号?  --- 异常信号是否为0,若为0,则无异常;为非0,则抛异常。

获取异常信号(低16位中的低7位):status & 0x7F

获取退出信号(低16位中的高8位): (status >> 8 ) & 0xFF

core dump(核心转储):当进程因为接收到带有core dump属性的信号而终止时,操作系统会将进程在内存中的状态(包括寄存器值、内存内容等)保存到磁盘上的一个文件中,这个文件通常命名为core.PID,其中PID是进程的进程ID。Core dump文件对于后续的调试工作非常有用,因为它提供了进程崩溃时的详细内存映像。

返回值: 若pid_t > 0 则返回等待进程的pid;若pid_t < 0 则返回失败。

② waitpid 

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

第一个参数 pid_t pid :可以指定进程的pid去等待,亦可将pid设为-1,即等待任意进程。

第二个参数 int* status  :输出型参数,即传进去的值不重要,传出来的值重要!

第三个参数:int options:为0,表示父进程等待的时候,以阻塞状态等待;为 WNOHANG,表示父进程等待的时候,以非阻塞状态等待。

若阻塞等待,父进程在哪里等子进程?--- 父进程在子进程的等待队列里排队.

阻塞状态 --- 阻塞式调用 --- wait/waited --- 子进程不退出,wait不返回 --- 等待的过程中,父进程啥也做不了!!

非阻塞状态 --- wait/waited不阻塞,而是立即返回 --- 轮询 + 非阻塞方案 --- 可以顺便做一些占据时间并不多的事情

返回值: 若pid_t > 0 则返回等待进程的pid   若pid_t < 0 则返回失败

二.进程替换

我们所创建的所有子进程执行的代码,都是父进程的一部分,那么,如果我们想让子进程执行新的程序(代码和数据不再与父进程有任何关联)呢?? 

1.单进程版的程序替换

Linux 命令行指令也是一个个进程(内建命令除外),所以我们在代码中,用特殊的函数去调用执行 xshell 命令中的命令(进程),这一过程,本质就是程序替换.

execl

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

第一个参数 path:表示我们要替换的目标程序的路径.

第二个参数 const char* arg:表示目标程序的执行方法.

注意:最终必须以NULL结尾,表示参数传递完毕!!

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

当代码执行到该函数时,本进程的所有数据和代码全都会被替换成目标进程的代码和数据,即使目标进程的代码执行完毕,原先进程的后续代码也将不再执行。

程序替换的函数的调用,调用失败有返回值,调用成功没有返回值!!

示例:

2.理解和掌握程序替的原理

a.单进程的程序替换原理

当原程序代码执行到excel函数接口时,OS会直接将磁盘中目标程序的代码和数据会覆盖原进程映射到物理内存上的代码和数据,并让CPU从“新加载到内存的代码的main函数”开始执行,这期间并不会创建新的PCB和程序地址空间等资源,exec系列的函数调用接口起到的仅仅是“加载器”的作用!

b.多进程程序替换原理

由于父子进程在物理内存上共享代码和数据,所以在磁盘上目标程序的代码和数据覆盖原进程(调用excel函数的父或子进程)在物理内存上的代码和数据前,OS 会发生写时拷贝,即在物理内存上重新拷贝一份代码和数据区,用存放于目标程序的代码和数据。

程序替换并不会创建新的进程,而是让目标进程占用原进程的资源,在原进程资源的基础上运行!

与父子进程间写时拷贝的区别

父子进程间的写时拷贝仅仅拷贝数据区,不会拷贝代码区,父子进程共用代码。而多进程的程序替换既拷贝数据区,也拷贝代码区,以免目标程序的代码将代码区覆盖,影响到第三进程的运行。

子进程怎么知道,新的程序的代码的起始位置在哪?

Linux系统形成的可执行程序是有格式的,是ELF格式,ELF格式中有表头,其中存放进程程序地址空间上各区的入口地址,其中就包括代码段的入口地址(Entry)。

为啥无论是单进程还是多进程 execl() 函数后面的代码都不跑了?

当eip寄存器走到 execl() 函数时,原进程映射到物理内存上的代码和数据都会被目标进程的代码和数据覆盖,并且使eip从目标进程的entry(可执行程序代码段的入口地址)开始执行目标进程的代码,而原进程execl()函数后的代码也就不复存在了。

3.了解程序替换的各函数接口

函数名中带'l'(list)这个字母的,都意味着:该函数的参数是可变参数.

函数名中带'p'(PATH)这个字母的,都意味着:OS会去环境变量向量表中寻找目标程序,所以我们不用再手写程序的路径,直接告诉OS目标程序的程序名即可.

函数名中带'v'(vector)这个字母的,都意味着:参数要以“数组”的形式传递.

a. execlp

① execlp(const char* filename, const char* arg, . . . );

filename:是要执行的程序的程序名.

arg:对目标程序的操作方法.

如:execlp( "ls", "ls","-a","-l", NULL);

b. execle

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

path:是要执行的程序的路径.

envp[ ] 是一个指向以null结尾的字符串数组的指针,是给新进程传递的环境变量表!

如:char* const envp[ ]={ "PATH=/bin:/usr/bin", "TZ=UTC", NULL };

execle("/usr/bin/ls", "ls","-a","-l", NULL, envp);

c. execv

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

argv 就是将对目标程序的操作,放在一个数组中.

如:char* const argv[ ]={ "ls", "-a", "-l", NULL };  

execv( "/usr/bin/ls", argv );

d. execvp

execvp(const char* filename, char* const argv[ ]); 

filename:要执行的程序文件的名称。

注意这里只需要文件名,不需要完整路径,因为 execvp会在环境变量指定的目录中查找该程序.

argv:就是将对目标程序的操作,放在一个数组中.

如:char* const argv[ ]={ "ls", "-a", "-l", NULL };  

execv( "ls", argv );

程序替换成功后,eip指针指向“目标进程的main函数”使CPU从头开始执行目标进程,而目标进程的main函数中的“命令行参数”是由exec系列函数接口在“加载”目标进程时,传递的参数!!

用excel调用另一个手写的可执行程序

4.xshell 父子进程架构和进程替换机制

当我们启动 xshell 并连接到远端服务器后,我们可以在 xshell 的命令行输入相关指令,此时,我们所在的进程是 bash 进程.

我们输入的命令会由 xshell 发送到远端服务器,在bash进程下进行解析和执行,如果我们执行的命令不是内建命令,bash 进程就会调用 fork() 创建子进程,并在子进程中调用 exec*系列的进程替换接口,由子进程执行完相关代码,并将执行结果交给 bash,而后由 bash 将最终结果交付给我们。

1.什么命令行?? ---一个进程打印出来的一串字符串,包括用户名、主机名、当前路径等信息

2.bash内的命令执行的底层原理??---fork出来的子进程 + exec系列函数 + wait等待

3.环境变量是如给传递给子进程或“替换进程”的??--- 通过exec系列函数传参、地址空间的继承(父子进程)

4.什么是内建命令??---本质是shell内部的一个函数,执行内建命令就是调用shell内部的一个函数

Linux 的命令分类:

① 常规命令,bash fork()创建子进程,让子进程去执行

② 内建命令,bash自己执行,类似于bash调用自己的某个函数去执行

三.命令行参数和环境变量

1.环境变量

a.环境变量简介

定义:环境变量一般是指在操作系统中用来指定操作系统运行环境的一些参数。

如:我们在编写C/C++代码的时候,在链接时,从来不知道我们所链接的动静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是由相关环境变量帮助编译器进程查找

环境变量通常具有某些特殊用途,还在系统中通常具有全局属性。

为什么系统自带的指令不需要路径,而我们写的可执行程序运行时需要./ ?

原因:echo #PATH 系统的指令都被添加到了PATH这一环境变量(Linux系统默认的指令搜索路径)中,执行时会自行找到,而我们写的可执行程序的路径并未写到PATH中,所以需要手动输入路径。

b.常见的环境变量

HOME:指定了当前用户的主目录路径

HISTSIZE=1000:表示历史指令最大保存数是1000

SSH_TTY=/dev/pts/25:表示设备终端文件,也就是打印显示器

PATH:可执行程序,也就是指令的搜索路径

LD_LIBRARY_PATH:指定了系统在哪些目录中查找共享库文件,用于链接动态库

修改指定的环境变量,如,修改PATH的方法:PATH=$PATH:/home/lesson15

同理,用覆盖的方法可以删除环境变量。

默认更改环境变量,只限于本次登录,重新登录,环境变量被自动恢复。

c.环境变量的全局属性——子进程可继承

通过命令行参数,打印出所有的环境变量:

int main(int argc, char* argv[ ], char* env[ ])

        for(int i=0; env[i] ; i++)

                printf("env[%d]->%s\n", i , env[i]);

本地变量 VS 环境变量:本地变量只在bash进程内部有效,不会被子进程继承下去;环境变量通过让所有的子进程继承的方式,实现自身的全局性!

d.查看环境变量的方式

① env (查看所有的环境变量)

② getenv("USER") (通过环境变量名获取某个环境变量的内容)

③ main(int argc,char* argv[],char* env[])传参

④ extern char** environ

e.有关环境变量的指令

① export NAME=123456   (导出本地变量,使其变为一个新的环境变量)

② env | grep NAME   (查看某个环境变量)

③ unset NAME  (清除某个环境变量或本地变量)

④ set   (查看所有本地变量和环境变量)

2.命令行参数

什么是命令行参数?

--- 在命令行中输入的数据,能被main()函数以形参的方式捕捉到,这就是命令行参数。

命令行启动的进程都是shell/bash的子进程,子进程的命令行参数和环境变量都是父进程bash给我们传递的!

那么父进程的环境变量信息又是从哪里来??

我们直接更改的是bash进程内部的环境变量信息,每一次重新登录,都会给我们形成新的bash解释器,并且新的bash解释器自动从?读取形成自己的环境变量信息!

每一次登录的时候,我们的bash进程都会读取 .bash_profile 配置文件中的内容,为我们bash进程形成一张环境变量表信息!

自定义一个环境变量,让我们在每次登录xshell的时候,它都会存在

vim ~/.bash_profile  (打开配置文件) ——> 定义一个环境变量PATH  并将该环境变量导出

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

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

相关文章

通过logstash同步elasticsearch数据

1 概述 logstash是一个对数据进行抽取、转换、输出的工具&#xff0c;能对接多种数据源和目标数据。本文介绍通过它来同步elasticsearch的数据。 2 环境 实验仅仅需要一台logstash机器和两台elasticsearch机器&#xff08;elasticsearch v7.1.0&#xff09;。本文用docker来模…

NLP 序列标注任务核心梳理

句向量标注 用 bert 生成句向量用 lstm 或 bert 承接 bert 的输出&#xff0c;保证模型可以学习到内容的连续性。此时 lstm 输入形状为&#xff1a; pooled_output.unsqueeze(0) (1, num_sentence, vector_size) 应用场景 词性标注句法分析 文本加标点 相当于粗粒度的分词任…

实时同步 解决存储问题 sersync

目录 1.sersync服务 2.sersync同步整体架构 ​编辑 3.rsync服务准备 4.sersync部署使用 5.修改配置文件 6.启动sersync 7.接入nfs服务 8.联调测试 1.sersync服务 sersync服务其实就是由两个服务组成一个是inotify服务和rsync服务组成 inotify服务用来监控那个…

Linux 文件系统(上)

目录 一.预备阶段 1.认识文件 2.OS对内存文件的管理 3.C库函数和系统调用接口 a.C库函数——fopen b.系统调用接口——open 二.理解文件描述符 1.一张图&#xff0c;详解文件描述符的由来 2.fd的分配规则 3.从fd的角度理解FILE 三.重定向和缓冲区 1.前置知识——理解…

网络安全-CSRF

一、环境 DVWA网上找 二、简单介绍 这个漏洞很早之前了&#xff0c;但是为了避免大家在面试等等的时候被问到&#xff0c;这里给大家温习一下 CSRF全程是没有黑客参与的&#xff0c;全程都是用户自己在操作 三、环境演练 这个是DVWA的提交表单页面&#xff0c;我这里伪造…

【2020工业图像异常检测文献】PaDiM

PaDiM: a Patch Distribution Modeling Framework for Anomaly Detection and Localization 1、Background 在单类学习&#xff08;仅使用正常数据&#xff08;即“单一类”&#xff09;来训练模型&#xff09;环境中的异常检测和定位任务方法中&#xff0c;要么需要深度神经网…

结合HashMap与Java 8的Function和Optional消除ifelse判断

shigen坚持更新文章的博客写手&#xff0c;记录成长&#xff0c;分享认知&#xff0c;留住感动。个人IP&#xff1a;shigen 在文章的开头我们先从这些场景进入本期的问题&#xff1a; 业务代码中各种if-else有遇到过吗&#xff0c;有什么好的优化方式&#xff1b;java8出来这么…

鸿蒙开发(NEXT/API 12)【跨设备互通特性简介】协同服务

跨设备互通提供跨设备的相机、扫描、图库访问能力&#xff0c;平板或2in1设备可以调用手机的相机、扫描、图库等功能。 说明 本章节以拍照为例展开介绍&#xff0c;扫描、图库功能的使用与拍照类似。 用户在平板或2in1设备上使用富文本类编辑应用&#xff08;如&#xff1a;…

学习 git 命令行的简单操作, 能够将代码上传到 Gitee 上

首先登录自己的gitee并创建好仓库 将仓库与Linux终端做链接 比如说我这里已经创建好了一个我的Linux学习仓库 点开克隆/下载&#xff1a; 在你的终端中粘贴上图中1中的指令 此时他会让你输入你的用户名和密码&#xff0c;用户名就是上图中3中Username for ....中后面你的一个…

预付费计量系统实体模型

1. 预付费计量系统实体模型 A generic entity model for electricity payment metering systems is shown in Figure 2. Although it provides a limited perspective, it does serve to convey certain essential concepts. 关于电子式预付费电表系统的实体模型见图 2…

李宏毅结构化学习 03

文章目录 一、Sequence Labeling 问题概述二、Hidden Markov Model(HMM)三、Conditional Random Field(CRF)四、Structured Perceptron/SVM五、Towards Deep Learning 一、Sequence Labeling 问题概述 二、Hidden Markov Model(HMM) 上图 training data 中的黑色字为x&#xff…

如何备份SqlServer数据库

第一步&#xff1a;登录你要备份的服务器数据库ssms 第二步&#xff1a;选择你要备份的数据库 此处已PZ-SJCS 数据库为例 右键该数据库-->任务-->备份 第三步&#xff1a;选择你备份的类型备份组件等&#xff0c;目标磁盘 &#xff0c;点击添加选择将你备份的文件备份那…

全面详尽的 PHP 环境搭建教程

目录 目录 PHP 环境搭建概述 在 Windows 上搭建 PHP 环境 使用集成环境 XAMPP 安装步骤 配置和测试 常用配置 手动安装 Apache、PHP 和 MySQL 安装 Apache 安装 PHP 安装 MySQL 配置 PHP 连接 MySQL 在 Linux 上搭建 PHP 环境 使用 LAMP 方案 安装 Apache 安装 …

【25.6】C++智能交友系统

常见错误总结 const-1 如下代码会报错 原因如下&#xff1a; man是一个const修饰的对象&#xff0c;即man不能修改任何内容&#xff0c;但是man所调用的play函数只是一个普通的函数&#xff0c;所以出现了报错。我们需要在play函数中加上const修饰&#xff0c;或者删除man对…

《论分布式存储系统架构设计》写作框架,软考高级系统架构设计师

论文真题 分布式存储系统&#xff08;Distributed Storage System&#xff09;通常将数据分散存储在多台独立的设备上。传统的网络存储系统采用集中的存储服务器存放所有数据&#xff0c;存储服务器成为系统性能的瓶颈&#xff0c;也是可靠性和安全性的焦点&#xff0c;不能满…

FreeRTOS-时间片调度

FreeRTOS-时间片调度 一、时间片调度简介二、时间片调度实验 一、时间片调度简介 同等优先级任务轮流的享有相同的CPU时间(可设置)&#xff0c;叫时间片&#xff0c;在FreeRTOS中&#xff0c;一个时间片就等于SysTick中断周期&#xff0c;所以说时间片大小取决于滴答定时器中断…

windows安装Anaconda教程

一、简介 Anaconda 是一个开源的 Python 和 R 语言的分发平台&#xff0c;专为科学计算和数据分析设计。它包含了包管理器 Conda&#xff0c;可以方便地安装和管理库、环境和依赖项。此外&#xff0c;Anaconda 还附带了许多数据科学工具和库&#xff0c;如 Jupyter Notebook 和…

【HTTPS】中间人攻击和证书的验证

中间人攻击 服务器可以创建出一堆公钥和私钥&#xff0c;黑客也可以按照同样的方式&#xff0c;创建一对公钥和私钥&#xff0c;冒充自己是服务器&#xff08;搅屎棍&#xff09; 黑客自己也能生成一对公钥和私钥。生成公钥和私钥的算法是开放的&#xff0c;服务器能生产&…

iOS17找不到developer mode

iOS17找不到开发者模式 developer mode 下载过app之后、弹窗Developer Mode Required之后&#xff0c;这个菜单就出现了&#xff08;之前死活找不到&#xff09;。 背景&#xff1a;用蒲公英分发测试app&#xff0c;有个同事买了新机(iphone 15 pro max)&#xff0c;添加了白名…

双虚拟机部署php项目

前言 经过前面的学习,我们对分布式部署有了一定的了解,这次我们尝试做些东西 准备 我打算用虚拟机部署一个外联网盘 一台虚拟机安装php另一台安装MySQL,但是之前已经安装过 MariaDB 了,就不打算改了。 通常MariaDB与MySQL兼容性很好,可以作为替代使用。彩虹外链网盘项目…