基于Linux 4.5的进程模型与调度器分析(2)

    在内核中,这四个哈希表一共占16个页框,也就是每个哈希表占4个页框,他们每个可以拥有2048个表项,内核会把把这四个哈希表的地址保存到pid_hash数组中。现在问题来了,拿pids[PIDTYPE_TGID]为例,怎么在2048个表项中保存32767个PID值,其实内核会对每个已经分配的PID值进行一个处理,得到的结果的数值就是对应的表项,处理结果相同的PID被串成一个链表,如下:

基于Linux 4.5的进程模型与调度器分析

    当我们使用"kill 29384"命令时,内核会根据29384处理得出199,然后以199为下标,获取PID哈希表中对应的链表头,并在此链表中找出PID=29384的进程。在进程描述符(thread_info)的*task中使用struct pid_link pids[PIDTYPE_MAX]链入这四个哈希表。对于另外三个哈希表,道理一样。

  1.4进程状态的转换:

    进程的状态用state表示,简单表示有以下3种:

volatile long state;    /* -1 unrunnable, 0 runnable, >0 stopped */

    其中详细有以下状态:

/*
 * Task state bitmask. NOTE! These bits are also
 * encoded in fs/proc/array.c: get_task_state().
 *
 * We have two separate sets of flags: task->state
 * is about runnability, while task->exit_state are
 * about the task exiting. Confusing, but this way
 * modifying one set can't modify the other one by
 * mistake.
 */
#define TASK_RUNNING            0
#define TASK_INTERRUPTIBLE      1
#define TASK_UNINTERRUPTIBLE    2
#define __TASK_STOPPED          4
#define __TASK_TRACED          8

/* in tsk->exit_state */
#define EXIT_DEAD              16
#define EXIT_ZOMBIE            32
#define EXIT_TRACE              (EXIT_ZOMBIE | EXIT_DEAD)
 
/* in tsk->state again */
#define TASK_DEAD              64
#define TASK_WAKEKILL          128    /** wake on signals that are deadly **/
#define TASK_WAKING            256
#define TASK_PARKED            512
#define TASK_NOLOAD            1024
#define TASK_STATE_MAX          2048

/* Convenience macros for the sake of set_task_state */
#define TASK_KILLABLE          (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE)
#define TASK_STOPPED            (TASK_WAKEKILL | __TASK_STOPPED)
#define TASK_TRACED            (TASK_WAKEKILL | __TASK_TRACED)

1.4.1五种互斥状态:      

state域能够取5个互为排斥的值(简单来说就是这五个值任意两个不能一起使用,只能单独使用):

状态   描述  
TASK_RUNNING   表示进程要么正在执行,要么正要准备执行(已经就绪),正在等待cpu时间片的调度  
TASK_INTERRUPTIBLE   进程因为等待一些条件而被挂起(阻塞)而所处的状态。这些条件主要包括:硬中断、资源、一些信号……,一旦等待的条件成立,进程就会从该状态(阻塞)迅速转化成为就绪状态TASK_RUNNING  
TASK_UNINTERRUPTIBLE   意义与TASK_INTERRUPTIBLE类似,除了不能通过接受一个信号来唤醒以外,对于处于TASK_UNINTERRUPIBLE状态的进程,哪怕我们传递一个信号或者有一个外部中断都不能唤醒他们。只有它所等待的资源可用的时候,他才会被唤醒。这个标志很少用,但是并不代表没有任何用处,其实他的作用非常大,特别是对于驱动刺探相关的硬件过程很重要,这个刺探过程不能被一些其他的东西给中断,否则就会让进城进入不可预测的状态  
TASK_STOPPED   进程被停止执行,当进程接收到SIGSTOP、SIGTTIN、SIGTSTP或者SIGTTOU信号之后就会进入该状态  
TASK_TRACED   表示进程被debugger等进程监视,进程执行被调试程序所停止,当一个进程被另外的进程所监视,每一个信号都会让进城进入该状态  

 1.4.2二种终止状态:      

      这两个附加的进程状态既可以被添加到state域中,又可以被添加到xit_state域中。只有当进程终止的时候,才会达到这两种状态:

状态   描述  
EXIT_ZOMBIE   进程的执行被终止,但是其父进程还没有使用wait()等系统调用来获知它的终止信息,此时进程成为僵尸进程  
EXIT_DEAD   进程的最终状态  
    1.4.3睡眠状态:      

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/12804.html