Linux系统 进程
Linux系统 进程
- 进程
- 私有地址空间
- 用户模式和内核模式
- 上下文切换
- 进程控制
- 系统调用错误处理
- 进程控制函数
- 获取进程 ID
- 创建和终止进程
- 回收子进程
- 让进程休眠
- 加载并运行程序
进程
异常是允许操作系统内核提供进程(process)概念的基本构造块,进程是计算机科学中最深刻、最成功的概念之一。异常控制流与进程有密切的关系,因为它为进程的多任务运行、异常处理和资源管理提供了基础。
进程是操作系统对正在运行的程序的一种抽象。它为每个程序提供了一种假象,仿佛每个程序都在独占地使用处理器、主存和 I/O 设备,而实际上系统中可能同时存在多个进程并发执行,操作系统负责管理和协调这些进程对硬件资源的共享。
私有地址空间
进程的私有地址空间包括
- 代码区:存放程序代码,通常是只读的,以防止程序意外修改自身指令。
- 数据区:包含已初始化的全局和静态变量。
- 堆区:从低地址向高地址增长,用于动态内存分配,如程序运行过程中根据需要创建的数据结构。
- 栈区:从高地址向低地址增长,用于存放函数调用相关信息,如局部变量、函数参数、返回地址等。
这种布局有助于组织和管理进程的数据和指令存储,并且通过地址空间的隔离保证了进程间的独立性和安全性,防止一个进程意外访问或修改另一个进程的数据。
用户模式和内核模式
在用户模式下,进程只能访问自己的虚拟内存空间,无法直接操作硬件或执行特权指令。而在内核模式下,进程具有完全的权限,可以访问整个内存空间并与硬件直接交互,操作系统的核心功能大多在内核模式下执行。
进程从用户模式切换到内核模式通常由系统调用、中断或异常触发。当进程请求操作系统服务时,它会通过系统调用触发模式切换。系统调用通过陷阱指令使得进程从用户模式转入内核模式,操作系统处理完请求后,再返回用户模式继续执行。
上下文切换
进程上下文包含了进程执行所需的所有信息,这些信息完整地描述了进程在某一时刻的执行状态,当进程被暂停或切换时,操作系统需要保存这些上下文信息,以便在下次恢复执行时能够准确地回到之前的执行状态。
- 程序计数器(PC)的值:指示下一条要执行的指令地址。
- 寄存器的值:包括通用寄存器、栈指针、程序状态字寄存器,用于存储进程当前的计算状态和临时数据。
- 页表:用于将虚拟地址转换为物理地址,实现内存管理。
- 内核栈:用于保存进程在内核态执行时的函数调用信息和临时数据。
进程控制
系统调用错误处理
void unix_error(char *msg)
{fprintf(stderr, "%s: %s\n", msg, strerror(errno));exit(0);
}
pit_t Fork()
{pit_t pid;if ((pid = fork()) < 0)unix_error("Fork error");return pid;
}
Unix 系统级函数出错时通常返回 -1 并设置 errno,上面是对系统调用的错误处理封装,下面的部分中都使用错误处理包装函数。它们能够保持代码示例简洁,而又不会给你错误的假象,认为允许忽略错误检査。包装函数定义在一个叫做 csapp.c 的文件中,它们的原型定义在一个叫做 csapp.h 的头文件中;可以从 CS:APP 网站上在线地得到这些代码。
进程控制函数
获取进程 ID
#include <sys/types.h>
#include <unistd.h>pid_t getpid(void);
pid_t getppid(void);
// 返回:调用者或其父进程的 PID。
getpid
和 getppid
函数返回一个类型为 pid_t 的整数值,在 Linux 系统上它在 types.h 中被定义为 int。
创建和终止进程
#include <stdlib.h>void exit(int status);
// 该函数不返回。
exit 函数以 status 退出状态来终止进程(或返回一个整数值)。
#include <sys/types.h>
#include <unistd.h>pid_t fork(void);
// 返回:子进程返回 0,父进程返回子进程的 PID,如果出错,则为 -1。
父进程调用fork
后,操作系统会创建一个新的进程控制块(PCB)和地址空间等资源给子进程,然后将父进程的上下文复制到子进程中。之后,父进程和子进程从fork
函数返回后开始独立执行,虽然它们从相同的代码位置继续执行,但由于返回值不同,可以通过判断返回值来执行不同的代码分支,例如父进程可以在fork
后继续执行其他任务,同时等待子进程完成某些操作,而子进程可以执行特定于子进程的任务,如执行另一个程序等。
// 使用 fork 创建一个新进程
int main()
{pid_t pid;int x = 1;pid = Fork();if (pid == 0) { /* Child */printf("child : x=%d\n", ++x);exit(0);}/* Parent */printf("parent: x=%d\n", --x);exit(0);
}
linux> ./fork
parent:x=0
child :x=2
回收子进程
#include <sys/types.h>
#include <sys/wait.h>pid_t waitpid(pid_t pid, int *statusp, int options);
// 返回:如果成功,则为子进程的 PID,如果 WNOHANG,则为 0,如果其他错误,则为 -1。
pid
:指定要等待的子进程的 PID(进程标识符)。
- 如果
pid > 0
,则等待进程 ID 为pid
的子进程结束。 - 如果
pid == 0
,则等待与当前进程同属一个进程组的任何子进程结束。 - 如果
pid == -1
,则等待任何子进程结束(类似于wait
)。 - 如果
pid < -1
,则等待进程组 ID 为pid
的子进程结束(即进程组内的任何子进程)。
status
:指向整型变量的指针,用于存储子进程的退出状态。如果该参数为 NULL
,则不保存子进程的状态。
options
:控制等待行为的选项,常见的选项有:
WNOHANG
:非阻塞模式,如果没有子进程退出,waitpid
立即返回而不是阻塞。WUNTRACED
:在子进程停止(但没有终止)时也返回,即使它没有结束。WCONTINUED
:如果子进程因信号而暂停,可以在它继续运行时通知父进程。WNOHANG | WUNTRACED
:立即返回,如果等待集合中的子进程都没有被停止或终止,则返回值为 0;如果有一个停止或终止,则返回值为该子进程的 PID。
子进程的退出状态:如果 status
参数不为 NULL
,waitpid
会将子进程的退出状态存储在 status
指向的变量中。退出状态可以通过以下宏来解析:
WIFEXITED(status)
:如果子进程正常退出,返回真。WEXITSTATUS(status)
:返回子进程的退出码。只有在 WIFEXITED() 返回为真时,才会定义这个状态。WIFSIGNALED(status)
:如果子进程因为未捕捉到的信号退出,返回真。WTERMSIG(status)
:返回导致子进程终止的信号号码。WIFSTOPPED(status)
:如果子进程被信号暂停,返回真。WSTOPSIG(status)
:返回导致子进程暂停的信号号码。WIFCONTINUED(status)
:如果子进程因接收到继续信号(如SIGCONT
)而恢复,返回真。
错误条件:如果调用进程没有子进程,那么 waitpid 返回 -1,并且设置 errno 为 ECHILD。如果 waitpid 函数被一个信号中断,那么它返回 -1,并设置 errno 为 EINTR。
wait 函数
#include <sys/types.h>
#include <sys/wait.h>pid_t wait(int *statusp);
// 返回:如果成功,则为子进程的 PID,如果出错,则为 -1。
调用 wait(&status)
等价于调用 waitpid(-1, &status, 0)
。
让进程休眠
#include <unistd.h>unsigned int sleep(unsigned int secs);
// 返回:还要休眠的秒数。int pause(void);
// 总是返回 -1。
sleep
函数将一个进程挂起一段指定的时间。
pause
函数让调用函数休眠,直到该进程收到一个信号。
加载并运行程序
#include <unistd.h>int execve(const char *filename, const char *argv[],const char *envp[]);
// 如果成功,则不返回,如果错误,则返回 -1。
execve
是一个用于启动新程序的系统调用,它是 UNIX 和 Linux 系统中执行程序的重要机制。通过 execve
,当前进程可以加载并执行一个新的程序文件。执行该系统调用后,当前进程的地址空间(包括代码、数据、堆栈等)将被替换为新程序的内容,原进程的代码不再执行。
pathname
:要执行的程序的路径。它是一个以 null 结尾的字符串,指定了要执行的文件的绝对路径或相对路径。argv
:一个指向参数数组的指针,用于传递给新程序的命令行参数。它是一个数组,其中第一个元素通常是程序的名称,接下来的元素是传递给程序的各个参数。数组的最后一个元素必须是NULL
。envp
:一个指向环境变量数组的指针。它是一个包含环境变量的数组,每个环境变量是一个以=
分隔的字符串。数组的最后一个元素必须是NULL
。
int main(int argc, char *argv[], char *envp[]);
argc
是一个整数,表示命令行中传递给程序的参数的数量。它的值至少为 1,因为argv[0]
始终是程序的名称或路径。argv
是一个指向字符串数组的指针,数组中的每个元素是一个指向以 null 字符结尾的字符串的指针。这些字符串对应于命令行中传递给程序的参数。envp
是一个指向环境变量数组的指针。每个环境变量是一个以 null 字符结尾的字符串,它的格式通常是KEY=VALUE
,例如PATH=/usr/bin
。
当 main 开始执行时,用户栈的组织结构下图所示。从栈底(高地址)往栈顶(低地址)依次看。首先是参数和环境字符串。栈往上紧随其后的是以 null 结尾的指针数组,其中每个指针都指向栈中的一个环境变量字符串。全局变量 environ
指向这些指针中的第一个 envp[0]
紧随环境变量数组之后的是以 null 结尾的 argv[]
数组,其中每个元素都指向栈中的一个参数字符串。在栈的顶部是系统启动函数 libc_start_main
的栈帧。
操作环境数组
#include <stdlib.h>char *getenv(const char *name);
// 返回:若存在则为指向 name 的指针,若无匹配的,则为 NULL。
getenv
用于从环境变量中获取指定变量的值。环境变量是操作系统用于存储关于当前进程的配置信息的键值对,比如用户的主目录、系统路径等。
#include <stdlib.h>int setenv(const char *name, const char *newvalue, int overwrite);
// 返回:若成功则为 0,若错误则为 -1。void unsetenv(const char *name);
// 返回:无。
setenv
用于设置(或修改)一个环境变量的值。如果该环境变量已存在,它将被更新;如果不存在,它会被创建。
unsetenv
用于删除指定的环境变量。调用该函数后,该环境变量在当前进程的环境中将不再可用。
相关文章:

Linux系统 进程
Linux系统 进程 进程私有地址空间用户模式和内核模式上下文切换 进程控制系统调用错误处理进程控制函数获取进程 ID创建和终止进程回收子进程让进程休眠加载并运行程序 进程 异常是允许操作系统内核提供进程(process)概念的基本构造块,进程是…...
机载视频流回传+编解码方案
无线网络,低带宽场景。不能直接转发ROS raw image(10MB/s),而要压缩(编码)后再传输。可以用rtsp的udp传输或者直接传输话题,压缩方法有theora(ROS image_transport默认支持ÿ…...

Ubuntu 20.04 Server版连接Wifi
前言 有时候没有网线口插网线或者摆放电脑位置不够时,需要用Wifi联网。以下记录Wifi联网过程。 环境:Ubuntu 20.04 Server版,无UI界面 以下操作均为root用户,如果是普通用户,请切换到root用户,或者在需要权…...

【VRChat 改模】开发环境搭建:VCC、VRChat SDK、Unity 等环境配置
一、配置 Unity 相关 1.下载 UnityHub 下载地址:https://unity.com/download 安装打开后如图所示: 2.下载 VRChat 官方推荐版本的 Unity 跳转界面(VRChat 官方推荐页面):https://creators.vrchat.com/sdk/upgrade/…...

人工智能的微积分基础
目录 编辑 引言 微积分的基本概念 1. 导数 2. 积分 3. 微分方程 微积分在人工智能中的应用 1. 机器学习中的优化 2. 反向传播算法 3. 概率与统计 4. 控制理论 5. 自然语言处理中的梯度 6. 计算机视觉中的积分 7. 优化算法中的微积分 8. 微分几何在深度学习中的…...
Android 基础类(01)- Thread类 - readyToRun和threadLoop
一、前言: 在阅读AOSP代码过程中,我们经常会看到Thread子类重写两个方法:readyToRun和threadLoop,不清楚的同学,可能在这儿连调用逻辑都搞不清楚了,因为找不到谁调用了它。我这儿先不去深究Thread内部逻辑…...
C++设计模式之构造器
动机 在软件系统中,有时候面临着“一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。 如何…...

红日靶场-5
环境搭建 这个靶场相对于前几个靶场来说较为简单,只有两台靶机,其中一台主机是win7,作为我们的DMZ区域的入口机,另外一台是windows2008,作为我们的域控主机,所以我们只需要给我们的win7配置两张网卡&#…...

做异端中的异端 -- Emacs裸奔之路3: 上古神键Hyper
谈一下快捷捷冲突的问题。 Emacs几乎穷尽所有组合键 我用下面命令,在Fundamental模式下,枚举所有绑定。 (defun keymap-lookup-test-fn(); printable keys(setq printable-chars (number-sequence 33 126))(setq i 0)(while (< i (length printable…...

Java多线程介绍及使用指南
“多线程”:并发 要介绍线程,首先要区分开程序、进程和线程这三者的区别。 程序:具有一定功能的代码的集合,但是是静态的,没有启动运行 进程:启动运行的程序【资源的分配单位】 线程:进程中的…...

HarmonyOS 5.0应用开发——列表(List)
【高心星出品】 文章目录 列表(List)列表介绍列表布局设置主轴方向设置交叉轴方向 列表填充分组列表填充 滚动条位置设置滚动位置滚到监听 列表项侧滑 列表(List) 列表介绍 列表作为一种容器,会自动按其滚动方向排列…...
自动化电气行业的优势和劣势是什么
优势 市场需求广泛: 自动化电气技术广泛应用于电力系统、制造业、交通、农业等多个领域,随着智能化、数字化趋势的加强,其市场需求持续增长。在智能制造、智能电网等领域,自动化电气技术更是发挥着关键作用,推动了行业…...
第 42 章 - Go语言 设计模式
在Go语言中,设计模式是一种被广泛接受的解决常见问题的最佳实践。这些模式可以分为三类:创建型模式、结构型模式和行为型模式。下面我将结合案例以及源代码对这三种类型的设计模式进行详细讲解。 创建型模式 创建型模式主要关注对象的创建过程…...
【机器学习】---大语言模型
引言:开启大语言模型的奇幻旅程 近年来,人工智能(AI)领域正在经历一场前所未有的技术革命,而其中最耀眼的明星莫过于大语言模型(Large Language Models, LLMs)。这些模型,犹如现代科…...

挑战用React封装100个组件【002】
项目地址 https://github.com/hismeyy/react-component-100 组件描述 组件适用于需要展示图文信息的场景,比如产品介绍、用户卡片或任何带有标题、描述和可选图片的内容展示 样式展示 代码展示 InfoCard.tsx import ./InfoCard.cssinterface InfoCardProps {t…...

MarkDown-插入图片-图片url地址的生成获取方法
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、url地址是什么二、如何获取图片的url地址1.了解图床2.使用图床获取图片URL地址2.1进入网站后,点击右下角“Select Image.”按钮,即可…...

插值、拟合和回归分析的相关知识
目录 0 序言 1 分段线性插值 2 多项式插值 3 样条插值 4 最小二乘拟合 5 多元线性回归 0 序言 在生产实践和科学研究中,常常有这些问题: 插值问题:由实验或测量得到变量间的一批离散样点,要求得到变量之间的函数关系或得到样点之外的…...

【小白学机器学习42】进行多次抽样,样本的分布参数和总体的分布参数的关系
目录 1 进行多次抽样,样本的分布参数和总体的分布参数的关系 2 样本容量越大,多次抽样的样本的分布参数和总体的分布参数的关系 3 随着样本容量增大,多次抽样均值的 平均值,方差的变化 4 随着样本容量增大,多次抽…...
链动星海 质引未来|中信银行加码科技金融 “接力式”服务助力“新质生产力”释放
11月26日,第二届中国国际供应链促进博览会(以下简称链博会)在北京中国国际展览中心开幕。中信集团以“链动星海 质引未来”为主题,亮相先进制造链展区。此次布展由中信金控主办、中信银行承办,携手中信证券、中信建投证…...
黑马2024AI+JavaWeb开发入门Day02-JS-VUE飞书作业
视频地址:哔哩哔哩 讲义作业飞书地址:飞书 一、作业1 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge">&l…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...

Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...

微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...

给网站添加live2d看板娘
给网站添加live2d看板娘 参考文献: stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下,文章也主…...
离线语音识别方案分析
随着人工智能技术的不断发展,语音识别技术也得到了广泛的应用,从智能家居到车载系统,语音识别正在改变我们与设备的交互方式。尤其是离线语音识别,由于其在没有网络连接的情况下仍然能提供稳定、准确的语音处理能力,广…...
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么?它的作用是什么? Spring框架的核心容器是IoC(控制反转)容器。它的主要作用是管理对…...

MySQL的pymysql操作
本章是MySQL的最后一章,MySQL到此完结,下一站Hadoop!!! 这章很简单,完整代码在最后,详细讲解之前python课程里面也有,感兴趣的可以往前找一下 一、查询操作 我们需要打开pycharm …...