第三章 进程管理

3.1 进程

1.进程:

  • 进程就是处于执行期的程序。
  • 进程就是正在执行的程序代码的实时结果。
  • 进程是处于执行期的程序以及相关的资源的总称。
  • 进程包括代码段和其他资源。

2.线程:执行线程,简称线程,是在进程中活动的对象。

  • 内核调度的对象是线程而不是进程。

  • Linux对线程并不特别区分,视其为特殊的进程。

3.在现代操作系统中,进程提供两种虚拟机制:虚拟处理器和虚拟内存包含在同一个进程中的线程可以共享虚拟内存,但是每个都拥有各自的虚拟处理器。

4.几个函数

  • fork():创建新进程
  • exec():创建新的地址空间并把新的程序载入其中
  • clone():fork实际由clone实现
  • exit():退出执行
  • wait4():父进程查询子进程是否终结
  • wait()、waitpid():程序退出执行后变为僵死状态,调用这两个消灭掉。

3.2 进程描述符及任务结构

  1. 内核把进程的列表存放在叫做任务队列的双向循环链表中。
  2. 链表中的每一项都是进程描述符。
  3. 进程描述符的类型为task_struct。

3.2.1 分配进程描述符

  1. Linux通过slab分配器分配task_struct结构——能达到对象复用和缓存着色的目的。
  2. slab分配器——动态生成,只需在栈底或者栈顶创建一个新的结构struct thread_info。
  3. 每个任务的thread_info结构在它的内核栈的尾端分配。
  4. 结构中task域中存放的是指向该任务实际task_struct的指针。

3.2.2 进程描述符的存放

  1. 内核通过一个唯一的进程标识值PID来标识每个进程。

  2. pid类型为pid_t,实际上就是一个int类型,最大值默认设置为32768,上限私改/proc/sys/kernel/pid_max。

  3. pid存放在各自进程描述符中。

3.2.3 进程状态

进程描述符中的state域是用来描述进程当前状态的。共有五种状态,标志如下:

  • TASK_RUNNING(运行):进程是可执行的,或者正在执行,或者在运行队列中等待执行
  • TASK_INTERRUPTIBLE(可中断):进程正在睡眠/被阻塞
  • TASK_UNINTERRUPTIBLE(不可中断):睡眠/被阻塞进程不被信号唤醒 TASK_TRACED:被其他进程跟踪的进程
  • TASK_STOPPED(停止):进程停止执行;进程没有投入运行也不能投入运行。 接收到SIGSTOP、SIGTSTP、SIGTTIN、SIGTTOU等信号时,或者调试时收到任何信号,都可以进入这种状态。

3.2.4 设置当前进程状态

用set_task_state(task,state)函数。

3.2.5 进程上下文

程序执行系统调用或者触发异常后,会陷入内核空间,这时候内核代表进程执行,并且处于进程上下文中。
进程对内核的访问必须通过接口:系统调用和异常处理程序

3.2.6 进程家族树

  1. 所有的进程都是pid为1的init进程的后代。
  2. 内核在系统启动的最后阶段启动init进程。
  3. 系统中的每一个进程必有一个父进程,可以拥有0个或多个子进程,拥有同一个父进程的进程叫做兄弟。
  4. 这种关系存放在进程描述符中,parent指针指向父进程task_struct,children是子进程链表。

3.3 进程创建

Unix系统的进程创建方式

  • fork()通过拷贝当前进程创建一个子进程
  • exec()负责读取可执行文件并将其载入地址空间开始运行

3.1 写时拷贝

  • Linux的fork()使用写时拷贝推迟甚至免除拷贝。内核在创建新进程的时候并不复制整个地址空间,而是让父进程和子进程共享同一个拷贝;直到子进程/父进程需要写入的时候才进行拷贝
  • fork的实际开销只是复制父进程的页表以及给子进程创建唯一的进程描述符

3.2 fork()

  1. Linux通过clone系统调用实现fork
  2. 由clone去调用do_fork()
  3. 定义在<kernel/fork.c>中的do_ fork()完成创建中的大部分工作,它调用copy_process函数,然后让进程开始运行

  最后copy_process返回的就是指向子进程的指针

3.3 vfork()

  除了不拷贝父进程的页表项外,vfork()系统调用和fork()功能相同。子进程作为父进程的一个单独的线程在它的地址空间里运行,父进程被阻塞,直到子进程退出或执行exec()。

  vfork()系统调用的实现是通过向clone()系统调用传递一个特殊标志来进行的:

3.4 线程在Linux中的实现

  线程机制提供了在同一程序内共享内存地址空间运行的一组线程。在Linux系统中,线程仅仅被视为一个与其他进程共享某些资源的进程。每个线程都有自己的task_struct。

3.4.1 创建线程

1. 线程的创建与普通进程类似,只不过在调用clone()的时候需要传递一些参数标志来指明共享的资源

2. 传递给clone()的参数标志决定了新创建进程的行为方式和父子进程之间共享的资源种类

3.4.2 内核线程

内核线程与普通进程的区别只在于内核线程没有独立的地址空间:

  • 它只能通过其他内核线程创建;内核通过kthread内核进程衍生所有的内核线程
  • 新创建的线程处于不可运行状态,直到wake_ up_process()明确地唤醒它

3.5 进程终结

终结进程大部分依赖于do_exit()来完成:

3.5.1 删除进程描述符

  1. 该任务是和清理工作分开进行的,因为这样在进程终结之后系统仍然可以获得它的信息
  2. 通过release_task()实现进程描述符的删除
  3. 至此,所有资源都被释放了

3.5.2 解决孤儿进程

1. 孤儿进程:父进程在进程之前退出,就会遗留下子进程,也就是孤儿进程

2. 解决方法:在当前的线程组内给孤儿进程寻找新的父进程;否则直接以init作为其父进程

  • 调用顺序:do_ exit()-->forget_ original_ parent()-->find_ new_ parent()-->ptrace_ exit_ finish()

一旦系统为进程成功地找到和设置了新的父进程,就不会再有出现驻留僵死进程的危险了。init进程会例行调用wait()来检查其子进程,清除所有与其相关的僵死进程。



Linux内核分析 读书笔记 (第三章)的更多相关文章

  1. Linux内核分析 读书笔记 (第一章、第二章)

    第一章 Linux内核简介 1.1 Unix的历史 Unix很简洁,仅仅提供几百个系统调用并且有一个非常明确的设计目的. 在Unix中,所有东西都被当做文件,这种抽象使对数据和对设备的操作是通过一套相 ...

  2. 20135239 益西拉姆 linux内核分析 读书笔记之第四章

    chapter 4 进程调度 4.1 多任务 多任务操作系统就是能同时并发的交互执行多个进程的操作系统. 多任务系统可以划分为两类: - 非抢占式多任务: - 进程会一直执行直到自己主动停止运行(这一 ...

  3. 《Linux内核分析》之第三章读书笔记

    进程管理 进程是处于执行期的程序以及相关的资源的总称,也称作任务.执行线程,简称线程,是在进程中活动的对象. 可以两个或两个以上的进程执行同一个程序 也可以两个或两个以上并存的进程共享许多资源 内核调 ...

  4. Linux内核分析 读书笔记 (第七章)

    第七章 链接 1.链接是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载(或被拷贝)到存储器并执行. 2.链接可以执行于编译时,也就是在源代码被翻译成机器代码时:也可以执行于 ...

  5. Linux内核分析 读书笔记 (第五章)

    第五章 系统调用 5.1 与内核通信 1.调用在用户空间进程和硬件设备之间添加了一个中间层.该层主要作用有三个: 为用户空间提供了硬件的抽象接口. 系统调用保证了系统的稳定和安全. 实现多任务和虚拟内 ...

  6. Linux内核分析 读书笔记 (第四章)

    第四章 进程调度 调度程序负责决定将哪个进程投入运行,何时运行以及运行多长时间.进程调度程序可看做在可运行态进程之间分配有限的处理器时间资源的内核子系统.只有通过调度程序的合理调度,系统资源才能最大限 ...

  7. STL源码分析读书笔记--第三章--迭代器(iterator)概念与traits编程技法

    1.准备知识 typename用法 用法1:等效于模板编程中的class 用法2:用于显式地告诉编译器接下来的名称是类型名,对于这个区分,下面的参考链接中说得好,如果编译器不知道 T::bar 是类型 ...

  8. Linux内核分析 读书笔记 (第十八章)

    第十八章 调试 18.1 准备开始 1. 需要的只是: 一个bug 一个藏匿bug的内核版本 相关内核代码的知识和运气 2. 在跟踪bug的时候,掌握的信息越多越好. 18.2 内核中的bug 1.  ...

  9. 《Linux内核设计与分析》第六周读书笔记——第三章

    <Linux内核设计与实现>第六周读书笔记——第三章 20135301张忻估算学习时间:共2.5小时读书:2.0代码:0作业:0博客:0.5实际学习时间:共3.0小时读书:2.0代码:0作 ...

随机推荐

  1. Shell脚本应用(if语句的结构)

    1.测试:检测表达式是否成立,成立则返回值为0,否则为非0 方法: 1)test  表达式 2)[ 表达式 ] 2.文件测试: -d:是否为目录 -f:是否为文件 -e:是否存在 -r:是否有读取权限 ...

  2. django —— MVT模型

    转载----

  3. if语句(初学者)

    用if语句可以构成分支结构.它根据给定的条件进行判断,以决定执行某个分支程序段.C语言的if语句有三种基本形式. 1.基本形式:if(表达式)语句 其语义是:如果表达式的值为真,则执行其后的语句,否则 ...

  4. linux命令之 df file fsck fuser

    有非常多人说,网上非常多知识点都有了.为什么你还要在自己的博客中反复这些东西呢? 我想说的是.别人写的东西是别人理解的东西,同一时候也是别人学习过程的总结,对于自己来说.自己写自己的博客最基本的目的就 ...

  5. P2665 [USACO08FEB]连线游戏Game of Lines

    本着dp的心情,结果是道水题STL  set就行了 题意:看有多少种斜率(题在那里半天说多少直线(不平行的)),其实就是找斜率的种类 #include<cstdio> #include&l ...

  6. centos时区设置

    [root@ logs]# tzselect Please identify a location so that time zone rules can be set correctly.Pleas ...

  7. 分布式计算(三)Azkaban介绍

    转载自:Azkaban学习之路 (一)Azkaban的基础介绍 目录 一.为什么需要工作流调度器 二.工作流调度实现方式 三.常见工作流调度系统 四.各种调度工具对比 五.Azkaban 与 Oozi ...

  8. Linux C++调试利器-gdb

    在Linux上开发后台C++程序时,没有类似Windows VisualStudio那样强大的可视化IDE.为了提高调试效率,快速定位问题,需要掌握gdb工具的一些基本用法. 添加调试符号信息  co ...

  9. LVDS时序分析

    LVDS时序分析 2012年05月07日 11:48:08 Walle 阅读数:3355 标签: 平台工作   最近在调试基于telechip平台的LVDS驱动,一开始对该平台的LVDS时序不是很了解 ...

  10. MIUI7 系统应用精简(米5、红米note3)

    1.由于安装的部分应用在root后无法使用,所以自己一直不能使用MIUI的开发版本. 2.前段时间米5升级MIUI8,实在是用着不咋地,耗电,王者还掉帧,于是降级miui7 3.被逼走上了刷机路. 1 ...