zoukankan      html  css  js  c++  java
  • Linux进程分析

    1. 介绍

    进程是系统进行资源分配的基本单位,而线程则是系统调度和执行的基本单位;通常认为,一个进程包含一个或多个线程

    进程是程序的一个执行过程,程序是一个静态文件存储在计算机系统的硬盘等存储空间中,而进程则是处于动态条件下由操作系统维护的系统资源管理实体。

    09194625-3402ef9dae8b4fa1a46657ac23e82505 

    2. 数据结构

    在Linux中,用struct task_struct来表示一个进程,通常称为进程控制块

    task_struct,称为进程控制块,表示一个进程,主要数据结构如下

    成员 作用
    char comm[TASK_COMM_LEN] 程序名
    volatile long state;
    int exit_state;
    进程状态, 对于state, 值为TASK_RUNNING,TASK_INTERRUPTIBLE等
    当进程释放资源时, exit_state有效, 其值为EXIT_ZOMBIE, EXIT_DEAD
    pid_t pid 进程标识符, 用于标识一个进程
    pid_t tgid 线程组的主进程号
    void *stack 指向进程内核栈, struct thread_info (check thread_union)
    unsigned int flags 进程的标记, 如PF_STARTING

    struct task_struct *real_parent;
    struct task_struct *parent;
    struct list_head children;
    struct list_head sibling;
    struct task_struct *group_leader;

    表示进程亲属关系的成员:
    real_parent指向其父进程, 若创建它的父进程不再存在, 则指向init进程。
    parent指向其父进程, 当它终止时, 必须向它的父进程发送信号. 通常与real_parent相同
    children表示链表的头部, 链表中的所有元素都是它的子进程。
    sibling用于把当前进程插入到兄弟链表中
    group_leader指向其所在进程组的领头进程

    unsigned int ptrace;
    struct list_head ptraced;
    struct list_head ptrace_entry;
    unsigned long ptrace_message;
    siginfo_t *last_siginfo;

    用于ptrace系统调用:
    成员ptrace表明是否需要被被跟踪(0不被跟踪)
    它的可能取值如PT_PTRACED等

    int prio, static_prio, normal_prio;
    unsigned int rt_priority;
    const struct sched_class *sched_class;
    struct sched_entity se;
    struct sched_rt_entity rt;
    unsigned int policy;
    cpumask_t cpus_allowed;

    用于进程调度
    static_prio用于保存静态优先级,可以通过nice系统调用来进行修改。
    rt_priority用于保存实时优先级。
    normal_prio的值取决于静态优先级和调度策略。
    prio用于保存动态优先级。
    policy表示进程的调度策略
    sched_class结构体表示调度类
    se和rt都是调用实体: 一个用于普通进程, 一个用于实时进程
    cpus_allowed用于控制进程可以在哪里处理器上运行。
    struct mm_struct *mm, *active_mm 进程地址空间
    mm指向进程所拥有的内存描述符
    active_mm指向进程运行时所使用的内存描述符
    - 对于普通进程而言, 这两个指针变量的值相同
    - 对于内核线程, 它们的mm成员总是为NULL

    int link_count, total_link_count;
    struct fs_struct *fs;
    struct files_struct *files;

    fs用来表示进程与文件系统相关的信息
    files表示进程当前打开的文件

    3. 进程分类

    首先,Linux实际上是并不区分进程和线程,都是基于task_struct来描述和调度,只是两者只是对资源的占用不同;用户线程和用户进程的区别在于是否拥有独立的数据段和堆栈

    Linux下分为内核线程,轻量级进程及用户线程三种线程

    内核线程: 内核线程通常完成内核特定的任务, 其调度由内核负责, 运行在内核态, 执行的是内核中的函数
    轻量级进程: 也称LWP, 是一种由内核支持的用户线程,它是基于内核线程的高级抽象;每个LWP由一个内核线程支持
    用户线程: 指不需要内核支持而完全建立在用户空间的线程库,用户线程的建立、同步、销毁及调度完全在用户空间完成

    TIP: 用ps命令查看,名称中加"[]"的进程,就是内核线程

    用户线程/POSIX线程在Linux上的实现有LinuxThreads和NPTL

    4. 进程组织

    在linux系统中,所有进程都是由init进程派生而来;init进程的进程描述符由init_task静态生成.

    4.1 进程链表

    进程关系是由双向链表tasks组织成的,链表的头和尾都为init_task

    struct list_head tasks;

    12214436-0690267d0c8441f6ac5a505720107dc6

    内核提供了一些宏来操作进程

    /* 获取下一个进程 */
    #define next_task(p) \ 
        list_entry_rcu((p)->tasks.next, struct task_struct, tasks)
    
    /* 便利进程链表 */
    #define for_each_process(p) \ 
    for (p = &init_task; (p = next_task(p)) != &init_task; )

    4.2 运行队列

    Linux将处于可运行状态(即在TASK_RUNNING状态)的进程组织成运行队列
    队列的标志有两个:一个是"空闲进程" idle_task、一个是队列的长度nr_running

    nr_running,也就是系统中处于可运行状态(TASK_RUNNING)的进程数目
    若nr_running为0,就表示队列中只有空闲进程

    5. 进程调度

    在Linux中,进程调度由schedule()来触发

    schedule
      __schedule
        context_switch
          switch_to
            __switch_to

    5.1 进程状态

    通常来说有如下四种进程状态

     - TASK_RUNNING:         可运行状态, 处于该状态的进程可以被调度执行而成为当前进程
    - TASK_INTERRUPTIBLE:   可中断的睡眠状态, 可在资源有效、或通过信号或定时中断唤醒
    - TASK_UNINTERRUPTIBLE: 不可中断的睡眠状态, 处于该状态的进程仅当所需资源有效时被唤醒
    - TASK_DEAD:            死亡状态, 进程结束且已释放资源, 但其task_struct仍未释放

    5.2 调度方式

    Linux采用"有条件的可剥夺"调度方式

    对于普通进程,当其时间片结束时,调度程序挑选出下一个处于TASK_RUNNING状态的进程作为当前进程
    对于实时进程,若其优先级足够高,则会从当前的运行进程中抢占CPU成为新的当前进程

    5.3 调度策略

    调度策略用来区分普通进程和实时进程,以满足实时进程的要求

    Linux有三种调度策略,由成员变量policy来指定:
    @1 SCHED_NORMAL: 面向普通进程, 分时调度策略, 是进程的默认的调度策略
    @2 SCHED_FIFO: 先到先服务调度策略, 是一种实时调度策略, 用于运行所需时间比较短的实时进程
    @3 SCHED_RR: 时间片轮转方式, 实时调度策略, 用于运行所需时间比较长的实时进程
    @4 SCHED_BATCH: 主要用于批处理进程

    进程的调度策略从父进程那里继承,也可以通过sched_setscheduler()函数来修改

    5.4 进程优先级

    Linux进程优先级包括动态优先级、静态优先级 、实时优先级

    参考:
    <Linux进程管理剖析>

  • 相关阅读:
    idea快捷键总结
    将对象序列化和反序列化
    在Springmvc中获取properties属性
    配置springmvc在其他类中(spring容器外)获取注入bean
    redis学习之三配置文件redis.conf 的含义
    redis学习之二from github
    敏捷开发方法XP的12个最佳实践
    IIS-网站发布之后访问HTTP 错误 403.14
    IIS-将iis直接指向.net代码会出现错误
    HTTP 错误 500.24
  • 原文地址:https://www.cnblogs.com/hzl6255/p/2843415.html
Copyright © 2011-2022 走看看