Linux系统调用编程
文章目录
- 一、进程和线程
- 二、Linux的虚拟内存管理和stm32的真实物理内存
- **Linux虚拟内存管理**
- STM32物理内存映射
- 2. 主要区别
- 三、Linux系统调用函数 fork()、wait()、exec()
- 1. fork():创建子进程
- 2. wait():等待子进程状态改变
- 3. exec():替换进程映像
- 综合应用
- 四、总结
一、进程和线程
进程:进程是程序的执行实例,是操作系统分配资源(CPU、内存、文件等)的基本单位。每个进程拥有独立的地址空间和系统资源。一个进程可以有多个线程,比如在Windows系统中,一个运行的xx.exe就是一个进程。

线程:线程是进程内的执行单元,是CPU调度的基本单位。一个进程可包含多个线程,所有线程共享进程的资源(如内存、文件)。如浏览器的一个标签页可能用一个线程加载页面,另一个线程处理用户输入。
在Linux虚拟机下查看进程
使用命令:ps -a

终止进程:kill 进程号

二、Linux的虚拟内存管理和stm32的真实物理内存
Linux虚拟内存管理
虚拟地址空间:每个进程拥有独立的虚拟地址空间(通常为4GB或更大),由**内存管理单元(MMU)**动态映射到物理内存或磁盘交换空间。
分页机制:物理内存被划分为固定大小的页(如4KB),虚拟地址通过页表转换到物理页帧。未使用的页可被换出到磁盘(Swap)。
内存保护:不同进程的内存空间隔离,防止非法访问(如写只读页会触发段错误)。
按需分配:内存分配延迟到实际使用时(如malloc申请内存后,物理页在首次访问时才分配)。
共享内存:多个进程可通过虚拟内存映射共享同一物理内存(如动态库)。
STM32物理内存映射
直接访问物理地址:程序直接操作物理内存和外设寄存器,无地址转换层(通常无MMU)。
静态内存布局:内存和外设的地址在芯片设计时固定(如Flash、SRAM、GPIO寄存器的地址在数据手册中定义)。
确定性访问:无分页或交换机制,内存访问延迟固定,适合实时性要求高的场景。
手动管理:开发者需自行规划内存使用(如静态分配或简单动态分配)。
2. 主要区别
| 特性 | Linux虚拟内存 | STM32物理内存映射 |
|---|---|---|
| 地址空间 | 虚拟地址(由MMU转换) | 直接使用物理地址 |
| 硬件支持 | 依赖MMU实现地址转换和保护 | 无MMU,可能支持MPU(仅内存保护) |
| 内存隔离 | 进程间隔离,防止越界访问 | 无隔离,需开发者保证正确性 |
| 多任务支持 | 通过虚拟内存实现进程独立地址空间 | 需RTOS配合(如FreeRTOS)或裸机调度 |
| 动态内存分配 | 灵活(如malloc+缺页中断) | 通常静态分配或简单堆管理(易碎片化) |
| 交换空间 | 支持磁盘交换扩展可用内存 | 无交换,受限于物理内存大小 |
| 外设访问 | 通过内核驱动(如mmap映射到用户空间) | 直接读写外设寄存器地址 |
| 实时性 | 不确定(因页错误或交换延迟) | 确定性的低延迟访问 |
三、Linux系统调用函数 fork()、wait()、exec()
1. fork():创建子进程
功能:复制当前进程,生成一个几乎完全相同的子进程(包括代码、数据、堆栈、文件描述符等)。
子进程从 fork() 的返回处开始执行,与父进程并发运行。
关键特性
| 返回值 | 含义 |
|---|---|
| >0 | 父进程中返回子进程PID |
| 0 | 子进程中返回0 |
| -1 | 调用失败 |
写时复制(Copy-On-Write, COW)
父子进程共享物理内存,直到任一进程尝试修改数据时才会复制内存页,提高效率。
示例代码
#include <unistd.h>
#include <stdio.h>int main() {pid_t pid = fork();if (pid == -1) {perror("fork failed");return 1;} else if (pid == 0) {printf("子进程 (PID: %d)\n", getpid());} else {printf("父进程 (Child PID: %d)\n", pid);}return 0;
}
2. wait():等待子进程状态改变
功能
阻塞父进程,直到某个子进程终止或收到信号。
回收子进程资源(避免僵尸进程)。
常用函数
wait(int *status):等待任意子进程结束,状态存入 status。
waitpid(pid_t pid, int *status, int options):
可指定等待的子进程PID(pid=-1 表示任意子进程),支持非阻塞选项(如 WNOHANG)。
状态宏(检查子进程退出原因):
WIFEXITED(status):子进程正常退出。
WEXITSTATUS(status):获取子进程退出码。
WIFSIGNALED(status):子进程被信号终止。
示例代码
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>int main() {pid_t pid = fork();if (pid == 0) {printf("子进程存在...\n");_exit(42); // 子进程退出码42} else {int status;wait(&status);if (WIFEXITED(status)) {printf("子进程存在码 %d\n", WEXITSTATUS(status));}}return 0;
}
3. exec():替换进程映像
功能
加载新程序到当前进程的内存空间,替换原有代码、数据、堆栈等。
调用成功后,原进程的代码不再执行(除非 exec() 失败)。
常用函数(参数传递方式不同):
| 函数 | 参数格式 | 示例 |
|---|---|---|
| execl() | 可变参数列表(NULL结尾) | execl(“/bin/ls”, “ls”, “-l”, NULL) |
| execv() | 字符串数组(argv风格) | char *args[] = {“ls”, “-l”, NULL}; execv(“/bin/ls”, args) |
| execvp() | 自动搜索 PATH 环境变量 | execvp(“ls”, args) |
关键特性
无返回值:成功时不返回,失败时返回 -1(需检查错误)。
保留的文件描述符:默认保持打开(可通过 fcntl 设置 FD_CLOEXEC 关闭)。
示例代码
#include <unistd.h>
#include <stdio.h>int main() {execl("/bin/ls", "ls", "-l", NULL); // 替换为执行 `ls -l`perror("exec 失败"); // 仅当exec失败时执行return 1;
}
综合应用
//C程序来说明fork()的用法&
//exec()系统调用以创建进程#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/wait.h>int main(){
pid_t pid;
int ret = 1;
int status;
pid = fork();if (pid == -1){// pid == -1 表示发生了错误printf("can't fork, error occured\n");exit(EXIT_FAILURE);
}
else if (pid == 0){// pid == 0 表示创建了子进程// getpid() 返回调用进程的进程id// 返回子进程的进程idprintf("child process, pid = %u\n",getpid());// 返回子进程的父进程,即父进程本身printf("parent of child process, pid = %u\n",getppid());// argv list第一个参数应该指向// 与正在执行的文件关联的文件名// 数组指针必须以NULL结尾// 指针char * argv_list[] = {"ls","-lart","/home",NULL};// execv()仅在发生错误时返回。// 返回值为-1execv("ls",argv_list);exit(0);
}
else{// 为pid返回一个正数// 父进程// getppid()返回进程的父进程id// 调用进程// 返回父进程ID的父进程printf("Parent Of parent process, pid = %u\n",getppid());printf("parent process, pid = %u\n",getpid());// 父进程对子进程调用waitpid()// waitpid()系统调用暂停// 调用进程直到pid指定的子进程// 状态改变// 有关所有标志或选项,请参见wait()手册if (waitpid(pid, &status, 0) > 0) {if (WIFEXITED(status) && !WEXITSTATUS(status))printf("program execution successful\n");else if (WIFEXITED(status) && WEXITSTATUS(status)) {if (WEXITSTATUS(status) == 127) {// execv failedprintf("execv failed\n");}elseprintf("program terminated normally,"" but returned a non-zero status\n");}elseprintf("program didn't terminate normally\n");}else {// waitpid() failedprintf("waitpid() failed\n");}exit(0);
}
return 0;
}
运行效果:

四、总结
本次学习了进程和线程、虚拟内存管理、系统函数fork()、wait()、exec()的相关知识以及在Linux虚拟机上的基本使用。
参考链接:1.Linux下的fork和exec函数
2.探索 Linux 编程基础 深入理解 fork 函数的实现原理与实践应用
3.详解Linux中的fork,exec,wait
4.添加进程和线程的区别(超详细)
相关文章:
Linux系统调用编程
文章目录 一、进程和线程二、Linux的虚拟内存管理和stm32的真实物理内存**Linux虚拟内存管理**STM32物理内存映射2. 主要区别 三、Linux系统调用函数 fork()、wait()、exec()1. fork():创建子进程2. wait():等待子进程状态改变3. exec():替换…...
游戏引擎学习第203天
回顾当前情况 在这里我将直播完成整个游戏的制作。我们现在面临一些技术上的困难,确实如此。我的笔记本电脑的电源接口坏了,所以我不得不准备了这台备用笔记本,希望它能够正常工作。我所以希望一切都还好,尽管我不完全确定是否一…...
408 计算机网络 知识点记忆(4)
前言 本文基于王道考研课程与湖科大计算机网络课程教学内容,系统梳理核心知识记忆点和框架,既为个人复习沉淀思考,亦希望能与同行者互助共进。(PS:后续将持续迭代优化细节) 往期内容 408 计算机网络 知识…...
线性代数:分块矩阵,秩,齐次线性,非齐次线性的解相关经典例题
所以C错误,选D 排除A,B选项...
Nginx功能及应用全解:从负载均衡到反向代理的全面剖析
Nginx作为一款开源的高性能HTTP服务器和反向代理服务器,凭借其高效的资源利用率和灵活的配置方式,已成为互联网领域中最受欢迎的Web服务器之一。无论是作为HTTP服务器、负载均衡器,还是作为反向代理和缓存服务器,Nginx的多种功能广…...
深度学习数据集划分比例多少合适
在机器学习和深度学习中,测试集的划分比例需要根据数据量、任务类型和领域需求灵活调整。 1. 常规划分比例 通用场景 训练集 : 验证集 : 测试集 60% : 20% : 20% 适用于大多数中等规模数据集(如数万到数十万样本),平衡了训练数…...
CExercise_1_5 水仙花数
题目: 经典循环案例:请求出所有的水仙花数,并统计总共有几个。 所谓的水仙花数是指一个三位数,其各位数字的立方和等于该数本身。 举例:153就是一个水仙花数,153 1 * 1 * 1 5 * 5 * 5 3 * 3 * 3 1 125…...
用C实现一个最简单的正则表达式引擎
用C实现一个简单的正则表达式引擎 下面我将实现一个极简的正则表达式引擎,仅支持以下基本功能: . 匹配任意单个字符* 匹配零个或多个前导字符^ 匹配字符串开头$ 匹配字符串结尾 完整代码实现 #include <stdio.h> #include <stdbool.h>bo…...
哈密尔顿路径(Hamiltonian Path)及相关算法题目
哈密尔顿路径要求访问图中每个顶点恰好一次,通常用于解决旅行商问题(TSP)或状态压缩DP问题。 哈密尔顿路径(Hamiltonian Path)是指在一个图中经过每个顶点恰好一次的路径。如果这条路径的起点和终点相同(即…...
MINIQMT学习课程Day10
开始获取股票数据课程的学习: 获取qmt账号的持仓情况后,我们进入下一步,如何获得当前账号的委托状况 还是之前的步骤,打开qmt,选择独立交易, 之后使用pycharm,编写py文件 导入包:…...
JAVA实战开源项目:智慧图书管理系统(Vue+SpringBoot) 附源码
本文项目编号 T 152 ,文末自助获取源码 \color{red}{T152,文末自助获取源码} T152,文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…...
Linux 系统管理综合实训 —— 基于 NAT 模式的多 IP 配置、Nginx 服务部署及存储管理
1. 虚拟机网络配置:NAT模式与多IP地址设置 将你的虚拟机的网卡模式设置为nat模式,给虚拟机网卡配置三个主机位分别为100、200、168的ip地址 设置静态IP [rootlocalhost ~]# nmcli c modify ens160 ipv4.method manual ipv4.addresses 192.168.2.100/2…...
如何在windows 环境、且没有显卡的情况下用python跑通从ModelScope下载的大模型的调用
文章目录 背景介绍源代码:安装调试过程1.设置第三方镜像源2.预先安装:3.在python中创建代码:4.最终修改程序,将device_map从“cuda”改成“auto”,大模型调用1.5B(1___5B)的5.最终跑出结果解释:示例&#x…...
黑马点评redis改 part 1
本篇将主要阐述短信登录的相关知识,感谢黑马程序员开源,感谢提供初始源文件(给到的是实战第7集开始的代码)【Redis实战篇】黑马点评学习笔记(16万字超详细、Redis实战项目学习必看、欢迎点赞⭐收藏)-CSDN博…...
Apache Struts2 漏洞(CVE-2017-5638)技术分析
一、漏洞简介 CVE-2017-5638 是 Apache Struts2 中的一个远程命令执行漏洞,攻击者可以通过构造特定的 HTTP 请求头,利用Struts的 OGNL 表达式解析机制,在服务器端执行任意代码。 二、漏洞触发场景 漏洞存在于 Struts2 的 Jakarta Multipar…...
A2DP(Advanced Audio Distribution Profile)是蓝牙协议栈中用于音频传输的一个标准化协议
A2DP(Advanced Audio Distribution Profile)是蓝牙协议栈中用于音频传输的一个标准化协议,主要用于高质量音频流的无线传输。以下是A2DP协议的详细信息: 定义 A2DP协议允许音源设备(Source,简称SRC&#…...
【Ragflow】11. 文件解析流程分析/批量解析实现
概述 本文继续对ragflow文档解析部分进行分析,并通过脚本的方式实现对文件的批量上传解析。 文件解析流程 文件解析的请求处理流程大致如下: 1.前端上传文件,通过v1/document/run接口,发起文件解析请求 2.后端api\apps\docum…...
第三期:深入理解 Spring Web MVC [特殊字符](数据传参+ 特殊字符处理 + 编码问题解析)
✨前言:传参和状态管理,看似简单其实门道不少 在 Web 开发中,前端和后端最核心的交流方式就是“传参”,而“传参”除了涉及如何写代码获取参数,还藏着很多开发者容易忽略的细节: 为什么 URL 带了中文&…...
嵌入式学习笔记——ARM-中断与异常
文章目录 中断与异常的区别中断与 DMA 的区别中断能否睡眠?下半部能否睡眠?1. 中断处理程序不能睡眠2. 下半部(SoftIRQ、Tasklet、Workqueue) 中断处理注意点1. 快进快出2. 避免阻塞3. 正确返回值4. 如何处理大量任务5. 避免竞态问…...
Everything 安装教程与使用教程(附安装包)
文章目录 前言一、Everything 介绍二、Everything 安装教程1.Everything 安装包下载2.选择安装文件3.选择安装语言4.接受许可协议5.选择安装位置6.配置安装选项7.完成安装 三、Everything 使用教程1.启动软件2.简单关键词搜索3.按类型搜索 前言 在日常使用电脑时,随…...
嵌入式开发中栈溢出的处理方法
嵌入式开发中栈溢出的处理方法 目录 引言栈溢出的原理栈溢出的危害栈溢出检测方法 哨兵变量法栈着色法硬件监测机制编译器栈保护 裸机系统中的栈溢出处理操作系统中的栈溢出处理预防栈溢出的最佳实践结论 引言 在嵌入式系统开发中,栈溢出是一个常见且危险的问题…...
SQL语句(三)—— DQL
目录 基本语法 一、基础查询 1、查询多个字段 2、字段设置别名 3、去除重复记录 4、示例代码 二、条件查询 1、语法 2、条件列表常用的运算符 3、示例代码 三、分组查询 (一)聚合函数 1、介绍 2、常见的聚合函数 3、语法 4、示例代码 &…...
#python项目生成exe相关了解
在 Windows 上将 Python 项目 生成 EXE 可执行文件,主要使用 pyinstaller。以下是完整步骤: 📌 1. 安装 PyInstaller pip install pyinstaller如果已安装,可执行以下命令检查版本: pyinstaller --versionὌ…...
Opencv计算机视觉编程攻略-第九节 描述和匹配兴趣点
一般而言,如果一个物体在一幅图像中被检测到关键点,那么同一个物体在其他图像中也会检测到同一个关键点。图像匹配是关键点的常用功能之一,它的作用包括关联同一场景的两幅图像、检测图像中事物的发生地点等等。 1.局部模板匹配 凭单个像素就…...
JSON-lib考古现场:在2025年打开赛博古董店的奇妙冒险
各位在代码海洋里捡贝壳的探险家们!今天我们要打开一个尘封的Java古董箱——JSON-lib!这货可是2003年的老宝贝,比在座很多程序员的工龄还大!准备好穿越回Web 1.0时代,感受XML统治时期的余晖了吗? …...
Android: Handler 的用法详解
Android 中 Handler 的用法详解 Handler 是 Android 中用于线程间通信的重要机制,主要用于在不同线程之间发送和处理消息。以下是 Handler 的全面用法指南: 一、Handler 的基本原理 Handler 基于消息队列(MessageQueue)和循环器(Looper)工作,…...
汇编学习之《push , pop指令》
学习本章前线了解ESP, EBP 指令 汇编学习之《指针寄存器&大小端学习》-CSDN博客 栈的特点: 好比一个垂直容器,可以陆续放入物体,但是先放的物体通常会被后面放的物体压着,只有等上面后放的物品拿出来后,才能…...
Python循环控制语句
1. 循环类型概述 Python提供两种主要的循环结构: while循环 - 在条件为真时重复执行for循环 - 遍历序列中的元素 2. while循环 基本语法 while 条件表达式:循环体代码示例 count 0 while count < 5:print(f"这是第{count1}次循环")count 13. f…...
微信小程序(下)
目录 在事件处理函数中为 data 中的数据赋值 事件传参 bindinput 的语法格式 实现文本框和 data 之间的数据同步 条件渲染 结合 使用 wx:if hidden wx:if与 hidden 的对比 wx:for 手动指定索引和当前项的变量名 wx:key 的使用 WXSS 和 CSS 的关系 什么是 rpx 尺寸…...
【零基础入门unity游戏开发——2D篇】2D 游戏场景地形编辑器——TileMap的使用介绍
考虑到每个人基础可能不一样,且并不是所有人都有同时做2D、3D开发的需求,所以我把 【零基础入门unity游戏开发】 分为成了C#篇、unity通用篇、unity3D篇、unity2D篇。 【C#篇】:主要讲解C#的基础语法,包括变量、数据类型、运算符、…...
