进程分析—从操作系统到Linux内核深入
必看前言文中图片均是经自己亲自调改生成。“豆包”仅把图片背景变黑图形 字体均经过校正。纯手搓无复制目录操作系统OS基本概念操作系统架构图底层操作系统与库函数的关系内存RAM与磁盘硬盘进程再谈操作系统进程的数据来源OS内的进程块pid、ppidpid(process id 进程id)ppid(parent process id)查询指令父进程-bash进程fork函数运行图示底层进程状态深入内核1.运行2.阻塞(scanf)网状本质挂起孤儿进程读懂进程状态进程查询Ⅰ暂停Ⅱ休眠Ⅲ死亡进程访问属性权限优先级查询*UID性质总结进程调度内核级分析CPU调度算法结构活跃进程活跃进程与过期进程操作系统OS基本概念操作系统(Operation System)是一个基本的程序集合为用户提供友好的执行环境进行管理软硬件的软件。操作系统架构图绝大多数的计算机操作系统的架构图基于冯•诺依曼提出的基本架构由输入设备、存储器、运算器、控制器和输出设备组成。五大组件的基本关系如下控制器负责读取指令产生控制信号。从内存读取指令、解码指令并产生控制信号。指挥协调其他部件的工作流程。运算器负责执行运算。算术运算(加减乘除)和逻辑运算(与或非。是整个计算机的数据加工中心。底层操作系统底层是应用C语言编写的主要利用struct结构体来管理驱动设备、底层硬件和进程等。操作系统与库函数的关系理解操作系统与库函数的关系是区分“系统编程”与“应用编程”的关键。库函数是操作系统提供给应用程序的接口和“工具箱”二操作系统是真正的硬件管理者。硬件程序通常不直接指挥操作系统而是直接通过调用库函数来请求操作系统提供服务。内存RAM与磁盘硬盘CPU是数据处理器(运算器控制器)需要读取数据。♔内存是数据的“工作台”磁盘是数据的“仓库”。CPU读取数据只能从内存中读取指令和数据来执行无法直接访问磁盘。因此磁盘里的数据必须先被加载到内存中CPU才能处理它们。进程前言此处探讨的进程均是子进程对象概念基本概念程序的一个执行实现正在执行的程序等。内核方面担当系统分配资源(CPU、内存)的实体。进程 内核结构对象自己的代码数据。再谈操作系统进程的数据来源操作系统读取数据只能从内存中读取内存内数据来自磁盘的“可执行程序代码段、数据段”。磁盘内数据被读取到内存中OS内的进程块操作系统内由struct XXX {……}结构体来管理进程。Linux内XXX是PCB(进程控制块Process Control Block)PCB间使用双向链表链接。PCB结构体内拥有代码地址和数据地址这些指针指向PCB外的进程数据(代码段数据段)。因此进程 PCB(struct task_struct) 该进程的代码段和数据段pid、ppidid查询方式pid(process id 进程id)每个进程都有自己的pid类似于我们的身份证号码当进程退出后重新启动其pid就会改变类似于人生重开后的身份证号。♝像热键CtrlC就是终止进程。ppid(parent process id)该进程的父进程id。查询指令while :; do ps ajx | head -1 ps ajx | grep myprocess;sleep 1; done每1秒查询一次或while :; do clear echo $(date %Y-%m-%d %H:%M:%S) ps ajx | head -1 ps ajx | grep myprocess echo sleep 1 done //复制版本 while :; do clear; echo $(date %Y-%m-%d %H:%M:%S) ; ps ajx | head -1; ps ajx | grep myprocess; echo ; sleep 1; done更简洁的查询父进程父进程是指通过fork()来创建出来的另一个进程。被创建出来的那个新进程就是这个父进程的子进程。父进程与子进程构成了树状结构整个系统的所有进程的根节点就是内核启动的第一个用户态进程(通常是init或systemdPID1)。-bash进程介绍当登录Linux服务器操作系统立马为你创建一个新的进程这个进程就是-bash。它是一切进程的子进程因此你可以从任意一个进程的ppid来不断追溯到达-base进程。-bash进程会显示一个命令提示符(比如 $ # )等待你输入命令。-bash进程与init/systemd进程的关系init/systemd向下会达到-base进程。fork函数原型pid_t fork(); #pid_t本质是signed int-2^31 ~ 2^31-1原理用于创建一个新的进程使得原进程变作新进程的父进程两个进程在下面的代码执行过程中调用顺序完全不确定受很多种因素决定。返回值fork调用一次但是会返回两次一次在父进程一次在子进程父进程的返回ID 0子进程的返回ID 0。若新进程创建失败则返回-1。.c文件下Man 3 fork #查询fork函数man查询图仅展示一部分使用举例//prc.c #includestdio.h #includeunistd.h int main() { printf(启动\n); printf(我是原进程pid %d\n, getpid()); pid_t i fork(); if(i 0) //子进程代码 { printf(我是衍生出来的子进程 pid %d ppid %d\n, getpid(), getppid()); } else if(i 0) //父进程入口 { printf(我是原来的进程变为了父进程pid %d\n, getpid()); } else{ printf(子进程创建失败\n); } return 0; }运行结果运行图示底层子进程拷贝父进程数据它们同时指向相同的代码数据当二者中任意一者发生写时再资源创建各自资源独立。进程状态三种主要类型运行 阻塞 挂起运行和挂起是正常一般的状态而挂起是极端情况下处理模式。深入内核1.运行进程想要运行本质在于是否位于CPU维护的“调度队列(runqueue)”只有位于调度队列的进程元素才有运行的资格。ps一个CPU仅维护一个调度队列调度队列严格遵守“尾进头出FIFO”原则。进程控制块PCB——struct task_structPCB间使用指针链接最终形成双向链表的结构。图示如下2.阻塞(scanf)阻塞的来源于I/O流及数据传输相关本质是“我需要的东西还没有准备好”并非“我没有资源”而阻塞。以I/O中的scanf为例说明阻塞的原理。同样的device结构体之间链接节点struct device { int id;//设备id int status;//设备状态 void* data; struct device* next;// 指向下一个 struct device* prev;// 指向前一个 int type; struct task_struct* wait_queue;// 等待队列 }等待队列wait_queue是位于链表外的又一队列例如多个输入的等待。运行和阻塞间的切换就是链表的“增删查改”。例如程序运行到scanf时OS的处理网状本质事实PCB间的链接并非简单的双向链表而是网状复杂结构。每个PCBstruct task_struct内嵌套一种结构体struct list_head每个list_head内部都拥有两个指针next prevtask_struct内嵌套了多个这样的结构体。因此链接父子 兄弟 全局进程构成网状结构。struct task_struct { struct list_head tasks; // 接入全局进程链表 struct list_head children; // 接入父进程的子进程链表 struct list_head sibling; // 接入兄弟进程链表 struct list_head run_list; // 接入调度器运行队列 // ... 还有 400 个字段 };下图不用看懂仅作“网状”的展示挂起极端情况下像内存空间不足、用户主动暂停及系统休眠引发的非一般进程状态。挂起指的是进程被人为/系统地从内存移动到磁盘(swap分区)以释放宝贵的内存资源。孤儿进程定义子进程还未来得及结束时父进程就已经结束。孤儿进程被系统受理父进程(init/systemd)id为1可理解为操作系统至此此进程变为后台进程。读懂进程状态前言进程状态的查询受运行间隔的影响因此在使用循环体来检测进程状态时要谨慎处理。描述进程的常量// 数组 static const char* const task_state_array[] { R (running), S (sleeping), D (disk sleep), T (stopped), t (trcing stop), X (dead), Z (zombine), };进程查询// 每秒查询一次进程状态 pc代表执行文件名称 while :; do echo $(date %Y-%m-%d %H:%M:%S) ps ajx | grep \./pc | grep -v grep echo sleep 1 doneⅠ暂停Ⅱ休眠Ⅲ死亡进程访问属性进程的访问属性包括权限和优先级决定了进程能否被访问能被访问的话被访问的顺序如何。权限权限决定了进程可以访问哪些资源由进程的身份决定。优先级进程的优先级决定了进程获得CPU资源的能力由评判优先级的值PRI决定值越低优先级越高越高优先级越低。查询ps -al |head -1 ps -al |grep procNI值作为修复值调整PRI值的大小。PRI (默认值)80 NI当新旧进程调整时NI值会发生变化。*UIDUID是文件/目录权限中判断访问者属于拥有者/所属组/其他人。上图中UID的1000代表wzb用户。使用ls -ln查询显现UID性质总结总体而言进程的性质竞争性进程间存在资源竞争关系与优先级问题。独立性多个进程运行时需要各自独享资源进程间具备一定的独立性。并行多个进程在多个CPU下分别同时进行称为并行。并发多个进程在同一个CPU下采用进程切换超迅速切换的方式使得多个进程得以推进称之为并发。进程调度类型设计目标核心指标实时操作系统(RTOS)在规定时间内响应外部事件确定性、可预测性、响应延迟有最大上限分时操作系统让多个用户/任务公平地共享CPU吞吐量、平均响应时间及公平性在进程中的体现进程切换通过寄存器存储上下文数据且区分是否先前执行过以决策是否使得寄存器存储上下文数据。 ps实时操作系统基于时间片的来实现最大时间消耗。如响应超时 既体现了实时操作系统也体现了分时操作系统。内核级分析CPU调度算法结构CPU维护一个调度队列runqueue本质此队列是一个内部嵌套进程属性变量struct rqueue_Elmen* array[2]的结构体。struct rqueue_Elmen*内部含有队列状态nr_active、5*32位图bitmap和FIFO队列queue[140]。队列queue[140]内每个元素链接为双向链表——形成了由链地址法形成的哈希表活跃进程array[0] 的 nr_active决定此array是活跃进程函数过期进程bitmap位图5*32 160queue[140]维护的进程队列哈希表。bitmap160位但实际仅用到了[0,139]记140个元素。【0,99】分时优先级系统管理不探讨。【100139】实时优先级系统统筹管理同样的下标越小的进程优先级越大。活跃进程与过期进程构成元素完全一致执行不同的任务要求。array[0]和array[1] 两者在内存中各自维护自己的调度队列及其属性明显的进程的调度实际是队列节点的移动当一个进程在活跃队列执行完/超出时间片规定自动移动到过期进程同样的FIFO中。燃尽式博客 写完不知天地为何物 仿佛天越来越远地越来越近 求关球馆求(oo)
上一篇/下一篇内容由系统自动关联
返回资讯列表 →