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…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
【LeetCode】算法详解#6 ---除自身以外数组的乘积
1.题目介绍 给定一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O…...
Ubuntu系统多网卡多相机IP设置方法
目录 1、硬件情况 2、如何设置网卡和相机IP 2.1 万兆网卡连接交换机,交换机再连相机 2.1.1 网卡设置 2.1.2 相机设置 2.3 万兆网卡直连相机 1、硬件情况 2个网卡n个相机 电脑系统信息,系统版本:Ubuntu22.04.5 LTS;内核版本…...
uni-app学习笔记三十五--扩展组件的安装和使用
由于内置组件不能满足日常开发需要,uniapp官方也提供了众多的扩展组件供我们使用。由于不是内置组件,需要安装才能使用。 一、安装扩展插件 安装方法: 1.访问uniapp官方文档组件部分:组件使用的入门教程 | uni-app官网 点击左侧…...
DeepSeek越强,Kimi越慌?
被DeepSeek吊打的Kimi,还有多少人在用? 去年,月之暗面创始人杨植麟别提有多风光了。90后清华学霸,国产大模型六小虎之一,手握十几亿美金的融资。旗下的AI助手Kimi烧钱如流水,单月光是投流就花费2个亿。 疯…...
数据结构:泰勒展开式:霍纳法则(Horner‘s Rule)
目录 🔍 若用递归计算每一项,会发生什么? Horners Rule(霍纳法则) 第一步:我们从最原始的泰勒公式出发 第二步:从形式上重新观察展开式 🌟 第三步:引出霍纳法则&…...
验证redis数据结构
一、功能验证 1.验证redis的数据结构(如字符串、列表、哈希、集合、有序集合等)是否按照预期工作。 2、常见的数据结构验证方法: ①字符串(string) 测试基本操作 set、get、incr、decr 验证字符串的长度和内容是否正…...
FTXUI::Dom 模块
DOM 模块定义了分层的 FTXUI::Element 树,可用于构建复杂的终端界面,支持响应终端尺寸变化。 namespace ftxui {...// 定义文档 定义布局盒子 Element document vbox({// 设置文本 设置加粗 设置文本颜色text("The window") | bold | color(…...
