Linux内核进程管理基本概念-进程、运行队列、等待队列、进程切换、进程调度

下面简述一些基本概念,以及对内核代码做最初步的了解;

 

一 Linux内核进程管理基础

 

    Linux 内核使用 task_struct 数据结构来关联所有与进程有关的数据和结构,Linux 内核所有涉及到进程和程序的所有算法都是围绕该数据结构建立的,是内核中最重要的数据结构之一。
    该数据结构在内核文件 include/linux/sched.h 中定义,是个很大的结构体;在 3.8 的内核中,该数据结构有 380 行。

    Linux中进程ID有如下类型:PID,TGID,PGID,SID;
    如果考虑进程之间有复杂的关系,如线程组、进程组、会话组,这些组均有组ID;分别为 TGID、PGID、SID;

    内核中使用下面两个函数来实现分配和回收PID:
    static int alloc_pidmap(struct pid_namespace *pid_ns);
    static void free_pidmap(struct upid *upid);

    Linux中增加命名空间这个概念是为了虚拟化和方便管理。
    进程命名空间;作用:linux通过命名空间管理进程号,在不同的namespace中可以有pid相同的进程;进程命名空间是一个父子结构,子空间对于父空间可见。

 

二 task_struct结构

    Linux用task_struct结构表示进程,2.6内核的task_struct结构相对于2.4内核有很大变化。
    该结构记录了进程的重要信息。


    与进程调度有关的信息包括:


    1 state

    进程状态;一个进程共有7种可能状态,分别是:TASK_RUNNING、TASK_INTERRUPTIBLE、TASK_UNINTERRUPTIBLE、TASK_STOPPED、TASK_TRACED、EXIT_ZOMBIE和EXIT_DEAD;

    2 timestamp

    进程发生调度事件的时间(单位是 nanosecond)。


    3 prio, static_prio

    进程的优先级和静态优先级。Prio表示进程的动态优先级,与2.4内核中goodness()的计算结果相当。在0~MAX_PRIO-1之间取值(MAX_PRIO 定义为 140),其中0~MAX_RT_PRIO-1(MAX_RT_PRIO定义为100)属于实时进程范围,MAX_RT_PRIO~MX_PRIO-1属于非实时进程。数值越大,表示进程优先级越小。static_prio表示进程的静态优先级,相当于2.4内核中的nice。一个进程的初始时间片的大小完全取决于它的静态优先级。


    4 sleep_avg

    进程的平均等待时间,在0到NS_MAX_SLEEP_AVG之间取值,初值为0,相当于进程等待时间与运行时间的差值。它是动态优先级计算的关键因子,sleep_avg越大,计算出来的进程优先级也越高。


    5 interactive_credit

    该变量表示进程的交互程度。在-CREDIT_LIMIT到CREDIT_LIMIT+1之间取值,初始值为0,而后根据不同的条件加1减1,一旦该值超过CREDIT_LIMIT,即表示该进程是交互进程。


    6 array

    指向当前CPU的active就绪进程队列。


    7 run_list

     进程通过这个list_head变量连接自己到prio_array数组中queue队列,这样相同优先级的进程连接成一个双向列表,表头为prio_array结构中的queue变量。

 

三 进程运行队列(就绪队列)

 

    Linux内核定义了一个list_head数据结构,字段head和prev分别表示通用的双向链表向前和向后的指针元素。每个task_struct包含一个list_head类型的run_list字段。

    在Linux2.4内核中,就绪进程队列是一个全局数据结构,所有的处理器共享同一个队列。调度器对它的所有操作都会因全局自旋锁而导致系统各个处理机之间的等待,使得就绪队列成为一个明显的瓶颈。2.6内核重新设计就绪进程队列为每CPU的数据结构,每个处理器都维护一个自己的就绪队列,这样就避免了2.4内核中的SMP性能瓶颈。

 

    每个CPU的就绪进程队列由一个struct runqueue结构描述,其中最关键的子结构是优先级就绪数组。

    描述优先级就绪数组的数据结构是prio_array_t。

 

四 进程等待队列

 

    Linux等待队列在内核中有很多用途,尤其在中断处理、进程同步以及定时。例如等待一个磁盘操作的终止,等待释放资源,或等待时间经过的固定的时间间隔。

    

等待队列由双向链表实现。

 

struct __wait_queue_head {  

        spinlock_t lock;  

        struct list_head task_list;  

};  //等待队列的头结点

typedef struct__wait_queue_head wait_queue_head_t;

 

struct __wait_queue {

    unsigned int flags; //标识是互斥进程还是非互斥进程 

        #define WQ_FLAG_EXCLUSIVE      0x01  /* 表示等待进程想要被独占地唤醒  */  

        void *private;  /* 指向等待进程的task_struct实例 */          
        wait_queue_func_t func;      /* 用于唤醒等待进程      */          
       sruct list_head task_list;  /* 用于链表元素,将wait_queue_t链接到wait_queue_head_t */ 

};

typedef struct__wait_queue wait_queue_t;  

 

五 进程切换

 

    内核必须有能力挂起正在CPU上运行的进程,并恢复以前挂起的某个进程执行。这种行为称为进程切换、任务切换或上下文切换。
    尽管每个进程都拥有属于自己的地址空间,但所有进程必须共享CPU寄存器。在恢复一个进程的执行之前,内核必须确保每个寄存器装了挂起进程时的值。
    进程恢复前必须装入寄存器的一组数据称为硬件上下文,它的一部分存在TSS段,而剩余部分存放在内核态堆栈中。

    
    每个进程描述符包含一个类型thread_struct的thread字段,来保存进程切换时的硬件上下文。


    进程切换主要有两大步:1、切换全局页表项;2、切换内核堆栈和硬件上下文。这个切换工作由context_switch()完成。其中switch_mm完成第一步,而switch_to和__switch_to()主要完成第二步。更详细的,__switch_to()主要完成硬件上下文切换,switch_to主要完成内核堆栈切换。

        schedule() --> context_switch() --> switch_to --> __switch_to()

 

六 进程调度

 

进程调度由schedule()函数实现。

Linux的进程调度是基于分时技术(time-sharing)。允许多个进程“并发”运行就意味着CPU 的时间被粗略地分成“片”,给每个可运行进程分配一片。

调度策略也是基于依照优先级排队的进程。
在Linux 中,进程的优先级是动态的。调度程序跟踪进程做了些什么,并周期性地调整它们的优先级。在这种方式下,在较长的时间间隔内没有使用CPU的进程,通过动态地增加它们的优先级来提升它们。相应地,对于已经在CPU上运行了较长时间的进程,通过减少它们的优先级来处罚它们。每个进程在创建之初有一个基本的优先级,执行期间调度系统会动态调整它的优先级,交互性高的任务会获得一个高的动态优先级,而交互性低的任务获得一个低的动态优先级。

Linux操作系统支持多进程,进程控制块PCB(Process ControlBlock)是系统中最为重要的数据结构之一。用来存放进程所必需的各种信息,PCB用结构task_struct来表示,包括进程的类型、进程状态、优先级、时钟信息等。

Linux系统中,进程调度操作由schedule()函数执行,这是一个只在内核态运行的函数,函数代码为所有进程共享。

 


更多详情自行参阅如下;
https://www.cnblogs.com/hazir/p/linux_kernel_pid.html
https://blog.csdn.net/sdulibh/article/details/50827911
https://www.jianshu.com/p/c1c5e347d64c
https://blog.csdn.net/lsjseu/article/details/9249665
 

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值