【XTerminal】【树莓派】Linux系统下的函数调用编程
目录
一、XTerminal下的Linux系统调用编程
1.1理解进程和线程的概念并在Linux系统下完成相应操作
(1) 进程
(2)线程
(3) 进程 vs 线程
(4)Linux 下的实践操作
1.2Linux的“虚拟内存管理”和stm32正式物理内存(内存映射)的区别
(1)Linux虚拟内存管理
(2)STM32物理内存映射
(3)主要区别
1.3理解 Linux系统调用函数 fork()、wait()、exec() 等并通过vi 编辑一个c程序
(1)系统调用函数介绍
fork()
wait()
exec()
(2)创建syscall_demo.c
(3)编写示例程序
(4)编译运行
二、在树莓派中创建多个账号并完成Linux系统调用函数联系
1.1组员账号创建
1.2在树莓派环境中学习并调用fork()、wait()和exec()函数
(1)创建文件 syscall_demo.c
(2)编写示例程序
(3)编译运行
一、XTerminal下的Linux系统调用编程
1.1理解进程和线程的概念并在Linux系统下完成相应操作
(1) 进程
定义:进程是程序的一次执行实例,拥有独立的内存空间、文件描述符和系统资源。
特点:
-
每个进程有唯一的 PID(进程ID)。
-
进程间相互隔离,通信需通过 IPC(进程间通信) 机制(如管道、共享内存等)。
-
创建进程通过
fork()或exec()系统调用。
(2)线程
定义:线程是进程内的执行单元,共享同一进程的内存和资源。
特点:
-
线程有独立的 栈,但共享堆、全局变量和文件描述符。
-
创建线程通过
pthread_create()(POSIX 线程库)。 -
轻量级,切换开销比进程小。
(3) 进程 vs 线程
| 特性 | 进程 | 线程 |
|---|---|---|
| 独立性 | 完全隔离 | 共享同一进程资源 |
| 创建开销 | 大(需复制内存) | 小(共享内存) |
| 通信方式 | IPC(管道、信号等) | 直接读写共享变量 |
| 崩溃影响 | 不影响其他进程 | 导致整个进程终止 |
(4)Linux 下的实践操作
ps -a

通过kill命令尝试终止该进程
kill -9 PID

我们发现提示没有那个进程。这是因为该进程为临时进程,执行完毕后已自动退出,因此报错 。
我们可以通过下面命令查找系统中所有的进程及其对应的PID
ps -aux

我们可以对应选择一个进程进行结束

1.2Linux的“虚拟内存管理”和stm32正式物理内存(内存映射)的区别
(1)Linux虚拟内存管理
核心机制: Linux通过虚拟内存抽象物理内存,为每个进程提供独立的、连续的虚拟地址空间(通常为4GB,32位系统),由MMU(内存管理单元)动态映射到物理内存或磁盘交换空间。
其工作流程为:
进程访问虚拟地址 → MMU查页表 → 若页在物理内存则访问,否则触发缺页异常 → 内核加载缺失页或终止进程
(2)STM32物理内存映射
核心机制: STM32等嵌入式MCU通常直接操作物理内存,通过内存映射(将外设寄存器、Flash、RAM等硬件资源分配到固定的物理地址。
其典型内存布局为:
0x00000000 - 0x1FFFFFFF: Flash(代码存储) 0x20000000 - 0x2001FFFF: SRAM(数据) 0x40000000 - 0x5FFFFFFF: 外设寄存器
(3)主要区别
| 特性 | Linux虚拟内存 | STM32物理内存映射 |
|---|---|---|
| 地址空间 | 虚拟地址(进程独立) | 物理地址(全局唯一) |
| 硬件支持 | 依赖MMU实现地址转换 | 无MMU,直接访问物理地址 |
| 内存扩展 | 支持Swap扩展虚拟内存 | 仅限芯片内置的物理内存 |
| 内存保护 | 通过页表实现权限控制 | 无保护,需开发者谨慎操作 |
| 外设访问 | 通过/dev/mem或驱动间接访问 | 直接读写内存映射的外设寄存器 |
| 使用场景 | 通用计算(多任务、复杂应用) | 实时嵌入式系统(确定性、低延迟) |
存在差异的原因:
Linux需要支持多进程、大内存应用,虚拟内存提供灵活性和安全性。
STM32:追求实时性和确定性,省去MMU降低开销,适合裸机或RTOS(如FreeRTOS)。
1.3理解 Linux系统调用函数 fork()、wait()、exec() 等并通过vi 编辑一个c程序
(1)系统调用函数介绍
fork()
功能:创建一个新的进程(子进程),子进程是父进程的副本。
返回值:
-
父进程中返回子进程的PID(>0)。
-
子进程中返回0。
-
失败时返回-1。
头文件:<unistd.h>
wait()
功能:父进程等待子进程结束,并回收子进程的资源(防止僵尸进程)。
参数:int *status(存储子进程的退出状态)。
返回值:成功时返回子进程PID,失败时返回-1。
头文件:<sys/wait.h>
exec()
功能:替换当前进程的映像为新的程序(如运行另一个可执行文件)。
常用变体:
-
execl():参数列表形式。 -
execv():参数数组形式。 -
execvp():自动搜索PATH环境变量。
返回值:成功时不返回,失败时返回-1。
头文件:<unistd.h>
(2)创建syscall_demo.c
vi syscall_demo.c
(3)编写示例程序
进入vi编译器后,按"i"进入插入模式
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>int main() {pid_t pid;int status;pid = fork();if (pid < 0) {fprintf(stderr, "Fork failed!\n");return 1;} else if (pid == 0) {printf("Child Process (PID=%d): Hello from fork()!\n", getpid());execlp("ls", "ls", "-l", NULL);perror("exec failed");return 1;} else {printf("Parent Process (PID=%d): Waiting for child...\n", getpid());wait(&status);printf("Parent: Child exited with status %d\n", WEXITSTATUS(status));}return 0;
}
编写完成后按Esc退出插入模式,输入“:wq”保存并退出
注:
| 保存文件 | Esc → :w → 回车 | 保存但不退出 |
|---|---|---|
| 保存并退出 | Esc → :wq → 回车 | 保存并退出 |
| 强制退出不保存 | Esc → :q! → 回车 | 丢弃所有修改 |

(4)编译运行
输入下面代码进行编译运行:
#编译
gcc syscall_demo.c -o syscall_demo
#添加权限
chmod +x syscall_demo
# 运行
./syscall_demo

结果解释:
Parent Process (PID=960685): Waiting for child
#父进程(PID=960685)打印信息,表示已通过 fork() 创建子进程,并调用 wait() 进入阻塞状态,等待子进程结束。Child Process (PID=960686): Hello from fork()!
#子进程(PID=960686)被创建后,打印自己的 PID 和消息,随后调用execlp("ls", "ls", "-l", NULL)。
子进程的代码映像被替换为 ls -l 命令,原程序的后续代码(如 perror)不再执行。-rwxr-xr-x 1 zhangzy group2 17056 Apr 3 23:23 a.out
-rwxr-xr-x 1 zhangzy group2 17056 Apr 3 23:25 syscall_demo
-rw-r--r-- 1 zhangzy group2 610 Apr 3 23:23 syscall_demo.c
-rwxr-xr-x 1 zhangzy group2 65 Apr 3 22:12 test.sh
#ls -l 命令的输出,显示当前目录下的文件详情:
总用量 48Parent: Child exited with status
#子进程(ls -l)执行完毕后,父进程的 wait(&status) 返回。
WEXITSTATUS(status) 提取子进程的退出状态码 0,表示 ls 命令成功执行。
二、在树莓派中创建多个账号并完成Linux系统调用函数联系
1.1组员账号创建
首先要进行树莓派的VNC远程登录,具体步骤可以看我前面的博客:树莓派3b:环境配置,VNC远程控制并进行简单代码运行_树莓派vnc-CSDN博客
先进入VNC命令行

(1)创建用户
为每个组员创建一个独立的系统账号,并生成各自的目录
sudo adduser user1
sudo adduser user2

(2)配置用户权限
确保用户有基本的开发权限,(如sudo权限)
# 将用户添加到sudo组(允许执行管理员命令)
sudo usermod -aG sudo username1# 验证用户组
groups username1

我们通过命令行测试,发现新用户可以进行登录(后续代码也可以通过电脑命令行实现)

1.2在树莓派环境中学习并调用fork()、wait()和exec()函数
(1)创建文件 syscall_demo.c
nano syscall_demo.c
(2)编写示例程序
该程序展示了Linux系统调用fork()、exec()、和wait()函数的工作过程
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>int main() {pid_t pid;int status;// 1. fork() 示例pid = fork();if (pid < 0) {fprintf(stderr, "Fork failed!\n");return 1;} else if (pid == 0) {// 子进程printf("Child Process (PID=%d): Hello from fork()!\n", getpid());// 2. exec() 示例:替换为执行 'ls' 命令execlp("ls", "ls", "-l", NULL);// 如果exec失败,才会执行到这里perror("exec failed");return 1;} else {// 父进程printf("Parent Process (PID=%d): Waiting for child...\n", getpid());// 3. wait() 示例wait(&status);printf("Parent: Child exited with status %d\n", WEXITSTATUS(status));}return 0;
}
(3)编译运行
编译:
gcc syscall_demo.c -o syscall_demo
运行:
./syscall_demo

相关文章:
【XTerminal】【树莓派】Linux系统下的函数调用编程
目录 一、XTerminal下的Linux系统调用编程 1.1理解进程和线程的概念并在Linux系统下完成相应操作 (1) 进程 (2)线程 (3) 进程 vs 线程 (4)Linux 下的实践操作 1.2Linux的“虚拟内存管理”和stm32正式物理内存(内存映射)的区别 (1)Linux虚拟内存管…...
umi框架开发移动端h5
1、官网:https://umijs.org/ 2、创建出来的项目 yarn create umi yarn start3、推荐目录结构 . ├── config │ └── config.ts ├── public//静态资源 ├── dist ├── mock │ └── app.ts|tsx ├── src │ ├── .umi │ ├── .um…...
TDengine 重磅功能虚拟表
简介 虚拟表功能是 TDengine 最近刚发现的 3.3.6.0 版本中一项重磅级新功能,虚拟表可理解为在原来查询基础上做了一层逻辑表,在数据查询建模时即可不依赖底层物理存储表,直接通过虚拟表进行数据查询建模,这样逻辑上会更加清晰&am…...
3.9/Q2,Charls最新文章解读
文章题目:Association between remnant cholesterol and depression in middle-aged and older Chinese adults: a population-based cohort study DOI:10.3389/fendo.2025.1456370 中文标题:中国中老年人残留胆固醇与抑郁症的关系࿱…...
Java Lambda 表达式提升效率
lambda 表达式的应用场景 Stream 的应用场景 Lambda/Stream 的进一步封装 自定义函数式接口(用 jdk 自带的函数式接口也可以) https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html import java.io.Serializable;/*** 可序…...
人工智能混合编程实践:C++ ONNX进行图像超分重建
人工智能混合编程实践:C++ ONNX进行图像超分重建 前言相关介绍C++简介ONNX简介ONNX Runtime 简介**核心特点**图像超分辨率重建简介应用场景前提条件实验环境项目结构使用C++ ONNX进行图像超分重建sr_main.cpp参考文献前言 由于本人水平有限,难免出现错漏,敬请批评改正。更多…...
K8S学习之基础七十四:部署在线书店bookinfo
部署在线书店bookinfo 在线书店-bookinfo 该应用由四个单独的微服务构成,这个应用模仿在线书店的一个分类,显示一本书的信息,页面上会显示一本书的描述,书籍的细节(ISBN、页数等),以及关于这本…...
Python不可变数据类型全解析:原理、优势与实战指南
目录 引言:为什么Python要区分可变与不可变? 一、不可变数据类型的核心特性 二、五大不可变数据类型深度解析 三、不可变数据类型的三大核心优势 四、不可变数据类型的典型应用场景 五、不可变 vs 可变:如何选择? 六、实战技…...
六.FFmpeg对mp4文件操作(ubuntu)
一.抽取aac数据 1.代码抽取aac没有声音,使用ffmpeg命令行也无法转换为wav 问题解决:ADTS头的采样率没有设置正确,av_dump_format 获取视频信息的时候可以看到aac的详细信息。 void Widget::adts_header(char *szAdtsHeader, int dataLen) …...
Apache Doris 2025 Roadmap:构建 GenAI 时代实时高效统一的数据底座
在全球 290 位开发者的协作下,Apache Doris 在 2024 年完成了 7000 次代码提交,并发布了 22 个版本,实现在实时分析、湖仓一体和半结构化数据分析等核心场景的技术突破及创新。 2025 年,Apache Doris 社区将秉承“以场景驱动创新…...
HTTP数据传输的几个关键字Header
本文着重针对http在传输数据时的几种封装方式进行描述。 1. Content-Type(描述body内容类型以及字符编码) HTTP的Content-Type用于定义数据传输的媒体类型(MIME类型),主要分为以下几类: (一)、基础文本类型 text/plain …...
二极管正负极区分
二极管正负极区分 二极管是一种具有单向导电性的半导体器件,正确区分正负极对于其使用非常重要。以下是几种常见的二极管正负极区分方法: 1. 外观标识 有标记的二极管 色环或色点:许多二极管在表面会有一个色环或色点,这个标记…...
CyclicBarrier、Semaphore、CountDownLatch的区别,适用场景
CyclicBarrier、Semaphore 和 CountDownLatch 是 Java 并发包中用于线程协作的工具类,它们虽然都与线程同步相关,但设计目的和使用场景有显著差异。以下是它们的核心区别和典型应用场景: 1. CountDownLatch 核心机制 一次性计数器…...
【c++深入系列】:类与对象详解(中)
🔥 本文专栏:c 🌸作者主页:努力努力再努力wz 💪 今日博客励志语录: 不是因为看到希望才坚持,而是坚持了才能看到希望 那么上一篇博客我讲解了什么是类和对象以及类和对象是怎么定义的࿰…...
解锁界面设计密码,打造极致用户体验
界面设计是对软件、网站、移动应用等产品的用户界面进行设计的过程,旨在为用户提供美观、易用、高效的交互体验。以下是关于界面设计的一些主要方面: 一、设计原则 用户中心原则:以用户为中心,了解用户的需求、期望、行为和习惯…...
用Python和Pygame创造粉色粒子爱心:3D渲染的艺术
引言 在计算机图形学中,3D效果的2D渲染是一个迷人的领域。今天,我将分享一个使用Python和Pygame库创建的粉色粒子爱心效果。这个项目不仅视觉效果惊艳,而且代码简洁易懂,非常适合图形编程初学者学习3D渲染的基础概念。 项目概述…...
汽车 HMI 设计的发展趋势与设计要点
一、汽车HMI设计的发展历程与现状 汽车人机交互界面(HMI)设计经历了从简单到复杂、从单一到多元的演变过程。2012年以前,汽车HMI主要依赖物理按键进行操作,交互方式较为单一。随着特斯拉Model S的推出,触控屏逐渐成为…...
《AI大模型应知应会100篇》第56篇:LangChain快速入门与应用示例
第56篇:LangChain快速入门与应用示例 前言 最近最火的肯定非Manus和OpenManus莫属,因为与传统AI工具仅提供信息不同,Manus能完成端到端的任务闭环。例如用户发送“筛选本月抖音爆款视频”,它会自动完成: 爬取平台数据…...
vue-office 支持预览多种文件(docx、excel、pdf、pptx)预览的vue组件库
官网地址:https://github.com/501351981/vue-office 支持多种文件(docx、excel、pdf、pptx)预览的vue组件库,支持vue2/3。也支持非Vue框架的预览。 1.在线预览word文件(以及本地上传预览) 1.1:下载组件库 npm inst…...
Java 大视界 -- Java 大数据在智能农业无人机植保作业路径规划与药效评估中的应用(165)
💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…...
哈希表系列一>两数之和
目录 题目:方法:暴力代码:优化后代码: 题目: 链接: link 方法: 暴力代码: public int[] twoSum(int[] nums, int target) {解法一:暴力解法:int n nums.length;for(int…...
【SPP】深入解析蓝牙 L2CAP 协议在SPP中的互操作性要求
在蓝牙协议体系中,L2CAP(Logical Link Control and Adaptation Protocol)作为基带协议与高层协议之间的桥梁,承担着数据分帧、协议复用、QoS协商等核心功能。当涉及串行端口通信时,L2CAP的规范实现直接决定了设备间数据传输的可靠性、效率及兼容性。本文基于《Serial Port…...
CAD插件实现:自动递增编号(前缀、后缀、位数等)——CADc#实现
cad中大量输入一定格式的递增编号时,可用插件实现,效果如下: ①本插件可指定数字位数、起始号码、加前缀、后缀、文字颜色等(字体样式和文字所在图层为cad当前图层和当前字体样式)。 ②插件采用Jig方式,即…...
Spring | Spring、Spring MVC 和 Spring Boot 的区别
关注:CodingTechWork 引言 在 Java 开发领域,Spring、Spring MVC 和 Spring Boot 是三个经常被提及的概念。它们之间既有联系又有区别,对于初学者来说可能会感到困惑。本文将详细介绍它们的区别,并通过示例代码帮助读者更好地理解…...
观察者模式在Java微服务间的使用
一.、使用RabbitMQ来实现 (1) 生产者(订单微服务) import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.stereotype.Service;Service public class OrderService {private final RabbitTemplate rabbitTemplate;…...
C语言--回文字符串
输入:字符串,判断是否是回文字符串,例如abcba输出Yes 输出:是否 代码 思路:使用两个指针分别指向头和尾,依次对比第一个元素和最后一个元素,第二个和倒数第二个元素,如果遇到不相同…...
【云计算物理网络】数据中心网络架构设计
云计算的物理基础:数据中心网络架构设计 一、技术背景:从“三层架构”到“云原生网络”二、技术特点:云数据中心网络的四大支柱三、技术细节:CLOS架构的实现挑战四、未来方向:从“连接设备”到“感知服务”结语&#x…...
Coco-AI 支持嵌入,让你的网站拥有 AI 搜索力
在之前的实践中,我们已经成功地把 Hexo、Hugo 等静态博客和 Coco-AI 检索系统打通了:只要完成向量化索引,就可以通过客户端问答界面实现基于内容的智能检索。 这一层已经很好用了,但总觉得少了点什么—— 比如用户还得专门打开一…...
批处理脚本的主要解析规则
批处理脚本的主要解析规则 批处理脚本(Batch files)有一套独特的解析规则,这些规则在很多情况下不太直观,但了解它们对于编写可靠的脚本至关重要。以下是最重要的一些规则: 1. 变量扩展规则 标准变量扩展 (%变量%) 解析时扩展:…...
TRDI 公司的RiverPro 和 RioPro ADCP 用户指南
TRDI 公司 RiverPro 和 RioPro ADCP 用户指南 简介第一章 - 概述第二章 - 安装第三章 - 采集数据第四章 - 维护第五章 - 测试RIVERPRO/RIOPRO第六章 - 故障排除第七章 - 将系统返回TRDI进行维修第八章 - 规格第九章 - 命令第十章 - 输出数据格式附录A-合规通知首次完整翻译《Ri…...
