一、认识进程和线程,在Linux系统下查看系统中各进程的编号pid并终止一个进程pid
1.进程和线程
进程:操作系统分配资源(如内存、CPU时间片)的基本单位。每个进程有独立的内存空间,进程间通信需要较复杂的机制(如管道、信号、共享内存等)。
线程:进程内的执行单元,共享同一进程的资源(如内存、文件句柄)。线程间通信更高效,但需注意同步问题(如竞态条件)。
2.用 ps -a 命令查看系统中各进程的编号pid且用 kill 命令终止一个进程pid
命令如下
#在后台运行一个 sleep 120 秒的进程
sleep 120 &#查看进程的PID
ps -a
输出示例:PID TTY TIME CMD1234 pts/0 00:00:00 bash5678 pts/1 00:00:00 ps终止进程
kill PID(如kill 1234)
操作结果:
二、Linux的“虚拟内存管理”与stm32中的 真实物理内存(内存映射)的区别
1.Linux虚拟内存管理
虚拟内存是操作系统对物理内存的抽象层,通过 硬件(MMU) 和 软件(内核页表) 协作实现。
特性 | 说明 |
---|---|
虚拟地址空间 | 每个进程拥有独立的虚拟地址空间(如0x0000~0xFFFF),与物理内存解耦。 |
分页机制 | 内存按固定大小(如4KB)分页,通过页表(Page Table)映射虚拟页到物理页或磁盘(Swap)。 |
内存保护 | 页表项标记内存权限(读/写/执行),防止非法访问(如代码区只读)。 |
按需分配 | 物理内存仅在实际访问时分配(触发缺页中断),避免浪费。 |
共享内存 | 多个进程可共享同一物理页(如动态库代码)。 |
Swap机制 | 将不活跃的内存页换出到磁盘,缓解物理内存不足。 |
示例:
- 进程A访问虚拟地址
0x1234
→ MMU查页表 → 映射到物理地址0x5678
。 - 若目标页不在物理内存中,触发缺页中断 → 内核从磁盘加载该页。
2.STM32物理内存映射
TM32等微控制器无MMU,直接通过物理地址访问内存和外设,其设计目标是实时性和确定性:
特性 | 说明 |
---|---|
物理地址直接访问 | 所有代码直接操作物理地址(如0x20000000 为SRAM起始地址)。 |
内存与外设统一编址 | 外设寄存器通过特定地址访问(如0x40000000 为GPIOA寄存器地址)。 |
静态内存分配 | 内存布局在编译时确定(通过链接脚本),无动态分页或交换机制。 |
无内存保护 | 所有代码均可访问任意物理地址,易因错误操作导致系统崩溃。 |
确定性延迟 | 无地址转换开销,访问外设和内存的时间可精确计算,适合实时系统。 |
示例:
操作STM32的GPIO:
volatile uint32_t *GPIOA = (uint32_t*)0x40020000; // 直接访问GPIOA寄存器地址
*GPIOA |= 0x01; // 设置PA0引脚为高电平
3. 关键区别对比
维度 | Linux虚拟内存 | STM32物理内存 |
---|---|---|
地址空间 | 虚拟地址隔离(进程安全) | 直接物理地址(无隔离) |
硬件依赖 | 依赖MMU实现地址转换 | 无MMU,直接访问物理地址 |
内存分配 | 动态分页,按需分配 | 静态分配,编译时固定 |
内存保护 | 通过页表权限实现(读/写/执行) | 无保护,代码可任意修改内存或外设 |
实时性 | 因地址转换和缺页中断导致延迟不确定 | 访问延迟确定,适合实时控制 |
应用场景 | 通用多任务系统(如服务器、PC) | 资源受限的嵌入式实时系统(如电机控制、传感器) |
4. 注意事项
-
在Linux中:
- 用户程序通过
malloc
申请的是虚拟内存,实际物理内存分配由内核管理。 - 直接访问物理地址需通过
/dev/mem
或内存映射(mmap
),且需要root权限。
- 用户程序通过
-
在STM32中:
- 需手动管理内存,避免溢出(如栈、堆大小需在链接脚本中明确定义)。
- 操作外设时需严格遵循寄存器地址和时序,错误写入可能导致硬件故障。
总结:Linux虚拟内存是抽象层,解决多任务安全与资源扩展问题;STM32物理内存映射是直接控制,满足实时性和硬件效率需求。两者适用于截然不同的场景,理解其差异是开发跨平台系统的关键。
三、Linux系统调用函数 fork()、wait()、exec() 等的含义和调用方法
1.用xterminal(或者putty等)远程登录自己阿里云服务器Ubuntu系统的账号,在home目录下创建一个子目录,然后使用vi编辑一个c代码,gcc编译,实现一个系统调用函数的例子
下图为整个命令流程:
c文件起名为fork_exec_wait.c,代码如下(此代码是deepseek写的):
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>int main() {pid_t pid = fork(); // 创建子进程if (pid < 0) {fprintf(stderr, "Fork failed\n");return 1;} else if (pid == 0) {// 子进程执行ls -l命令execlp("ls", "ls", "-l", NULL);perror("exec failed"); // 若exec失败,输出错误return 1;} else {// 父进程等待子进程结束wait(NULL);printf("子进程执行完毕。\n");}return 0;
}
编辑好代码后在下方命令行输入:wq+Enter(一定要Enter!),然后点击发送就退出去了
2.在树莓派中创建账号,在该账号+home目录下,完成同样的操作
PS:一定要让树莓派跟你的电脑都连你的手机热点!!!
打开putty连接树莓派(关于树莓派可以看我另一个博客)无显示器安装访问树莓派3B+_如何在没用显示器的情况下给树莓派安装系统-CSDN博客
(1)创建账号(过程如下,详细看上面链接的博客)
(2)授权新账号使用sudo(方便进行安装一些工具等操作)
指令解释如下:
//添加
sudo usermod -aG sudo cq # -a表示追加,-G指定组//检查
groups cq # 输出应包含 "sudo"
(3)切换账号并安装gcc(编译工具)
指令解释如下:
//切换用户
pi@raspberrypi:~ $ su - cq//sudo whoami # 测试sudo权限,返回 "root"
cq@raspberrypi:~ $ sudo whoami//安装gcc
cq@raspberrypi:~ $ sudo apt install gcc
结果如下:
(4)创建作业目录并编写代码
//创建目录
mkdir -p ~/work6 //进入目录
cd ~/syscall_practice # 使用nano编辑器(xterminal中用的vi)
nano fork_exec_wait.c
c文件代码(同xterminal中):
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>int main() {pid_t pid = fork();if (pid < 0) {fprintf(stderr, "Fork失败\n");return 1;} else if (pid == 0) {execlp("ls", "ls", "-l", NULL);perror("exec失败");return 1;} else {wait(NULL);printf("子进程执行完毕。\n");}return 0;
}
保存退出:Ctrl+O
→ 回车 → Ctrl+X
(nano编辑器操作)
(5)编译并运行
指令:
//编译
gcc fork_exec_wait.c -o demo //运行
./demo
结果:
四、总结
本次实验我了解了进程和线程,通过查找资料了解了Linux虚拟内存和STM32物理内存的区别,还通过Xterminal在阿里云服务器以及通过Putty在树莓派上完成了系统调用实践。学到了很多,偷偷吐槽一下,putty不能复制粘贴代码,挺难受的。