ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Linux -- 进程概念

Linux -- 进程概念 1.基本概念与操作课本概念程序的⼀个执⾏实例正在执⾏的程序等内核观点担当分配系统资源CPU时间内存的实体。当前进程 内核数据结构(task_struct) ⾃⼰的程序代码和数据1.1 描述进程--PCB进程信息被放在⼀个叫做进程控制块的数据结构中可以理解为进程属性的集合。课本上称之为PCBprocess control block Linux 操作系统下的 PCB 是: task_structtask_struct-PCB的⼀种•在 Linux 中描述进程的结构体叫做 task_struct 。task_struct 是 Linux 内核的⼀种数据结构类型它会被装载到RAM(内存)⾥并且包含着进程的信息1.2 task_struct内容分类标⽰符:描述本进程的唯⼀标⽰符⽤来区别其他进程。状态:任务状态退出代码退出信号等优先级:相对于其他进程的优先级。程序计数器: 程序中即将被执⾏的下⼀条指令的地址。内存指针:包括程序代码和进程相关数据的指针还有和其他进程共享的内存块的指针上下⽂数据: 进程执⾏时处理器的寄存器中的数据[休学例⼦要加图CPU寄存器]。I∕O状态信息: 包括显⽰的I/O请求,分配给进程的I∕O设备和被进程使⽤的⽂件列表。记账信息: 可能包括处理器时间总和使⽤的时钟数总和时间限制记账号等。组织进程:可以在内核源代码⾥找到它。所有运⾏在系统⾥的进程都以task_struct 双链表的形式存在内核 ⾥。1.3 查看进程信息1. 进程的信息可以通过/proc系统⽂件夹查看如要获取PID为1的进程信息你需要查看 /proc/1 这个⽂件夹。1.4通过系统调⽤获取进程标⽰符#include stdio.h #include sys/types.h #include unistd.h int main() { printf(pid: %d\n, getpid()); printf(ppid: %d\n, getppid()); return 0; }1.5 通过系统调⽤创建进程-fork初识如果fork()返回值 0则为子进程。 0,则为父进程。 0,则为错误由于fork值返回之前子进程就已被创造所以两个进程都会返回值1.6进程状态/* *The task state array is a strange bitmap of *reasons to sleep. Thus running is zero, and *you can test for combinations of others with *simple bit tests. */ static const char *const task_state_array[] { R (running), /*0 */ S (sleeping), /*1 */ D (disk sleep), /*2 */ T (stopped), /*4 */ t (tracing stop), /*8 */ X (dead), /*16 */ Z (zombie), /*32 */ };1.7 Linux内核代码关于进程⼀个进程可以有⼏个状 态在Linux内核⾥进程有时候也叫做任务。下⾯的状态在kernel源代码⾥定义/* *The task state array is a strange bitmap of *reasons to sleep. Thus running is zero, and *you can test for combinations of others with *simple bit tests. */ static const char *const task_state_array[] { R (running), /*0 */ S (sleeping), /*1 */ D (disk sleep), /*2 */ T (stopped), /*4 */ t (tracing stop), /*8 */ X (dead), /*16 */ Z (zombie), /*32 */ };1.8进程状态查看ps aux / ps axj 命令1.9 补充概念-竞争、独⽴、并⾏、并发2.Z(zombie)-僵⼫进程•僵死状态Zombies是⼀个⽐较特殊的状态。当进程退出并且⽗进程使⽤wait()系统调⽤,后 ⾯讲没有读取到⼦进程退出的返回代码时就会产⽣僵死(⼫)进程• 僵死进程会以终⽌状态保持在进程表中并且会⼀直在等待⽗进程读取退出状态代码。• 所以只要⼦进程退出⽗进程还在运⾏但⽗进程没有读取⼦进程状态⼦进程进⼊Z状态危害当内存不够时会将进程的data和code放置swap分区此时为挂起状态如下3.孤儿进程•⽗进程先退出⼦进程就称之为“孤⼉进程”• 孤⼉进程被1号init/systemd进程领养当然要有init/systemd进程回收喽。4.进程优先级• cpu资源分配的先后顺序就是指进程的优先权priority。• 优先权⾼的进程有优先执⾏权利。配置进程优先权对多任务环境的linux很有⽤可以改善系统性 能。• 还可以把进程运⾏到指定的CPU上这样⼀来把不重要的进程安排到某个CPU可以⼤ 改善 系统整体性能。4.1查看系统进程在linux或者unix系统中⽤ps‒l命令则会类似输出以下⼏个内容4.2PRI and NI4.3 PRI VS NI5.进程切换CPU上下⽂切换其实际含义是任务切换,或者CPU寄存器切换。当多任务内核决定运⾏另外的任务 时,它保存正在运⾏任务的当前状态,也就是CPU寄存器中的全部内容。这些内容被保存在任务⾃⼰的堆栈中,⼊栈⼯作完成后就把下⼀个将要运⾏的任务的当前状况从该任务的栈中重新装⼊CPU寄存器,并开始下⼀个任务的运⾏,这⼀过程就是context switch。简单来说就是CPU 从正在运行的进程 A “暂停”下来保存好 A 的现场然后“恢复”并继续运行进程 B 的全过程。时间⽚当代计算机都是分时操作系统没有进程都有它合适的时间⽚(其实就是⼀个计数 器)。时间⽚到达进程就被操作系统从CPU中剥离下来。6.Linux2.6内核进程O(1)调度队列6.1 活动队列6.2 过期队列• 过期队列和活动队列结构⼀模⼀样6.3 active指针和expired指针6.4 总结• 在系统当中查找⼀个最合适调度的进程的时间复杂度是⼀个常数不随着进程增多⽽导致时间成 本增加我们称之为进程调度O(1)算法7. 命令⾏参数和环境变量7.1 基本概念环境变量(environment variables)⼀般是指在操作系统中⽤来指定操作系统运⾏环境的⼀些参数环境变量通常具有某些特殊⽤途还有在系统当中通常具有全局特性。7.2和环境变量相关的命令7.3和环境变量相关的一些事宜1.环境变量和C代码进程的关系进程通过代码获得环境变量2.谁传递的环境变量in bash - process - memoy - data其中bash 来自linux配置文件进程里所有的代码和指令来自bash的子进程。memory为临时的8.程序地址空间8.1空间布局图8.2虚拟地址#include stdio.h #include unistd.h #include stdlib.h int g_val 0; int main() { pid_t id fork(); if(id 0){ perror(fork); return 0; } else if(id 0){ //child,⼦进程肯定先跑完也就是⼦进程先修改完成之后⽗进程 再读取 g_val100; printf(child[%d]: %d : %p\n, getpid(), g_val, g_val); }else{ //parent sleep(3); printf(parent[%d]: %d : %p\n, getpid(), g_val, g_val); } sleep(1); return 0; }输出结果//与环境相关观察现象即可 child[3046]: 100 : 0x80497e8 parent[3045]: 0 : 0x80497e8我们发现⽗⼦进程输出地址是⼀致的但是变量内容不⼀样能得出如下结论:OS必须负责将 虚拟地址 转化成 物理地址8.3 进程地址空间分⻚虚拟地址空间上⾯的图就⾜矣说明问题同⼀个变量地址相同其实是虚拟地址相同内容不同其实是被映 射到了不同的物理地址8.5 虚拟内存管理描述linux下进程的地址空间的所有的信息的结构体是mm_struct 内存描述符。每个进程只有⼀ 个mm_struct结构在每个进程的 task_struct 结构中有⼀个指向该进程的mm_struct结构体指 针。struct task_struct { /*...*/ struct mm_struct *mm; //对于普通的⽤⼾进程来说该字段指向他 的虚拟地址空间的⽤⼾空间部分对于内核线程来说这部分为NULL。 struct mm_struct *active_mm; // 该字段是内核线程使⽤的。当 该进程是内核线程时它的mm字段为NULL表⽰没有内存地址空间可也并不是真正的没有这是因 为所有进程关于内核的映射都是⼀样的内核线程可以使⽤任意进程的地址空间。 /*...*/ }可以说 mm_struct 结构是对整个⽤⼾空间的描述。每⼀个进程都会有⾃⼰独⽴的 mm_struct 这样每⼀个进程都会有⾃⼰独⽴的地址空间才能互不⼲扰。先来看看由 task_struct 到 mm_struct 进程的地址空间的分布情况那既然每⼀个进程都会有⾃⼰独⽴的 mm_struct 操作系统肯定是要将这么多进程的 mm_struct 组织起来的虚拟空间的组织⽅式有两种1. 当虚拟区较少时采取单链表由mmap指针指向这个链表2. 当虚拟区间多时采取红⿊树进⾏管理由mm_rb指向这棵树。linux内核使⽤ vm_area_struct 结构来表⽰⼀个独⽴的虚拟内存区域(VMA)由于每个不同质的虚 拟内存区域功能和内部机制都不同因此⼀个进程使⽤多个vm_area_struct结构来分别表⽰不同类型 的虚拟内存区域。上⾯提到的两种组织⽅式使⽤的就是vm_area_struct结构来连接各个VMA⽅便进 程快速访问。8.6 为什么要有虚拟地址空间且虚拟地址和物理地址解耦进程管理和内存管理解耦
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进