3.进程

  • 进程:程序执行的一个实例,充分描述程序已经执行到何种程度的数据结构的集合.目的:担当资源分配的实体.每个线程是进程的一个执行流,可以由内核独立调度.

  • 标示一个进程 
    1. 进程和进程描述符一一对应.并且一个线程组公用一个PID.

    2. 进程描述符处理:
      Linux吧内核态的进程堆栈和紧挨进程描述符的小数据结构thread_info,紧凑地存放在一个单独为进程分配的存储区内.其Size=8K.即两个页框.且为了效率,第一个页框的起始地址=2(13)倍.

    3. 其中,thread_info的size=52B.位于存储区的开始处.堆栈起始于末端,并朝内存区开始的方向增长.用户态刚切换到内核态时,栈为空.esp寄存器指向栈顶.

    4. 标示当前进程: 因为Size
      =8K=2(13).所以屏蔽掉esp的低13位即可获得thread_info结构的基地址.但是经常使用的是进程描述符的地址,用current宏来代表.

    5. 双向链表: 不在链表中包含数据,而是在数据结构中包含链表节点.

    6. 当内核寻找一个新进程在CPU上运行时,必须只考虑处于Task_Running的进程.为了增加速度,为每一种进程优先级建立一个不同的进程链表.

  • 进程间的关系

  1. 进程0和1由内核创建,1(init)是所有进程的祖先.

  2. 为了从进程的PID导出对应的进程描述符指针,建立散列表.又因为进程描述符包含了表示不同类型PID的字段,所以需要4种散列表.然后利用链表来处理冲突的PID.其表项是由冲突的进程描述符组成的双向链表.并且在进程数目远小于允许PID的最大数时,节省了空间.

  • 如何组织进程

  1. 没有为暂停,僵死,死亡状态的进程创建专门的链表,因其访问比较简单.

  2. 等待队列:
    表示一组睡眠的进程,当某一条件为真时,由内核唤醒他们.其列头含有一个Lock自旋锁.其链表元素含有指向进程描述符的指针,等待的时间,和Flags字段(=1,当多个进程等待相同资源时内核有选择地唤醒,=0为非互斥进程,总是唤醒).

  3. 进程的资源限制:限制(rlim)指定了进程能使用的系统资源数量.

  • 进程切换

  1. 硬件上下文:每个进程用于自己的地址空间,但所有进程都共享CPU寄存器.
    进程恢复执行前必须装入寄存器的一组数据称为硬件上下文.其是进程可执行上下文的一个子集.其一部分存放在TSS段,剩余的存放在内核态堆栈中.由于切换经常发生,所以减少保存和装入硬件上下文所花费的时间是很重要的.

  2. 以前的Linux版本使用硬件支持,并通过far
    jmp指令跳到next进程TSS描述符的选择符来执行进程切换.但基于以下理由,现有版本使用软件执行切换:

    1. 通过一组mov指令逐步执行切换,这样能控制所装入数据的合法性,并使检查ds和es寄存器的值成为可能.

    2. 新旧方法的时间消耗大致相同.

  3. 进程切换只发生于内核态.切换之前,用户态进程所使用的所有寄存器内容已保存在内核态堆栈上.

  4. 任务状态段:TSS.存放硬件上下文,Linux虽不使用硬件上下文切换,但为每一个CPU创建一个TSS.原因:

    1. CPU从用户态切换到内核态时,它就从TSS获取内核态堆栈的地址.

    2. 当用户态进程试图通过in/out指令访问I/O端口时,CPU通过访问TSS的I/O许可权位图来决定是否有访问权利.

  5. TSS反映了CPU上当前进程的特权级,而不必为没有运行的进程保留TSS.每个TSS都有一个TSSD描述符.存放在GDT中.但有tr寄存器存放TSSD的base和limit字段.所以CPU能够对TSSD直接寻址而非通过GDT.

  6. 执行进程切换: 分为两步:1)切换页全局目录以安装一个新的地址空间.2)切换内核态堆栈和硬件上下文.

  7. switch_to宏:3个参数:pre,next,last.首先,暂停A执行B,然后,内核激活A时,就必须暂停另一进程C(通常不是B).所以last为输出参数,表示把进程C的描述符地址写在内存的什么位置,该动作在A恢复执行后完成.

  8. 保存和加载FPU,MMX,XMM寄存器.

    1. FPU:已被集成到CPU内,如果进程使用了Escape指令,那么FPU就属于其硬件上下文,并且应被保存.

    2. MMX:家属多媒体APP的执行.其指令作用域FPU的浮点寄存器.缺点是不能把浮点指令与MMX指令混合使用,优点是能够忽略新指令,因为保存浮点单元的任务切换代码可以不修改地应用到保存MMX上.其在CPU内部引入了SIMD(单指令多数据)流水线.

    3. 之后,引入了SSE扩展,该扩展为处理包含在8个128位寄存器(XMM寄存器)的浮点值增加了功能.XMM寄存器不与FPU和MMX重叠.之后的SSE2支持高精度浮点值,并与SSE公用XMM寄存器.

    4. CPU并不在TSS中自动保存FPU,MMX,XMM寄存器.不过,硬件支持cr0寄存器中的一个TS标志,其遵循规则(1,每当执行硬件上下文切换时,设置TS;
      2,每当TS标志被设置时执行ESCAPE,MMX,SSE或SSE2指令,控制单元产生一个"Device not
      available"异常.).TS标志使得内核只有在真正需要时才保存和恢复这些寄存器.只有当进程使用这些指令时,当发生上下文切换时,内核置TS标志并保存寄存器内容.

  • 创建进程:

  1. 机制:1)写时复制允许父子进程读相同的物理页; 2)轻量级进程允许父子进程共享每进程在内核的很多数据结构;
    3)vfork()创建的进程能共享其父进程的内存地址空间.

  2. 内核进程:
    传统的Linux将一些重要任务委托给周期性执行的进程,但这样效率不高.而现在使用内核线程,其只运行在内核态.只能使用大于Page_Offset的线性地址空间.

  3. 以下为所有的内核线程:

    1. 进程0: idle进程.工作:初始化内核需要的数据结构,激活中断.创建进程1, ; 每个CPU一个进程0。

    2. 进程1: 一直存活到系统关闭.它创建和监控在OS外层执行的所有进程的活动.

    3. keventd:即事件,执行keventd_wq工作队列中的函数.

    4. kapmd:处理与高级电源管理(APM)相关的时间.

    5. kswapd:执行内存回收.

    6. pdflush:刷新脏缓冲区中的内容到磁盘以回收内存.

    7. kblockd:执行kblockd_workqueue工作队列中的函数,其实只是周期性地激活块设备驱动程序

    8. ksoftird:运行tasklet

  • 撤销进程:

  1. 进程终止了它们本该执行的代码,此时必须通知内核以便内核释放其所拥有的资源(内存,打开文件,信号量等).可以终止一个线程,或者线程组.

  2. Unix允许查询内核以或得进程的子或父进程的PID或者执行状态.所以其不允许在进程一终止就丢弃包含在进程描述符字段中的数据.只有父进程发出了与被终止的进程相关的wait()类调用之后,才运行这样做.这就是引入僵死状态的原因:技术上进程已死,但是必须保存它的描述符,直到父进程得到通知.

  3. 如果父进程在子进程结束之前结束,系统会充满了僵死进程,并且他们的进程描述符永久占用RAM.所以,强迫所有的孤儿进程称为init进程的子进程来解决.init进程在用wait()类系统调用检查器合法的子进程终止时,就会撤销僵死的进程.

3.进程

时间: 2024-10-11 00:18:02

3.进程的相关文章

C#:多进程开发,控制进程数量

正在c#程序优化时,如果多线程效果不佳的情况下,也会使用多进程的方案,如下: System.Threading.Tasks.Task task=System.Threading.Tasks.Task.Factory.StartNew( (object mystate) => { Process process = Process.Start("AutoCollectMrMultipleProcess.exe", mystate.ToString()); process.WaitF

C# 远程服务器 安装、卸载 Windows 服务,读取远程注册表,关闭杀掉远程进程

这里安装windows服务我们用sc命令,这里需要远程服务器IP,服务名称.显示名称.描述以及执行文件,安装后需要验证服务是否安装成功,验证方法可以直接调用ServiceController来查询服务,也可以通过远程注册表来查找服务的执行文件:那么卸载文件我们也就用SC命令了,卸载后需要检测是否卸载成功,修改显示名称和描述也用sc命令.至于停止和启动Windows服务我们可以用sc命令也可以用ServiceController的API,当停止失败的时候我们会强制杀掉远程进程,在卸载windows

【转】linux下杀死进程(kill)的N种方法

转载一篇,最原始的出处已不可考,望见谅! 常规篇: 首先,用ps查看进程,方法如下: $ ps -ef --smx       1822     1  0 11:38 ?        00:00:49 gnome-terminalsmx       1823  1822  0 11:38 ?        00:00:00 gnome-pty-helpersmx       1824  1822  0 11:38 pts/0    00:00:02 bashsmx       1827    

os -- 进程的控制

os -- 进程的控制 新建 模板 小书匠 参考 <计算机操作系统>(第四版) 汤小丹等编著 概念引入 进程控制 进程控制是最基本的功能,负责创建进程.结束进程等功能,一般由 OS 内核中的原语来实现 原语 所谓原语,就是由若干条指令组成的,用于完成一定功能的一个过程,算是不可分割的.最基本的操作 Note 接下来原语基本用于所有的操作 操作系统内核 操作系统将一些常用或者运行频率较高的模块(如时钟管理.进程调度等)常驻内存,这些就被称为 OS 内核 两大功能 支撑功能 中断处理 时钟管理 原

linux进程管理

进程管理 进程 Process 某应用程序打开的进程 PID Process ID 类型: 用户空间进程 内核空间进程 静态查看进程的状态 # ps [[email protected] ~]# ps >>>>查看本终端的进程 PID TTY          TIME CMD 4206 pts/0    00:00:00 bash 4378 pts/0    00:00:00 ps 选项的使用方式: BSD风格:选项没有横线- ps aux SysV风格:选项需要带有横线-  

linux基本命令整理(三):进程和vim

linux基本命令整理(三) -----------进程和vim 一.进程 1.查看进程 ps:将某个时间点的程序运行的状况截取下来 a:所有的进程 x:后台进程 u:有效的使用者相关的进程(常用组合aux) -IA:也能观察系统所有的数据 axjf:连同部分的程序树状态 -I:今查看和自己bash相关的程序 top:动态的观察进程的变化 -d:后面接描述,就是整个页面刷新的时间:默认是5秒 -b:以批次的方式执行top -n:与-b搭配使用,意义是需要进行几次top的输出结果 如:top -b

内存池、进程池、线程池

首先介绍一个概念"池化技术 ".池化技术 一言以蔽之就是:提前保存大量的资源,以备不时之需以及重复使用. 池化技术应用广泛,如内存池,线程池,连接池等等.内存池相关的内容,建议看看Apache.Nginx等开源web服务器的内存池实现. 起因:由于在实际应用当中,分配内存.创建进程.线程都会设计到一些系统调用,系统调用需要导致程序从用户态切换到内核态,是非常耗时的操作.           因此,当程序中需要频繁的进行内存申请释放,进程.线程创建销毁等操作时,通常会使用内存池.进程池.

Linux进程的睡眠和唤醒

1   Linux进程的睡眠和唤醒 在Linux中,仅等待CPU时间的进程称为就绪进程,它们被放置在一个运行队列中,一个就绪进程的状态标志位为TASK_RUNNING.一旦一个运行中的进程时间片用完, Linux内核的调度器会剥夺这个进程对CPU的控制权,并且从运行队列中选择一个合适的进程投入运行. 当然,一个进程也可以主动释放CPU的控制权.函数schedule()是一个调度函数,它可以被一个进程主动调用,从而调度其它进程占用CPU.一旦这个主动放弃CPU的进程被重新调度占用CPU,那么它将从

C#杀掉进程的方法

1 private static string CmdName = "cmd"; 2 /// <summary> 3 /// 关闭进程 4 /// </summary> 5 /// <param name="processName">进程名</param> 6 private void KillProcess(string processName) 7 { 8 Process[] myproc = Process.Ge

Linux进程管理与调度-之-目录导航【转】

转自:http://blog.csdn.net/gatieme/article/details/51456569 版权声明:本文为博主原创文章 && 转载请著名出处 @ http://blog.csdn.net/gatieme 目录(?)[-] 项目链接 进程的描述 进程的创建 进程的加载与运行 进程的退出 进程的调度 调度普通进程-完全公平调度器CFS 日期 内核版本 架构 作者 GitHub CSDN 2016-07-21 Linux-4.6 X86 & arm gatieme