当前位置: 首页 > article >正文

XV6操作系统:proc机制学习笔记

梳理struct proc的结构如下通过分析一个父子进程的程序关系来理解process的工作原理#include stdio.h #include stdlib.h #include unistd.h #include fcntl.h #include sys/wait.h #include string.h int main() { int fd; char buffer[64]; const char *msg Hello!\n; pid_t pid fork(); if (pid 0) { exit(1); } else if (pid 0) { fd open(test.txt, O_WRONLY | O_CREAT | O_TRUNC, 0644); write(fd, msg, strlen(msg)); close(fd); exit(0); } else { wait(NULL); fd open(test.txt, O_RDONLY); read(fd, buffer, sizeof(buffer)); printf(父进程读取到子进程写下的: %s, buffer); close(fd); } return 0; }1.阶段一 fork... pid_t pid fork(); ...1.1 单核CPU情形一个父进程fork出子进程pid 0的过程首先父进程需要在内存中遍历进程表找到UNUSED的闲置进程。接下来为子进程复制父进程的各种资源openfile、cwd分配属于它自己的pagetable页表、trapframe。再把state从USED设置为RUNNABLE进入调度器就绪队列。调度器scheduler()一直在寻找RUNNABLE的进程通过上下文切换内存地址和寄存器的存储值指的是struct context状态state变为RUNNING。1.2 多核CPU情形单核CPU是不需要考虑多核的冲突问题的实际上要是另外的CPU闲着就有很大概率会来插手可能会导致proc槽位浪费亦或者程序冲突。这就是spinlock的价值。CPU0会首先调用 acquire(p-lock) 获取自旋锁, p是我们当前process的结构体名。此时如果其他 CPU 核心想要动这个 proc 结构体就会进入spin原地打转直到 CPU0 把进程状态安全地改写为 USED 并释放锁。仔细来看spinlock这里有一个误区需要辩解。proc结构体中有spinlock结构体spinlock结构体中有cpu结构体cpu结构体中又有proc结构体。那不是内存要被无限套娃撑爆。然而spinlock结构体中保存的只是指向cpu结构体的指针cpu结构体中也是这样的。struct spinlock { uint locked; // Is the lock held? char *name; // Name of lock. struct cpu *cpu; // The cpu holding the lock. }; struct cpu { struct proc *proc; // The process running on this cpu, or null. struct context context; // swtch() here to enter scheduler(). int noff; // Depth of push_off() nesting. int intena; // Were interrupts enabled before push_off()? }; struct proc { struct spinlock lock; enum procstate state; // Process state void *chan; // If non-zero, sleeping on chan int killed; // If non-zero, have been killed int xstate; // Exit status to be returned to parents wait int pid; // Process ID struct proc *parent; // Parent process uint64 kstack; // Virtual address of kernel stack uint64 sz; // Size of process memory (bytes) pagetable_t pagetable; // User page table struct trapframe *trapframe; // data page for trampoline.S struct context context; // swtch() here to run process struct file *ofile[NOFILE]; // Open files struct inode *cwd; // Current directory char name[16]; // Process name (debugging) };这样的三角设计的设计导致1. proc 包含 lock锁保护进程状态保护进程内部成员变量2. lock 指向 cpu防止其他CPU篡改数据3. cpu 指向 proc内核随时能知道当前在跑哪个进程2.阶段二 trapframe子进程开始运行并调用了 open 和 write() 系统调用。... else if (pid 0) { fd open(test.txt, O_WRONLY | O_CREAT | O_TRUNC, 0644); write(fd, msg, strlen(msg)); ...2.1 用户态切换内核态trapframe.Suser程序没有权限直接操作硬盘。调用 open() 或者 write() 时RISC-V 处理器会执行 ecall 指令硬件立刻提高特权级通过蹦床内核态虚拟内存页表和用户态虚拟内存页表完全相同的地方这样进行转换时具有绝对地址才不会出问题跳入kernel态。以下为一次write系统调用示意图#include ritrampoline.Sscv.h #include memlayout.h .section trampsec .globl trampoline .globl usertrap trampoline: .aglign 4 .globl uservec .globl userret uservec: csrw sscratch, a0 # a0写入sscratch,用户态数据暂存 li a0, TRAPFRAME # 用trapframe替代a0 # save the user registers in TRAPFRAME sd ra, 40(a0) sd sp, 48(a0) sd gp, 56(a0) sd tp, 64(a0) sd t0, 72(a0) sd t1, 80(a0) sd t2, 88(a0) sd s0, 96(a0) sd s1, 104(a0) sd a1, 120(a0) sd a2, 128(a0) sd a3, 136(a0) sd a4, 144(a0) sd a5, 152(a0) sd a6, 160(a0) sd a7, 168(a0) sd s2, 176(a0) sd s3, 184(a0) sd s4, 192(a0) sd s5, 200(a0) sd s6, 208(a0) sd s7, 216(a0) sd s8, 224(a0) sd s9, 232(a0) sd s10, 240(a0) sd s11, 248(a0) sd t3, 256(a0) sd t4, 264(a0) sd t5, 272(a0) sd t6, 280(a0) csrr t0, sscratch sd t0, 112(a0) ld sp, 8(a0) ld tp, 32(a0) ld t0, 16(a0) ld t1, 0(a0) sfence.vma zero, zero //刷新TLB csrw satp, t1 // sfence.vma zero, zero // jalr t0 //JUMP TO t0(trap.c) userret: sfence.vma zero, zero csrw satp, a0 sfence.vma zero, zero li a0, TRAPFRAME # restore all but a0 from TRAPFRAME ld ra, 40(a0) ld sp, 48(a0) ld gp, 56(a0) ld tp, 64(a0) ld t0, 72(a0) ld t1, 80(a0) ld t2, 88(a0) ld s0, 96(a0) ld s1, 104(a0) ld a1, 120(a0) ld a2, 128(a0) ld a3, 136(a0) ld a4, 144(a0) ld a5, 152(a0) ld a6, 160(a0) ld a7, 168(a0) ld s2, 176(a0) ld s3, 184(a0) ld s4, 192(a0) ld s5, 200(a0) ld s6, 208(a0) ld s7, 216(a0) ld s8, 224(a0) ld s9, 232(a0) ld s10, 240(a0) ld s11, 248(a0) ld t3, 256(a0) ld t4, 264(a0) ld t5, 272(a0) ld t6, 280(a0) # restore user a0 ld a0, 112(a0) # return to user mode and user pc. # usertrapret() set up sstatus and sepc. sret2.2 保存现场uservec进入内核态的第一件事就是把子进程此刻用户态的所有寄存器如 a0 存放的文件路径指针a1 存放的打开模式等一股脑地保存到 p-trapframe陷入帧中。struct trapframe { /* 0 */ uint64 kernel_satp; // kernel page table /* 8 */ uint64 kernel_sp; // top of processs kernel stack /* 16 */ uint64 kernel_trap; // usertrap() /* 24 */ uint64 epc; // saved user program counter /* 32 */ uint64 kernel_hartid; // saved kernel tp /* 40 */ uint64 ra; /* 48 */ uint64 sp; /* 56 */ uint64 gp; /* 64 */ uint64 tp; /* 72 */ uint64 t0; /* 80 */ uint64 t1; /* 88 */ uint64 t2; /* 96 */ uint64 s0; /* 104 */ uint64 s1; /* 112 */ uint64 a0; /* 120 */ uint64 a1; /* 128 */ uint64 a2; /* 136 */ uint64 a3; /* 144 */ uint64 a4; /* 152 */ uint64 a5; /* 160 */ uint64 a6; /* 168 */ uint64 a7; /* 176 */ uint64 s2; /* 184 */ uint64 s3; /* 192 */ uint64 s4; /* 200 */ uint64 s5; /* 208 */ uint64 s6; /* 216 */ uint64 s7; /* 224 */ uint64 s8; /* 232 */ uint64 s9; /* 240 */ uint64 s10; /* 248 */ uint64 s11; /* 256 */ uint64 t3; /* 264 */ uint64 t4; /* 272 */ uint64 t5; /* 280 */ uint64 t6; };2.3 恢复现场userret当内核态子进程在硬盘上建好文件后会把文件描述符比如 3写进 trapframe-a0 中。随后执行 sret 指令退回用户态子进程醒来仿佛什么都没发生只是拿到了返回值 3。3.阶段三 打开文件表ofile当程序执行 open 时操作系统在底层构建了一条三级跳的映射链条这种设计实现了用户态与物理硬件的绝对隔离。文件描述符fd程序拿到的是一个简单的整数 fd。这个 fd 仅仅是该程序专属的 ofile 数组的下标。程序只能操作这个数字无法越权触碰内核的内存指针以此保证系统安全。动态运行时的 struct file内核通过 ofile 数组的下标找到对应的 struct file。设置这一层是因为同一个文件可以被并发访问。struct file 独立记录了本次 open 操作的专属上下文例如当前拥有的是只读还是读写权限以及具体的 off 偏移量。物理文件真身 inodestruct file 内部的 ip 指针最终指向内存中唯一的 inode。inode 包含了物理文件在底层磁盘上的真实扇区分布信息与元数据。4.阶段四 inode表、sleeplock当程序调用 write 准备将数据刷入磁盘时必须面对 CPU 高速运算与外设低速运转之间绝大的速度差。获取独占写入权内核找到目标 inode 后程序必须申请该 inode 绑定的 sleeplock。如果此时有其他任务正在写这个文件当前程序绝对不能使用 spinlock。因为 spinlock 会导致 CPU 空转在漫长的磁盘 I/O 期间空转是对算力的极大浪费。主动让出 CPU 核心拿不到 sleeplock 的程序会被内核变更为 SLEEPING 状态同时内核将目标 inode 的内存地址记录在该程序的 chan 字段中以此标记它具体在等待哪把锁。随后程序调用 swtch 触发上下文切换让出当前 CPU 核心去执行其他处于 RUNNABLE 状态的任务。详细实现见kernel/sleeplock.c硬件中断唤醒外设完成写入动作后会向 CPU 触发硬件中断。内核的中断处理例程随即介入检索所有处于 SLEEPING 状态且 chan 字段匹配该 inode 地址的程序将它们的状态回写为 RUNNABLE。调度器随后会重新安排其执行。5.阶段五 清理资源... close(fd); exit(0); } else { wait(NULL); ...子进程调用 exit()内核再次获取 p-lock自旋锁遍历 p-ofile 数组将所有打开的 struct file 的引用计数减一如果减到0就清理 inode。最后把状态改为 ZOMBIE。父进程调用 wait()由于父子并发父进程可能早就在 wait() 里等待了。发现子进程没死父进程会通过 sleep() 机制主动交出 CPU底层依赖 p-lock 保证检查状态和睡眠的原子性。当子进程变成 ZOMBIE 后唤醒父进程父进程终于读取子进程的残存状态并将其进程表项彻底抹平为 UNUSED。

相关文章:

XV6操作系统:proc机制学习笔记

梳理struct proc的结构如下&#xff0c;通过分析一个父子进程的程序关系来理解process的工作原理&#xff1a;#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/wait.h> #include <string.h>…...

Win11系统虚拟化性能优化指南:VBS关闭与配置全解析

1. 为什么需要关闭VBS虚拟化功能&#xff1f; 很多朋友升级到Win11后会发现电脑变卡了&#xff0c;尤其是玩游戏或者运行大型软件时帧数明显下降。这很可能是因为系统默认开启了VBS&#xff08;Virtualization-Based Security&#xff09;虚拟化安全功能。我去年刚换新电脑时就…...

DDT4All汽车诊断工具:从零开始掌握专业级ECU调参与故障诊断

DDT4All汽车诊断工具&#xff1a;从零开始掌握专业级ECU调参与故障诊断 【免费下载链接】ddt4all OBD tool 项目地址: https://gitcode.com/gh_mirrors/dd/ddt4all 想要深入了解汽车电子系统却不知从何入手&#xff1f;面对复杂的OBD-II诊断工具感到困惑&#xff1f;DDT…...

EmojiOne彩色表情字体:为你的项目注入生动表情的终极指南

EmojiOne彩色表情字体&#xff1a;为你的项目注入生动表情的终极指南 【免费下载链接】emojione-color OpenType-SVG font of EmojiOne 2.3 项目地址: https://gitcode.com/gh_mirrors/em/emojione-color EmojiOne彩色表情字体是一款基于OpenType-SVG格式的开源彩色字体…...

Adafruit GFX Library:嵌入式图形开发的终极开源解决方案

Adafruit GFX Library&#xff1a;嵌入式图形开发的终极开源解决方案 【免费下载链接】Adafruit-GFX-Library Adafruit GFX graphics core Arduino library, this is the core class that all our other graphics libraries derive from 项目地址: https://gitcode.com/gh_mi…...

[图文超超超详细教程] ~Cursor~ 保姆级下载安装以及API配置接入使用教程!!!

Cursor 是一款以 AI 为核心的智能代码编辑器&#xff0c;可以把它理解为“更懂项目上下文的 VS Code”。提供智能代码补全、代码生成、代码修改、代码搜索和代码解释等。与其他工具不同&#xff0c;Cursor 将AI 辅助编码直接融入到 编辑器的核心功能中&#xff0c;你可以用自然…...

LoRA微调实战:用低秩适配技术快速优化你的NLP模型(附代码)

LoRA微调实战&#xff1a;用低秩适配技术快速优化你的NLP模型&#xff08;附代码&#xff09; 当你在Hugging Face平台上尝试微调一个拥有数十亿参数的大语言模型时&#xff0c;是否曾被GPU内存不足的报错打断过&#xff1f;或者看着训练日志中缓慢下降的损失曲线&#xff0c;计…...

六自由度系统弱、强非线性振动参数辨识研究(Python代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

35个专业脚本如何彻底重构Adobe Illustrator工作流

35个专业脚本如何彻底重构Adobe Illustrator工作流 【免费下载链接】illustrator-scripts Adobe Illustrator scripts 项目地址: https://gitcode.com/gh_mirrors/il/illustrator-scripts Adobe Illustrator作为矢量设计的行业标准工具&#xff0c;其强大的功能背后隐藏…...

Claude Code 行为指南

Claude Code 行为指南 背景与问题 Andrej Karpathy&#xff08;前 OpenAI 创始成员、前 Tesla AI 总监&#xff09;在社交媒体上分享了他对 LLM 编码行为的观察&#xff1a;“模型会替你做出错误的假设并直接执行&#xff0c;而不去验证。它们不管理自己的困惑&#xff0c;不寻…...

如何轻松提升开发效率:智能编程助手的实战体验

如何轻松提升开发效率&#xff1a;智能编程助手的实战体验 【免费下载链接】cursor-free-vip [Support 0.45]&#xff08;Multi Language 多语言&#xff09;自动注册 Cursor Ai &#xff0c;自动重置机器ID &#xff0c; 免费升级使用Pro 功能: Youve reached your trial requ…...

二分查找力扣题(leetcode)鼗

一、语言特性&#xff1a;Java 26 与模式匹配进化 1.1 Java 26 语言级别支持 IDEA 2026.1 EAP 最引人注目的变化之一&#xff0c;就是新增 Java 26 语言级别支持。这意味着开发者可以提前体验和测试即将在 JDK 26 中正式发布的语言特性。 其中最重要的变化是对 JEP 530 的全面支…...

PUBG雷达系统:3分钟搭建您的专属战场指挥中心

PUBG雷达系统&#xff1a;3分钟搭建您的专属战场指挥中心 【免费下载链接】PUBG-maphack-map this is a working copy online-map from jussihi/PUBG-map-hack, use nodejs webserver instead of firebase. 项目地址: https://gitcode.com/gh_mirrors/pu/PUBG-maphack-map …...

高效日志分析利器:glogg跨平台日志查看器深度解析

高效日志分析利器&#xff1a;glogg跨平台日志查看器深度解析 【免费下载链接】glogg A fast, advanced log explorer. 项目地址: https://gitcode.com/gh_mirrors/gl/glogg 在复杂的软件开发与系统运维过程中&#xff0c;日志分析是每个技术人员必须面对的挑战。面对庞…...

专业CAD数据处理指南:如何高效使用开源DWG转换工具LibreDWG

专业CAD数据处理指南&#xff1a;如何高效使用开源DWG转换工具LibreDWG 【免费下载链接】libredwg Official mirror of libredwg. With CI hooks and nightly releases. PRs ok 项目地址: https://gitcode.com/gh_mirrors/li/libredwg LibreDWG是一款强大的开源CAD文件处…...

把 BAPI、RAP 和 Clean Core 接到一条线上,聊透 BAPI 型 RAP Business Object 的可扩展性

在很多真实项目里,最麻烦的场景从来不是 新建一个 RAP BO,而是手里已经有一套跑了很多年的 BAPI,业务规则、消息处理、权限控制、编号逻辑、过账动作,全都压在里面。业务部门又不想推倒重来,只是希望把它接到 SAP Fiori、OData、RAP 这条现代开发链路上,同时还得满足 Cle…...

Agent-Sandbox UI 上线,来看看有哪些的功能是你经常使用的?汉

一、简化查询 1. 先看一下查询的例子 /// /// 账户获取服务 /// /// /// public class AccountGetService(AccountTable table, IShadowBuilder builder) {private readonly SqlSource _source new(builder.DataSource);private readonly IParamQuery _accountQuery build…...

行业必备!AI教材编写工具,快速出稿且保持低查重率

AI教材创作工具介绍 谁没有在写教材的时候感到无从下手&#xff1f;面对一张空白的文档&#xff0c;有时常常不知道从何起步&#xff0c;思考着到底先讲课本的概念还是先用实例来说明&#xff1f;在章节划分上&#xff0c;纠结于是按逻辑关系来还是按课时来安排&#xff1f;不…...

避坑指南:JavaCV中FFmpegFrameGrabber处理音频流时,采样格式转换的那些‘坑’

JavaCV音频处理实战&#xff1a;FFmpegFrameGrabber采样格式转换的深度解析 1. 音频采样格式的底层逻辑与核心挑战 在多媒体处理领域&#xff0c;音频采样格式的转换是一个看似简单实则暗藏玄机的技术点。当我们使用JavaCV的FFmpegFrameGrabber处理音频流时&#xff0c;经常会遇…...

Mininet实战指南:从基础命令到高级网络模拟

1. Mininet入门&#xff1a;基础命令与核心概念 第一次接触Mininet时&#xff0c;我完全被它模拟真实网络的能力震撼到了。这个轻量级网络仿真工具能在单台Linux机器上创建包含主机、交换机、控制器和链路的虚拟网络&#xff0c;特别适合做SDN开发和网络协议测试。记得当时为了…...

别再瞎选 B2B2C 开源商城了!实测对比 Tigshop /ShopXO/Likeshop/Niushop/BeikeShop

作为一名折腾过不少开源电商项目的程序员&#xff0c;我深知一个道理&#xff1a;选择电商系统这事儿&#xff0c;选对了皆大欢喜&#xff0c;选错了就是无底洞。技术栈老旧的、文档缺东少西的、号称“免费”结果到处埋坑的&#xff0c;这些年我都踩过一遍。最近因为项目需要调…...

手把手复现DiffusionDet:基于PyTorch从论文到代码的完整实践指南(含COCO数据集)

从零实现DiffusionDet&#xff1a;基于PyTorch的扩散式目标检测实战指南 1. 环境配置与工具准备 在开始DiffusionDet项目之前&#xff0c;确保你的开发环境满足以下要求。我们将使用PyTorch作为主要框架&#xff0c;配合CUDA加速计算。 硬件建议&#xff1a; GPU&#xff1…...

如何让AI替你操作浏览器?Midscene Chrome扩展的智能自动化革命

如何让AI替你操作浏览器&#xff1f;Midscene Chrome扩展的智能自动化革命 【免费下载链接】midscene AI-powered, vision-driven UI automation for every platform. 项目地址: https://gitcode.com/GitHub_Trending/mid/midscene 你是否厌倦了每天重复点击、填写、提交…...

Linux下Python连接MySQL报错‘libstdc++.so.6: cannot allocate memory in static TLS block’的保姆级修复指南

Linux下Python连接MySQL报错‘libstdc.so.6: cannot allocate memory in static TLS block’的保姆级修复指南 最近在Linux服务器上部署Python应用时&#xff0c;不少开发者遇到了一个令人头疼的错误&#xff1a;当尝试通过mysqlclient连接MySQL数据库时&#xff0c;系统抛出li…...

Pentaho Kettle数据血缘追踪架构深度解析:构建企业级数据治理核心能力

Pentaho Kettle数据血缘追踪架构深度解析&#xff1a;构建企业级数据治理核心能力 【免费下载链接】pentaho-kettle Pentaho Data Integration ( ETL ) a.k.a Kettle 项目地址: https://gitcode.com/gh_mirrors/pe/pentaho-kettle 在复杂的企业数据集成场景中&#xff0…...

文墨共鸣GPU算力优化:StructBERT模型显存占用降低40%的部署技巧

文墨共鸣GPU算力优化&#xff1a;StructBERT模型显存占用降低40%的部署技巧 1. 项目背景与挑战 文墨共鸣是一个将深度学习算法与传统水墨美学相结合的语义相似度分析系统&#xff0c;基于阿里达摩院的StructBERT大模型。在实际部署中&#xff0c;我们发现原始模型存在明显的显…...

lerobot so101机械臂锁死紧急救援!删除校准文件三步重生术

问题在调试校准lerobot so101机械臂&#xff0c;第二遍执行校准机械臂的命令lerobot-calibrate时&#xff0c;整个机械臂锁死&#xff0c;无法手动调整舵机&#xff1a; lerobot-calibrate \--robot.typeso101_follower \--robot.port/dev/ttyACM0 \--robot.idmy_awesome_follo…...

Qwen3-0.6B-FP8部署教程:在国产昇腾910B平台适配vLLM(需修改backend)可行性分析

Qwen3-0.6B-FP8部署教程&#xff1a;在国产昇腾910B平台适配vLLM&#xff08;需修改backend&#xff09;可行性分析 1. 引言&#xff1a;当轻量级大模型遇上国产算力 最近&#xff0c;很多朋友都在问一个问题&#xff1a;现在大模型动辄几十上百亿参数&#xff0c;部署起来对…...

JAVA集合—ArrayList源码深度解析

前言ArrayList 可能是每个 Java 开发者最早接触、使用最频繁的集合类。但你是否真正理解过它的内部实现&#xff1f;比如&#xff1a;扩容机制是什么&#xff1f;为什么扩容是 1.5 倍&#xff1f;add() 和 remove() 的时间复杂度分别是多少&#xff1f;本文基于 JDK 21 源码&am…...

R语言建模总“跑不通”?3步定位环境污染源:从.Rprofile到Sys.getenv()的深度诊断手册

第一章&#xff1a;R语言建模环境“跑不通”现象的典型表现与危害R语言建模环境中的“跑不通”并非指语法错误导致的立即报错&#xff0c;而是一类隐蔽性强、复现性差、定位困难的系统性失配问题。这类问题常在跨平台迁移、版本升级或协作开发中集中爆发&#xff0c;表面看似代…...