ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

操作系统基础知识(总结向)

操作系统基础知识(总结向) 笔者写着篇文章是为了之后学习RTOS、linux内核裁剪、ROS等内容喜欢可以点个关注关注后续更新这篇文章部分截图节选自B站王道计算机教育仅供学习使用。文章目录0、操作系统概述四大特征内核系统调用操作系统开机引导WIN启动流程linux启动流程嵌入式Linux启动流程单片机启动流程1、进程调度---处理机管理进程与线程进程的状态进程间通信调度同步与互斥死锁信号量semaphore生产者与消费者多生产者与多消费者单生产者AB消费者读者与写者单写者 多读者 写优先多写者 多读者 写优先线程同步与互斥方式管程---封装好的类2、内存管理---存储器管理分配与回收连续分配内存管理单一连续分配固定分区分配动态分区分配非连续分配内存管理分页内存管理分段内存管理段页式内存管理内存扩充覆盖交换虚拟内存请求分页内存管理页面置换算法页面分配策略请求分段内存管理请求页段内存管理地址转换内存保护3、文件---文件管理文件系统层次结构文件系统布局硬盘中的布局物理格式化逻辑格式化内存中的布局文件调用过程文件逻辑结构---用户文件物理结构---OS顺序分配链接分配索引分配文件共享硬链接软连接虚拟文件系统文件挂载4、IO设备---设备管理IO软件的层次设备的分配与回收逻辑设备表LUTLogical Unit Table系统设备表SDTSystem Device Table)设备控制表DCTDevice Control Table)控制器控制表COCTController Control Table通道控制表CHCTChannel Control Table)假脱机技术---SPOOLing缓冲区---buffer---水库缓冲池0、操作系统概述四大特征并发—信号量共享虚拟—内存管理异步内核系统调用操作系统开机引导WIN启动流程#预启动 - 硬件初始化按下电源按钮电源开始稳定地向主板和其他组件供电。主板上的芯片组会向CPU发送一个复位信号。CPU脱离复位状态进入一个已知的初始状态。强制CPU从内存地址 0xFFFF0 开始执行指令。这个地址是硬编码在CPU内部的它指向了BIOS芯片ROM的入口点。BIOS开始执行POST程序。检查CPU、内存、显卡等是否正常工作。检测和初始化键盘、鼠标、硬盘、光驱等。BIOS读取用户设置如启动顺序并最终生成一份系统中所有硬件的清单。#启动引导设备 - 寻找引导扇区BIOS按照预设的启动顺序逐个尝试设备。BIOS找到硬盘后它会读取硬盘的第一个扇区0号扇区。这个扇区的大小是 512字节被称为主引导记录MBR。BIOS将这512字节的数据加载到内存的特定位置通常是 0x7C00。BIOS检查MBR的最后两个字节是否为魔数 0x55AA。如果不是则尝试列表中的下一个启动设备。#MBR与分区表主引导记录的前440字节是第一阶段引导加载程序的代码。控制权从BIOS移交到这里。主引导记录的中间部分是分区表它描述了硬盘上的分区情况。引导加载程序代码扫描分区表寻找活动分区又称主分区即安装了操作系统的分区。找到活动分区后引导加载程序会去读取这个活动分区的第一个扇区。这个扇区被称为分区引导记录PBR或引导扇区。#第二阶段引导加载程序分区引导记录包含了第二阶段引导加载程序的代码以及该分区的文件系统信息。控制权移交到分区引导记录代码。分区引导记录的512字节空间极其有限它的主要任务是去文件系统中查找并加载一个更强大的启动管理器文件。#操作系统选择与内核加载启动管理器被加载到内存并执行。启动管理器读取启动配置数据BCD Boot Configuration Data文件。BCD是一个数据库包含了所有启动配置信息比如安装了哪些操作系统、它们的内核在哪里。如果只有一个操作系统它会直接加载。如果有多个如Windows和Linux双系统启动管理器会显示一个启动菜单供用户选择。启动管理器会找到并加载 winload.exe。winload.exe 是操作系统的正式加载程序。此时控制权移交此处。winload.exe 加载Windows内核 ntoskrnl.exe。加载硬件抽象层 hal.dll。加载系统注册表配置单元和其他必要的启动驱动程序。CPU从16位的实模式切换到32位/64位的保护模式从而可以访问所有内存并执行现代操作系统的代码。#操作系统初始化ntoskrnl.exe 开始执行此时控制权移交至此。初始化核心系统组件、内存管理、进程调度等。内核启动 smss.exe。这是第一个用户模式进程它负责设置系统环境。启动子系统如Win32子系统。启动 csrss.exe 和winlogon.exe。winlogon.exe 启动显示登录界面。此时控制权移交至此。用户输入凭据后lsass.exe 进行身份验证。验证成功后winlogon.exe 启动 explorer.exe也就是我们看到的桌面外壳。此时操作系统启动完毕等待用户交互。同时系统还会在后台启动一系列服务和启动项。linux启动流程按下电源按钮电源开始稳定地向主板和其他组件供电。主板上的芯片组会向CPU发送一个复位信号。CPU脱离复位状态进入一个已知的初始状态。强制CPU从内存地址 0xFFFF0 开始执行指令。这个地址是硬编码在CPU内部的它指向了BIOS/UEFI 芯片ROM的入口点。BIOS/UEFI 开始执行POST程序。检查CPU、内存、显卡等是否正常工作。检测和初始化键盘、鼠标、硬盘、光驱等。BIOS/UEFI 读取用户设置如启动顺序。BIOS方式BIOS读取硬盘的 MBR。BIOS 读取 MBR前 512 字节。MBR 中包含 GRUB2 的 第一阶段代码 boot.img。boot.img 的空间极小它的唯一任务就是加载位于 MBR 之后、磁盘第一个扇区与第一个分区之间的 core.img。core.img 包含了基本的文件系统驱动使得 GRUB2 可以读取 /boot 分区中的文件。UEFI方式UEFI从 EFI 系统分区 查找 .efi 引导程序。EFI 固件直接从 ESP 分区加载 GRUB2 的 EFI 应用程序通常是 /EFI/ubuntu/grubx64.efi。这跳过了 MBR 和 core.img 的加载过程。core.img 或 grubx64.efi 会加载 /boot/grub 目录下的模块如文件系统模块、界面模块等。然后读取 /boot/grub/grub.cfg 配置文件。这个文件定义了启动菜单的样式、超时时间以及最重要的——可启动的操作系统列表。GRUB2 将 grub.cfg 中定义的菜单显示给用户。用户可以选择启动不同的 Linux 内核版本、进入恢复模式或者 chainload 其他系统如 Windows。当用户选择了一个菜单项后GRUB2 会从 /boot 目录加载对应的 Linux 内核镜像文件通常是 vmlinuz-版本号到内存中。同时它也会加载 初始 RAM 磁盘 文件通常是 initrd.img-版本号 或 initramfs-版本号。控制权从 GRUB2 移交到 Linux 内核。内核在内存中解压自己然后开始初始化设置内存管理、检测 CPU。初始化硬件子系统。内核需要挂载真正的根文件系统才能找到并运行第一个用户空间进程。内核会执行 initramfs 中的 /init 脚本。这个脚本的任务是加载必要的硬件驱动模块。如果根文件系统被加密会提示输入密码。激活 LVM/RAID 卷。最终找到并挂载真正的根文件系统。initramfs 的 /init 脚本在成功挂载真正的根文件系统后会进行 “pivot root” 操作即从内存中的 initramfs 切换到硬盘上的根文件系统。然后它执行根文件系统中的 /sbin/init 程序。这是 第一个用户空间进程其进程号永远是 1。/sbin/init 进程负责启动系统的其余部分。systemd 的二进制文件就是 /sbin/init一个符号链接。它并行启动服务大大加快启动速度。它管理着整个系统的服务、挂载点、套接字等称为 units。systemd 启动的目标是达到 “default.target”这通常是一个符号链接指向 multi-user.target多用户命令行界面或 graphical.target图形界面。在启动过程中它会解决各个单元之间的依赖关系并行启动所有必要的服务如网络、日志、显示管理器等。如果目标是 graphical.target图形界面systemd 会启动显示管理器如 GDM、SDDM 或 LightDM。显示管理器提供图形化登录界面。用户输入凭据登录后显示管理器启动桌面环境如 GNOME、KDE Plasma 或 XFCE。最终用户看到完整的桌面环境启动完成。嵌入式Linux启动流程使用bootloader的方式进行启动以RK35XX举例详细见SoC详细启动流程0724单片机启动流程使用bootloader的方式进行启动以STM32举例详细见单片机启动流程以STM32举例https://blog.csdn.net/wxr2268715051/article/details/160373020?spm1011.2415.3001.10575sharefrommp_manage_link1、进程调度—处理机管理进程与线程ARM架构下进程切换和线程切换的核心区别https://blog.csdn.net/wxr2268715051/article/details/163538216?spm1011.2415.3001.10575sharefrommp_manage_link进程的状态进程间通信调度饥饿同步与互斥互斥和同步都是为了解决并发环境下访问共享资源时可能出现的问题死锁信号量semaphorePV操作P—wait(S)—申请/占用资源 V—signal(S)—释放资源记录型信号量的数据结构/*记录型信号量的定义*/typedefstructintvalue;//剩余资源数structprocess*L;//等待队列}semaphore;互斥资源的访问—互斥信号量互斥量异步并发进程的同步—同步信号量每一对前后执行的关系都需要一个同步信号量先释放V再占用P生产者与消费者使用三个信号量互斥信号量—实现对buffer的互斥访问同步信号量—表示buffer当中空闲位置的数量同步信号量—表示buffer当中产品的数量// 全局变量和信号量BUFFER_SIZE10buffer[BUFFER_SIZE]// 共享缓冲区mutexsemaphore(1)// 互斥信号量初值1emptysemaphore(BUFFER_SIZE)// 空槽位数初值Nfullsemaphore(0)// 已填充槽位数初值0// 生产者进程PRODUCER(){while(1){itemproduce_item()// 生产一个数据项wait(empty)// 等待空槽位wait(mutex)// 进入临界区buffer[in]item// 放入数据signal(mutex)// 离开临界区signal(full)// 增加已填充槽位}}// 消费者进程CONSUMER(){while(1){wait(full)// 等待有数据可消费wait(mutex)// 进入临界区itembuffer[out]// 取出数据signal(mutex)// 离开临界区signal(empty)// 增加空槽位consume_item(item)// 消费数据}}互斥占用一定要在同步占用之后多生产者与多消费者单生产者AB消费者// 缓冲区生产者写入两个消费者读取BUFFER_SIZE10buffer[BUFFER_SIZE]// 同步变量mutexsemaphore(1)// 保护缓冲区的互斥锁data_readysemaphore(0)// 有新数据可供 A 消费a_donesemaphore(0)// A 已读完B 可以读b_donesemaphore(0)// B 已读完槽位可以回收slots_freesemaphore(BUFFER_SIZE)// 可用于生产者的空槽位// 生产者PRODUCER(){while(1){itemproduce_item()wait(slots_free)// 等空槽位wait(mutex)buffer[in]item// 放入数据signal(mutex)signal(data_ready)// 通知 A 有新数据}}// 消费者 A必须先读CONSUMER_A():whiletrue:wait(data_ready)// 等待新数据wait(mutex)itembuffer[out_a]// A 从自己的指针读取signal(mutex)signal(a_done)// 通知 BA 已读完这条consume_A(item)// A 处理数据// 消费者 B必须在 A 之后读CONSUMER_B(){while(1){wait(a_done)// 等待 A 先读完wait(mutex)itembuffer[out_b]// B 从自己的指针读取signal(mutex)signal(b_done)// 通知这条数据两个消费者都读完了signal(slots_free)// 槽位可以回收给生产者用consume_B(item)// B 处理数据}}读者与写者本质读共享写互斥读者对资源不消费单写者 多读者 写优先使用三个信号量一个计数值互斥信号量rw读的时候不能写写的时候不能写读任务计数count计算当前有多少读者正在读互斥信号量mutex_count实现对count的互斥互斥信号量w实现写优先// 信号量rwsemaphore(1)// 资源锁读者和写者都用它竞争资源mutex_countsemaphore(1)// 保护 count 的互斥锁wsemaphore(1)// 写者优先锁写者在等待时阻止新读者进入// 计数值count0// 当前正在读的读者数量WRITER(){while(1){wait(w)//写优先wait(rw)//--------------------------------------------------------write_resource(new_data)signal(rw)//--------------------------------------------------------signal(w)//写优先}}READER(){while(1){wait(w)//写优先wait(mutex_count)//------------------------------countifcount1:// 第一个读者负责抢占资源wait(rw)//---------------------------------------------------------signal(mutex_count)//-----------------------------signal(w)//写优先dataread_resource()wait(mutex_count)//------------------------------count--ifcount0:// 最后一个读者负责释放资源signal(rw)//----------------------------------------------------------signal(mutex_count)//------------------------------process_data(data)}}多写者 多读者 写优先// 信号量rwsemaphore(1)// 资源锁读者和写者都用它竞争资源mutex_countsemaphore(1)// 保护 count 的互斥锁wsemaphore(1)// 写者优先锁写者在等待时阻止新读者进入wwsemaphore(1)// ★新增★ 写者间互斥锁// 计数值count0// 当前正在读的读者数量WRITER(){while(1){wait(w)// 写优先抢占闸门wait(ww)// ★新增★ 写者之间互斥wait(rw)// 等待资源空闲write_resource(new_data)signal(rw)// 释放资源signal(ww)// ★新增★ 释放写者互斥锁signal(w)// 写优先释放闸门}}READER(){while(1){wait(w)// 写优先通过闸门wait(mutex_count)// 互斥修改 countcountifcount1:// ★修改★ 先加再判断wait(rw)// 第一个读者锁资源signal(mutex_count)signal(w)// 写优先释放闸门dataread_resource()wait(mutex_count)// 互斥修改 countcount--ifcount0:// 最后一个读者释放资源signal(rw)signal(mutex_count)process_data(data)}}线程同步与互斥方式管程—封装好的类2、内存管理—存储器管理进程的内存映像分配与回收连续分配内存管理进程的内外内部碎片分配给某进程的内存区域中如果有些部分没有用上。外部碎片是指内存中的某些空闲分区由于太小而难以利用。单一连续分配固定分区分配动态分区分配非连续分配内存管理体现出操作系统的虚拟特性分页内存管理页是信息的物理单位。分页的主要目的是为了实现离散分配提高内存利用率。分页仅仅是系统管理上的需要完全是系统行为对用户是不可见的。页的大小固定且由系统决定。分页的用户进程地址空间是一维的程序员只需给出一个记忆符即可表示一个地址。优点内存空间利用率高不会产生外部碎片只会有少量的页内碎片。缺点不方便按照逻辑模块实现信息的共享和保护快表Translation Lookaside BufferTLB内容一部分的页表特性访问速度比内存快很多cacheTLB不是内存作用存放最近访问的页表项加速地址变换联想进程线程的切换开销资源的不同最根本就是来源于此进程切换快表页面清除分段内存管理段是信息的逻辑单位。分段的主要目的是更好地满足用户需求。一个段通常包含着一组属于一个逻辑模块的信息。分段对用户是可见的用户编程时需要显式地给出段名。段的长度却不固定决定于用户编写的程序。分段的用户进程地址空间是二维的程序员在标识一个地址时既要给出段名也要给出段内地址。分段比分页更容易实现信息的共享和保护。不能被修改的代码称为纯代码或可重入代码不属于临界资源这样的代码是可以共享的。可修改的代码是不能共享的优点很方便按照逻辑模块实现信息的共享和保护。缺点如果段长过大为其分配很大的连续空间会很不方便。另外段式管理会产生外部碎片段页式内存管理先分段后分页内存扩充覆盖需要程序员显式声明现已不使用一个进程当中发生对内存分为固定区程序运行不会调入调出覆盖区程序运行会根据需要调入调出交换内存调度不同进程之间发生对外存硬盘分为文件区不连续的对换区连续的换出的进程挂起态存储在对换区虚拟内存请求调页访问的信息不在内存时由操作系统负责将所需信息从外存调入内存页面置换内存空间不够时将内存中暂时用不到的信息换出到外存请求分页内存管理新增页表项状态位表示页面是否已在内存中访问字段记录最近被访问过几次或记录上次访问的时间供置换算法选择换出页面时参考修改位表示页面调入内存后是否被修改过只有修改过的页面才需在置换时写回外存外存地址页面在外存中存放的位置页面置换算法页面分配策略驻留集工作集分配置换策略固定分配局部置换进程运行前就分配一定数量物理块缺页时只能换出进程自己的某一页可变分配全局置换只要缺页就分配新物理块可能来自空闲物理块也可能需换出别的进程页面可变分配局部置换频繁缺页的进程多分配一些物理块缺页率很低的进程回收一些物理块。直到缺页率合适请求分段内存管理请求页段内存管理地址转换逻辑地址相对-物理地址绝对逻辑地址是在进程视角下看到的地址。每个进程都拥有自己独立的、从0开始编址的、连续的地址空间。逻辑地址通常在编译和链接期间由编译器生成。编译器并不知道程序未来会被加载到物理内存的哪个位置。物理地址指的是在物理内存条RAM上真实存在的、每一个内存单元的绝对地址。CPU的地址总线最终就是通过这个地址来访问内存数据的。内存保护保证各进程在自己的内存空间内运行不会越界访问3、文件—文件管理块-页-扇区块操作系统按块建造索引表进行查找通常与内存页的大小相同同时也是最小的擦除单位页最小的写入单位扇区机械硬盘时代的最小可寻址单元固定为 512字节。文件系统层次结构文件系统布局硬盘中的布局物理格式化注意坏扇区操作系统不可见逻辑格式化内存中的布局文件调用过程文件逻辑结构—用户文件物理结构—OS顺序分配链接分配索引分配文件共享硬链接末影箱inode文件系统中的链接指针指向同一存储数据只有当某个文件的所有硬链接包括原始文件都被删除时磁盘上的数据才会被真正释放硬链接仅支持同一分区如 C 盘内软连接快捷方式虚拟文件系统文件挂载4、IO设备—设备管理IO软件的层次设备—特殊的文件设备独立性软件设备无关性软件设备接口系统调用设备的分配与回收一个通道控制多个控制器一个控制器控制多个设备逻辑设备表LUTLogical Unit Table一个用户一张LUT存在于进程级别/用户级别负责将进程使用的逻辑设备名映射到系统的物理设备。系统设备表SDTSystem Device Table)整个系统级别的全局表记录了系统中所有已被识别和配置的设备。无论设备是否正在被使用只要它存在于系统中就会在SDT中有一个条目。设备控制表DCTDevice Control Table)一个设备一张DCT设备队列的队首指针被阻塞的进程的PCB所放到的阻塞队列控制器控制表COCTController Control Table一个控制器一张COCT通道控制表CHCTChannel Control Table)一个通道一张CHCT1、进程发出 系统调用CPU从用户态陷入内核态操作系统查询该进程的LUT使用逻辑设备名作为索引找到对应的条目。该条目包含了指向系统级物理设备标识符的指针。2、操作系统使用从LUT中获取的物理设备标识符去查询全局的系统设备表SDT。在SDT中匹配到条目并从该条目中获取指向对应的设备控制表DCT 的指针。3、操作系统访问 DCT检查设备状态字段。如果设备状态为“忙”则将当前进程加入到DCT的等待队列中进程阻塞调度其他进程运行。如果设备状态为“闲”操作系统将状态标记为“忙”以防止其他进程占用。4、操作系统根据DCT中的指针找到管理该设备的控制器控制表COCT。检查COCT的状态。如果控制器“忙”则进程在COCT的等待队列中阻塞。控制器就绪后操作系统再根据COCT中的指针找到连接该控制器的通道控制表CHCT。同样检查CHCT的状态。如果通道“忙”则进程在CHCT的等待队列中阻塞。5、当设备、控制器、通道三者皆就绪后操作系统构建一个通道程序并将其地址填入CHCT。操作系统向通道发出启动I/O指令。6、通道接管工作它读取通道程序通过控制器向设备发出具体的控制命令。此时CPU被解放出来可以执行其他任务。假脱机技术—SPOOLingSimultaneous Peripheral Operations On-Line外围设备联机并行操作作用将独占设备改造成共享设备从而极大地提升CPU和I/O设备的利用率和系统效率。缓冲区—buffer—水库缓冲区是一块临时的数据存储区通常位于内存中用于在两个速度不匹配或时序不同的实体之间平滑数据流。缓冲区是SPOOLing的组成部分。缓冲池
返回列表