Linux内核分析 读书笔记 (第三章)

时间:2022-11-22 14:00:32

第三章 进程管理

3.1 进程

1.进程:

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

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

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

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

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

4.几个函数

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

3.2 进程描述符及任务结构

  1. 内核把进程的列表存放在叫做任务队列的双向循环链表中。
  2. 链表中的每一项都是进程描述符。
  3. 进程描述符的类型为task_struct。Linux内核分析  读书笔记 (第三章)

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函数,然后让进程开始运行

Linux内核分析  读书笔记 (第三章)

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

3.3 vfork()

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

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

Linux内核分析  读书笔记 (第三章)

3.4 线程在Linux中的实现

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

3.4.1 创建线程

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

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

3.4.2 内核线程

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

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

3.5 进程终结

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

Linux内核分析  读书笔记 (第三章)

Linux内核分析  读书笔记 (第三章)

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&rpar;概念与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. 用js写的比较简单3D旋转效果

    HTML代码如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quot ...

  2. Linux下mongodb的安装及启动

    安装 1>设置mongoDB目录 cd /home/apps 附:centOS下创建目录命令  mkdir /home/apps 2>下载mongodb curl -O http://fa ...

  3. SQL 比较时间大小

    比较字符串类型的时间大小 数据库中的时间是varchar类型的,MySql使用CURDATE()来获取当前日期,SqlServer通过GETDATE()来获取当前日期 1. 直接使用字符串来比较 注意 ...

  4. book publisher and study

    http://www.apress.com/ https://pragprog.com/ https://www.packtpub.com/ http://www.howzhi.com/

  5. MFC上下浮动与渐入渐出消息提示框实现

    类似QQ与360软件,消息提示有两种.上下浮动.渐入渐出. 1.上下浮动提示框实现 机制,定时器响应上下浮动消息. 主要API:MoveWindow. 源码如下UpDownTipDlg.h.UpDow ...

  6. S3 Browser 配置指南

    S3 Browser 相对于s3cmd是一个很方便的操作S3的图形化界面工具. 以下是配置步骤: 下载网址:http://s3browser.com/ keygen破解版: http://appdol ...

  7. Linux Git用户组

    Vivien: groupadd admin useradd -d /home/bill -s /bin/bash -m bill 用户组 查看用户列表 cat /etc/passwd 或者 cat ...

  8. Python字符串拼接的6种方法

    如有其他字符串拼接方法 欢迎留言提出哦 (示例版本为Py2) 1. 加号 第一种,有编程经验的人,估计都知道很多语言里面是用加号连接两个字符串,Python里面也是如此直接用 “+” 来连接两个字符串 ...

  9. centos6&period;4安装GCC

    1. Last login: Mon Aug  4 11:46:15 2014 from 10.3.7.128 [jifeng@jifeng04 ~]$ ls hadoop  jdk1.7.0_45  ...

  10. Android SQLiteOpenHelper Sqlite数据库升级onUpgrade

    Android Sqlite数据库升级,在Android APP开发之中,非常常见: 在确定原来的数据库版本号之后,在原来数据库版本号+1,就会执行onUpgrade方法,进行数据库升级操作: 在on ...