进程管理

  进程和文件是Linux操作系统的两个最基本的抽象。

  进程是处于执行期的程序,进程不仅仅局限于一段可执行程序代码,通常还包含其他资源,如打开的文件、挂起的信号、内核内部数据、处理器状态、进程地址空间及一个或者多个执行线程(thread of execution)、当然还包括用来存放全局变量的数据段等。

  线程(thread)是内核调度的对象,每个线程都拥有一个独立的程序计数器(PC指针)、函数调用栈和一组寄存器值。在Linux内核中,线程只不过是一种特殊的进程,线程仅仅被视为一个与其他进程共享某些资源的进程。而不管是线程还是进程,在Linux内核看来,都是一个任务(task),由一个task_struct结构体描述,即任务描述符,任务描述符通常位于进程内核栈的栈底,32位系统中其大小为1.7KB左右。

  进程是资源管理的最小单位,线程是程序执行的最小单位。

  进程提供了两种虚拟机制:虚拟处理器和虚拟内存。他们给进程一种假象,独占CPU且独享内存。

1.1 task_struct

  Linux内核把进程存放在叫做任务队列(task list)的双向循环链表中,链表中的每一项都是task_struct结构体变量,描述一个具体进程的所有信息。

  Linux通过slab分配器分配task_struct结构,这样能达到对象复用和缓存着色(cache coloring)的目的。其机制是Linux内核预先分配一组大小都为task_struct结构体大小的内存(结构体数组),当创建一个进程时,快速分配一个task_struct结构体项(数组成员)。

  在2.6以前的内核中,各个进程的task_struct存放在他们内核栈的尾端。

  Linux内核通过PID来唯一标识每个进程,PID的最大值默认为32768,即一个short int短整型数据。可以通过设置/proc/sys/kernel/pid_max提高上限。

  在Linux内核中,访问任务通常需要获得指向其task_struct结构体的指针,通过current宏可以实现。

1.2 进程状态

  task_struct->state记录进程状态:

  TASK_RUNNING(运行状态)——正在执行,或者在运行队列中等待执行

  TASK_INTERRUPTIBLE(可中断状态)——进程正在睡眠(或者阻塞),等待某些条件达成之后,内核就会把进程状态设置为运行

  TASK_UNINTERUPTIBLE(不可中断状态)——与可中断状态相比,不可中断状态对信号不作响应

  TASK_ZOMBIE(僵死状态)——该进程已经结束,但是其父进程还没有调用wait4()系统调用,即为了让父进程能够获知它的消息,子进程的task_struct仍然被保留着

  TASK_STOPPED(停止状态)——进程停止执行,通常发生在进程接收到SIGSTOP/SIGTSTP/SIGTTIN/SIGTTOU等信号时

  Linux系统中,用户态所有进程都是PID为1的init进程的后代,内核在系统启动的最后阶段启动init进程。

  Linux中每个进程都必须有一个父进程,每个进程可以拥有0~N个子进程。如果父进程在子进程之前退出,必须有机制来保证子进程可以找到继父,否则这些成为孤儿的进程就会在退出时永远处于僵死状态(保留task_struct结构体而空耗资源),白白浪费内存。解决的方法是给子进程在当前线程组找一个线程作为继父,如果不行,就让init进程做它们的继父。

1.3 内核线程(kernel thread)

  内核经常需要在后台执行一些操作,这种任务可以通过内核线程完成——独立运行在内核空间的标准进程。内核线程和普通进程的区别在于内核线程没有独立的地址空间(实际上它的mm指针被设置为NULL)。它只在内核空间运行,从来不切换到用户空间。内核线程和普通进程一样,可以被调度,也可以被抢占。

进程调度

  Linux内核为多任务可抢占式内核。进程调度就是负责CPU资源的分配,满足所有进程对CPU资源的需求。

  调度程序中最基本的数据结构是可执行队列(run queue),现代CPU一般都是多核架构,Linux内核为每一个核维护一个唯一的可执行队列。

Linux高级调试与优化——进程管理和调度的更多相关文章

  1. Linux高级调试与优化——内存管理

    1.物理地址和虚拟地址 Linux采用页表机制管理内存,32位系统中页大小一般为4KB,物理内存被划分为连续的页,每一个页都有一个唯一的页号. 为了程序的的可移植性,进程往往需要运行在flat mem ...

  2. Linux高级调试与优化——gdb调试命令

    番外 2019年7月26日至27日,公司邀请<软件调试>和<格蠹汇编——软件调试案例集锦>两本书的作者张银奎老师进行<Linux高级调试与优化>培训,有幸聆听张老师 ...

  3. [Wolfgang Mauerer] 深入linux 内核架构 第二章 进程管理与调度【未完】

     作为Linux开发爱好者,从事linux 开发有三年多时间.做过bsp移植,熟悉u-boot代码执行流程:看过几遍<linux 设备驱动程序开发>,分析过kernel启动流程,写过驱动, ...

  4. Linux内核入门到放弃-进程管理和调度-《深入Linux内核架构》笔记

    进程优先级 硬实时进程 软实时进程 普通进程 O(1)调度.完全公平调度器 抢占式多任务处理(preemptive multitasking):各个进程都分配到一定的时间段可以执行.时间段到期后,内核 ...

  5. Linux高级调试与优化——用户态堆

    内存问题是软件世界的住房问题 嵌入式Linux系统中,物理内存资源通常比较紧张,而不同的进程可能不停地分配和释放不同大小的内存,因此需要一套高效的内存管理机制. 内存管理可以分为三个层次,自底向上分别 ...

  6. Linux高级调试与优化——信号量机制与应用程序崩溃

    背景介绍 Linux分为内核态和用户态,用户态通过系统调用(syscall)进入内核态执行. 用户空间的glibc库将Linux内核系统调用封装成GNU C Library库文件(兼容ANSI &am ...

  7. Linux高级调试与优化——ptrace

    ptrace (process trace) #include <sys/ptrace.h> long ptrace(enum __ptrace_request request, pid_ ...

  8. Linux高级调试与优化——同时抓取coredump和maps文件

    Linux内核源码 Documentation/sysctl/kernel.txt core_pattern: core_pattern: core_pattern is used to specif ...

  9. Linux高级调试与优化——内存泄漏实战分析

    最近在整理Linux调试方面的文档,正好碰到了一个内存泄漏踩栈的问题,借此机会记录一下分析过程. 首先,发现问题之后,赶紧看一下产生coredump文件没有,果不其然,产生了coredump,果断上g ...

随机推荐

  1. Centos7:配置防火墙

    firewalld的基本使用 启动: systemctl start firewalld 关闭:systemctl stop firewalld 查看状态: systemctl status fire ...

  2. windows下xgboost安装到python

    初始环境 在安装之前,我的anaconda2已经安装好,git也有装好 下载相对应的xgboost.dll文件 下载地址 Installing the Python Wrapper for me: x ...

  3. SpringMVC基础02——HelloWorld

    1.搭建环境 博主使用的环境是IDEA2017.3,首先我们需要创建一个maven项目父项目,创建一个project,选择maven,之后点击next 添写当前项目的坐标,之后点击next 填写项目名 ...

  4. 浙大数据结构课后习题 练习一 7-1 Maximum Subsequence Sum (25 分)

    Given a sequence of K integers { N​1​​, N​2​​, ..., N​K​​ }. A continuous subsequence is defined to ...

  5. linux PHP空间设置GZIP压缩网页方法!

    网站设置GZIP压缩,缩小网页体积,让网站访问速度更快!方法很简单,只需要在你的网站根目录建立.htaccess文件并输入以下代码: 新建-记事本-复制以下代码:(如果网站已有.htaccess文件, ...

  6. windows开启ftp服务

    1.启动或关闭windows-->internet information services-->ftp服务器   选中 2.此电脑右键-->管理-->服务和应用程序--> ...

  7. 第五章 动画 48:动画-使用transition-group元素实例列表动画

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...

  8. Python可迭代序列反转总结

    字符串反转 示例:s = "hello" 方法一:使用切片 def reversed_str(s): return s[::-1] 方法二:使用reversed # 字符串 -&g ...

  9. Spring整合MongoDB(转)

    1.认识Spring Data MongoDB 之前还的确不知道Spring连集成Nosql的东西都实现了,还以为自己又要手动封装一个操作MongoDB的API呢,结果就发现了Spring Data ...

  10. react浏览器回退按钮的时候传递参数

    本来是有这个需求的,但是后来发现回退不也是到某个页面吗?接下来就使用了redux,真香啊,不管用户怎么操作,你到这个界面都给他一个值就完事了,没有就不给他这个值. 哈哈哈,公司框架使用umi.上代码 ...