# 嵌入式基础学习|C语言——进程篇综合(含进阶)

news/2025/2/22 17:25:46

进程与多任务编程

进程的概念

进程是进行中的程序,即程序的一次执行过程。它包含了程序在内存中的代码、数据以及CPU的执行状态。进程是程序的实例,是操作系统进行资源分配和调度的基本单位。

程序:静态的代码文件,存储在硬盘上。
进程:动态的执行实体,加载到内存中运行。
示例:
当我们运行一个程序时,比如 ./a.out,操作系统会将程序加载到内存中,创建一个进程来执行它。每个进程都有独立的内存空间和资源。

为什么需要进程?

早期的计算机一次只能运行一个程序,随着CPU性能的提升,现代操作系统支持多任务处理,即同时运行多个进程。进程的概念使得操作系统能够有效地管理多个程序的并发执行。

并发:多个进程在同一时间段内交替执行。
并行:多个进程在同一时刻同时执行(需要多核CPU)。

进程的组成

进程由以下几部分组成:

代码段:存放程序的执行代码。
数据段:存放全局变量和静态变量。
堆:动态分配的内存区域。
栈:存放函数调用的局部变量和返回地址。
PCB(进程控制块):操作系统用于管理进程的数据结构,包含进程的PID、PPID、状态等信息。
示例:
使用 size ./a.out 命令可以查看进程的内存布局:

bash

$ size ./a.out
text data bss dec hex filename
1515 600 8 2123 84b ./a.out
text:代码段
data:已初始化的全局变量
bss:未初始化的全局变量

进程的状态

进程在执行过程中会处于不同的状态,常见的状态包括:

R(运行态):进程正在执行或等待CPU调度。
S(可中断睡眠态):进程等待某个事件完成(如I/O操作)。
D(不可中断睡眠态):进程等待不可中断的事件(如磁盘I/O)。
T(暂停态):进程被暂停执行。
Z(僵尸态):进程已终止,但父进程尚未回收其资源。
示例:
使用 ps -aux 命令可以查看进程的状态:

bash

$ ps -aux | grep a.out

进程管理命令

top:实时查看系统进程状态。
ps:查看当前进程信息。
pstree:以树状结构显示进程关系。
kill:向进程发送信号,终止进程。
示例:
终止进程:

bash

$ kill -9 5266

进程的创建与结束

在Linux下,进程的创建通过 fork() 系统调用实现。

fork():创建一个子进程,子进程是父进程的副本。
父进程返回子进程的PID。
子进程返回0。
示例:
创建子进程并打印信息:

代码示例

#include <stdio.h>
#include <unistd.h>

int main() {
pid_t pid = fork();
if (pid == 0) {
printf(“子进程: PID = %d\n”, getpid());
} else if (pid > 0) {
printf(“父进程: PID = %d, 子进程PID = %d\n”, getpid(), pid);
} else {
perror(“fork失败”);
}
return 0;
}
输出:

父进程: PID = 1234, 子进程PID = 1235
子进程: PID = 1235

进程间的关系

孤儿进程:父进程终止后,子进程由 init 进程收养。
僵尸进程:子进程终止后,父进程未回收其资源。
示例:
查看进程树:

bash

$ pstree -sp 1234

进程的应用场景

并发执行:通过创建多个子进程,实现并发处理任务。
执行不同程序:通过 fork() 和 exec() 函数族,子进程可以执行与父进程不同的程序。
示例:
使用 exec() 执行新程序:

c

#include <stdio.h>
#include <unistd.h>

int main() {
pid_t pid = fork();
if (pid == 0) {
execl("/bin/ls", “ls”, NULL);
} else if (pid > 0) {
printf(“父进程: PID = %d\n”, getpid());
} else {
perror(“fork失败”);
}
return 0;
}
输出:

父进程: PID = 1234
file1.txt file2.txt

进程间的数据独立性

父子进程拥有独立的内存空间,对数据的修改不会相互影响。

示例:
父子进程修改全局变量:

c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int global_var = 0;

int main() {
pid_t pid = fork();
if (pid == 0) {
global_var += 2;
printf(“子进程: global_var = %d\n”, global_var);
} else if (pid > 0) {
global_var += 1;
printf(“父进程: global_var = %d\n”, global_var);
} else {
perror(“fork失败”);
}
return 0;
}
输出:

父进程: global_var = 1
子进程: global_var = 2

总结

进程是操作系统进行资源分配和调度的基本单位,通过 fork() 系统调用可以创建子进程,实现并发执行。父子进程拥有独立的内存空间,数据修改不会相互影响。进程的状态和关系可以通过 ps、pstree 等命令查看,进程的终止可以通过 kill 命令实现。

拓展:
在多核CPU环境下,进程可以并行执行,进一步提升系统性能。此外,进程间通信(IPC)机制如管道、消息队列、共享内存等,可以实现进程间的数据交换和协作。

代码示例:
以下是一个简单的多进程并发处理任务的示例:

c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

void task(int id) {
printf(“任务 %d 开始执行\n”, id);
sleep(2); // 模拟任务执行时间
printf(“任务 %d 执行完成\n”, id);
}

int main() {
for (int i = 0; i < 3; i++) {
pid_t pid = fork();
if (pid == 0) {
task(i);
exit(0);
} else if (pid < 0) {
perror(“fork失败”);
exit(1);
}
}
for (int i = 0; i < 3; i++) {
wait(NULL); // 等待所有子进程结束
}
printf(“所有任务执行完成\n”);
return 0;
}
输出:
任务 0 开始执行
任务 1 开始执行
任务 2 开始执行
任务 0 执行完成
任务 1 执行完成
任务 2 执行完成
所有任务执行完成
通过 fork() 创建多个子进程,每个子进程执行不同的任务,父进程等待所有子进程结束后再继续执行。


http://www.niftyadmin.cn/n/5862575.html

相关文章

windwos与linux环境下Iperf3带宽测试工具的安装、使用

目录 一、前言 二、windows 2.1下载 2.2安装 2.3使用 2.3.1服务端 2.3.2客户端 2.3.3输出内容 1.客户端 2.服务端 2.4.相关命令 三、linux 3.1安装 3.2使用 1.服务端 2.客户端 3.输出内容 1.客户端 2.服务端 一、前言 在数字化浪潮下&#xff0c;网络性能…

聊聊istio服务网格

聊聊istio服务网格 微服务的缺点&#xff1a;istio介绍微服务改进前后istio与服务治理 istio与k8s的关系istio的整体架构如有需要收藏的看官&#xff0c;顺便也用发财的小手点点赞哈&#xff0c;如有错漏&#xff0c;也欢迎各位在评论区评论&#xff01; 微服务的缺点&#xff…

写大论文的word版本格式整理,实现自动生成目录、参考文献序号、公式序号、图表序号

前情提要&#xff1a;最近开始写大论文&#xff0c;发现由于内容很多导致用老方法一个一个改的话超级麻烦&#xff0c;需要批量自动化处理&#xff0c;尤其是序号&#xff0c;在不断有增添删减的情况时序号手动调整很慢也容易出错&#xff0c;所以搞一个格式总结&#xff0c;记…

前端开发常见问题与面试-02

1、vue的双向绑定原理是什么&#xff1f;里面的关键点在哪里&#xff1f; Vue的双向绑定原理是基于Object.defineProperty或者Proxy来实现的&#xff0c;其关键点在于数据劫持&#xff0c;即对数据的读取和修改进行拦截&#xff0c;在数据发生变化时自动更新视图 2、实现水平…

Infuse Pro for Mac v8.1 全能视频播放器 支持M、Intel芯片

Infuse Pro 是一款强大的 Mac 视频播放器。它可以一口通吃您所有的视频文件 - Infuse 将把您从繁琐的视频转换中解放出来&#xff0c;用极美的方式在您的 Mac 上观赏几乎所有视频的格式。Infuse 已适配 macOS 11 并添加更加强大的在线视频&#xff0c;Trakt 同步&#xff0c;Ai…

神经网络剪枝技术的重大突破:sGLP-IB与sTLP-IB

神经网络剪枝技术的重大突破:sGLP-IB与sTLP-IB 在人工智能飞速发展的今天,深度学习技术已经成为推动计算机视觉、自然语言处理等领域的核心力量。然而,随着模型规模的不断膨胀,如何在有限的计算资源和存储条件下高效部署这些复杂的神经网络模型,成为了研究者们亟待解决的…

C# 生成二维码隐藏ASCII码

在 C# 中生成二维码时&#xff0c;如果需要隐藏或过滤掉 ASCII 码中的控制字符或不可见字符&#xff0c;可以在生成二维码之前对输入文本进行处理。以下是完整的实现步骤和代码示例&#xff1a; 1. 过滤 ASCII 码中的控制字符 ASCII 码中&#xff0c;0 到 31 以及 127 是控制字…

postman并发测试某个接口

记录一下在postman中压测某一个接口。 1、新建一个collection&#xff1a; 在collection中创建一个get请求&#xff08;压测该接口&#xff09; 2、 并发请求collection&#xff1a; 双击该collection&#xff0c;点击run按钮 然后&#xff0c;设置并发&#xff1a; 查看结果…