剖析task_struct 数据结构

                                         粉丝不过W

     在 linux 中每一个进程都由 task_struct 数据结构来定义

     task_struct 就是 PCB。是对进程控制的唯一手段也是最有效的手段

       当我们调用 fork() 时, 系统会为我们产生一个 task_struct 结构,然后从父进程那里继承一些数据, 并把新的进程插入到进程树中, 以待进行进程管理

     因此了解 task_struct 的结构对于我们理解任务调度( 在 linux 中任务和进程是同一概念 )的关键

      进行剖析 task_struct 的定义之前,我们先按照我们的理论推一下它的结构

           进程状态 ,将纪录进程在等待,运行,死锁

           调度信息,由哪个调度函数调度,怎样调度

           进程的通讯状况

           因为要插入进程树,所以有联系父子兄弟的指针, 必须是 task_struct 型

           时间信息,如 计算好执行的时间, 以便 cpu 分配

           标号,决定改进程归属

           可 读写打开的一些文件信息

          进程上下文和内核上下文

          处理器上下文

          内存信息

       因为每一个 PCB 都是这样的, 只有这些结构, 才能满足一个进程的所有要求

struct task_struct
{
    /* -1 unrunnable, 0 runnable, >0 stopped: 
     * 该进程是否可以执行,还是可中断等信息
     */
    volatile long state;
    //每个任务标志(PF_*),定义如下
    unsigned long flags;    //进程号,在调用 fork()时给出
    int sigpending;         //进程上是否有待处理的信号
    mm_segment_t addr_limit;/*进程地址空间,区分内核进程与普通进程在内存存放的位置不同
                             *0 - 0xBFFFFFFF for user-thead
                             *0 - 0xFFFFFFFF for kernel-thread
                             */
    //调度标志,表示该进程是否需要重新调度,若非 0,则当从内核态返回到用户态,会发生调度
    volatile long need_resched;
    int lock_depth;    //锁深度
    long nice;        //进程的基本时间片
    //进程的调度策略,有三种,实时进程:SCHED_FIFO,SCHED_RR, 分时进程:SCHED_OTHER
    unsigned long policy;
    struct mm_struct *mm;    //进程内存管理信息
    int processor;
    //若进程未运行, cpus_runnable 的值是 0,否则是 1 这个值在运行队列被锁时更新
    unsigned long cpus_runnable, cpus_allowed;
    struct list_head run_list;    //指向运行队列的指针
    unsigned long sleep_time;    //进程的睡眠时间
    //用于将系统中所有的进程连成一个双向循环链表, 其根是 init_task
    struct task_struct *next_task, *prev_task;
    struct mm_struct *artive_mm;
    struct list_head local_pages;    //指向本地页面
    unsigned int allocation_order, nr_local_pages;
    struct linx_binfmt *binfmt;    //进程所运行的可执行文件的格式
    int exit_code,exit_signal;
    int pdeath_signal;    //父进程终止是向子进程发送的信号
    unsignal long personality;
    //Linux 可以运行由其他 UNIX 操作系统生成的符合 iBCS2 标准的程序
    int did_exec;
    pid_t pid;    //进程标识符,用来代表一个进程
    pid_t pgrp;    //进程组标识,表示进程所属的进程组
    pid_t tty_old_pgrp;    //进程控制终端所在的组标识
    pid_t session;    //进程的会话标识
    pid_t tgid;
    int leader;    //进程是否为会话主管
    struct task_struct *p_opptr, *p_pptr, *p_cptr, *p_ysptr, *p_osptr;
    struct list_head thread_group;    //线程链表
    struct task_struct *pidhash_next;    //用于将进程链入 HASH 表
    struct task_struct **pidhash_pprev;
    wait_queue_head_t wait_chldexit;    //供wait4()使用
    struct completion *vfork_done;    //供fork()使用
    unsigned long rt_priority;    //实时优先级,用它计算实时进程调度时的weight值
    /*
     * it_real_value, it_real_incr 用于 REAL 定时器,单位为 jiffies, 
     *系统根据 it_real_value设置定时器的第一个终止时间. 在定时器到期时,
     *向进程发送 SIGALRM 信号,同时根据it_real_incr 重置终止时间.
     * it_prof_value, it_prof_incr 用于 Profile 定时器,单位为 jiffies,
     *当进程运行时,不管在何种状态下,每个 tick 都使 it_prof_value 值减一,
     *当减到 0 时,向进程发送信号 SIGPROF,并根据 it_prof_incr 重置时间.
     * it_virt_value, it_virt_value 用于 Virtual 定时器,单位为 jiffies。
     *当进程运行时,不管在何种状态下,每个 tick 都使 it_virt_value 值减一当减到 0 时,
     *向进程发送信号 SIGVTALRM,根据it_virt_incr 重置初值。
     */
    unsigned long it_real_value, it_prof_value, it_virt_value;
    unsigned long it_real_incr, it_prof_incr, it_virt_incr;
    struct timer_list real_timer;    //指向实时定时器的指针
    struct tms times;    //记录进程的消耗的时间
    unsigned long start_time;    //进程创建的时间
    //记录进程在每个 CPU 上所消耗的用户态时间和核心态时间
    long per_cpu_utime[NR_CPUS], per_cpu_stime[NR_CPUS];
    //内存缺页和交换信息:
    unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap;
    //表示进程的虚拟地址空间是否允许换出
    int swappable:1;

    /*
     * 进程认证信息:
     *  uid,gid 为运行该进程的用户的用户标识符和组标识符,通常是进程创建者的 uid,gid
     *  euid, egid 为有效 uid,gid
     *  fsuid, fsgid 为文件系统 uid,gid,这两个 ID 号通常与有效 uid,gid 相等,
     *在检查对于文件系统的访问权限时使用他们
     *  suid, sgid 为备份 uid,gid
     */
    uid_t uid, euid, fsuid;
    gid_t gid, egid, fsgid;
    //记录进程在多少个用户组中
    int nproups;
    //记录进程所在的组
    gid_t groups[NGROUPS];
    //进程的权能,分别是有效位集合,继承位集合,允许位集合
    kernel_cap_t cap_effective, cap_inheritable, cap_permitted;
    int keep_capabilities:1;
    struct user_struct *user;
    //与进程相关的资源限制信息
    struct rlimit rlim[RLIM_NLIMITS];
    //是否使用 FPU
    unsigned short used_math;
    //进程正在运行的可执行文件名
    char comm[16];

    //文件系统信息
    int link_count, total_link_count;
    //NULL if no tty 进程所在的控制终端,如果不需要控制终端,则该指针为空
    struct tty_struct *tty;
    unsigned int locks;

    //进程间通信信息
    //进程在信号灯上的所有 undo 操作
    struct sem_undo *semundo;
    //当进程因为信号灯操作而挂起时,他在该队列中记录等待的操作
    struct sem_queue *semsleeping;
    //进程的 CPU 状态,切换时,要保存到停止进程的 task_struct 中
    struct thread_struct thread;
    //文件系统信息
    struct fs_struct *fs;
    //打开文件信息
    struct files_struct *files;
    //信号处理函数
    spinlock_t sigmask_lock;
    struct signal_struct *sig;
    //进程当前要阻塞的信号,每个信号对应一位
    sigset_t blocked;
    //进程上是否有待处理的信号
    struct sigpending pending;
    unsigned long sas_ss_sp;
    size_t sas_ss_size;
    int(*notifier)(void *priv);
    void *notifier_data;
    sigset_t *notifier_mask;
    u32 parent_exec_id;
    u32 self_exec_id;
    spinlock_t alloc_lock
    void *journal_info;
};

生成结果

猜你喜欢

转载自blog.csdn.net/qq_44226094/article/details/105517526