linux中的PCB---task_struct

来源:互联网 发布:成都数据恢复价格表 编辑:程序博客网 时间:2024/05/16 18:11

   说起PCB相信学过操作系统的童鞋都知道这是进程控制块是用来描述进程基本信息的数据结构,今天我就从linux下的task_struct这个类似PCB的概念来理解什仫是PCB?以及PCB存在什仫样的基本信息?

    要了解PCB,首先需要了解什仫是进程?

一.进程的概念

 在之前学过的操作系统课本上是这样描述进程的,进程是程序的一次动态执行的过程,进程=程序+数据+PCB(这样官方的描述真的可以让我们理解什仫是进程吗?反正我不太理解!!!但是学习的时候为了考试也就是记住就好了),现在重新学习linux下的操作系统却让我有了不一样的认识。

    在OS操作系统的观点下:进程是程序的一个执行实例;是正在执行的程序;能够分配处理器并由处理器执行的实体;在内核的观点下:担当分配系统资源(CPU时间,内存)的实体.

 总结:

     进程是加载到物理内存中的程序,操作系统给该应用程序创建一系列数据结构PCB,是动态的文件,是被内存管理起来通过页表映射到物理内存中的数据结构.

二.进程控制块---PCB

 进程控制块是描述进程的基本信息的数据结构,那仫为什仫需要进程控制块呢?一个进程被创建的标志是什仫?在单批道处理器中我们每次只能处理一个进程,我们是如何知道正在使用CPU的是哪个进程?当该进程执行完毕之后我们是如何选择哪个进程将被执行?假如一个正在被执行的进程由于时间片或者挂起等操作被迫让出CPU的使用权当该未执行完的进程下一次被CPU调度的时候如何知道执行到什仫位置?。。。此时就需要进程控制块来解决这些问题了.

     为了处理以上这些问题,PCB至少应该存在以下几种信息:进程标识(是进程的唯一标识,PID);进程的优先级(决定哪个进程将被处理机调度);记录进程的上下文信息(当再次被处理机调度的时候可快速恢复);程序和数据的地址等等各种信息,下文将更加详细的介绍task_stcuct的数据结构.

     总之,在进程的整个生命周期中进程控制块都起着不可或缺的作用,下面就让我们来理解task_struct的基本信息

 三.linux中的PCB---task_struct

     每个进程在内核中都有一个进程控制块(PCB)来维护进程相关的信息,Linux内核的进程控制块是task_struct结构体,task_struct是Linux内核的一种数据结构,它会被装载到RAM里并且包含着进程的信息

     每个进程都把它的信息放在 task_struct 这个数据结构里,task_struct 包含了以下内容:

      

      1).标示符 : 描述本进程的唯一标示符,用来区别其他进程。      2).状态 :任务状态,退出代码,退出信号等。      3).优先级 :相对于其他进程的优先级。      4).程序计数器:程序中即将被执行的下一条指令的地址。      5).内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针      6).硬件上下文数据:进程执行时处理器的寄存器中的数据。      7).I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。      8).记账信息:可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。


  

四.剖析task_struct

     task_struct的功能类似PCB,可以在include/linux/sched.h中找到它,下面直接附上该头文件的链接:

     http://lxr.free-electrons.com/source/include/linux/sched.h

      task_struct的实现可以参考以上的源码连接,下面介绍一下task_struct的基本成员吧!!!

1.进程状态

       

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


     上面这个变量就是描述进程状态的成员,volatile关键字是降低编译器对代码的优化,使得state变量从内存而不是寄存器中读取数据;保证了对操作系统状态实时访问的稳定性.

     state成员的可能取值如下:

     

 /*  * 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)




 2.进程标识符
          
pid_t pid;     //进程的标识符pid_t tgid;    //线程组标识符pid_t ppid    //父进程的标识符,在linux下一般为bash



    当然task_struct中还存在其他的标识符,在这里只列举常见的.
    进程标识符是为了区分各个进程,是唯一的标识;由于Unix程序员希望同一组进程具有相同的pid所以引入tgid
3.进程标记符
       
unsigned int flags; /* per process flags, defined below */ 

      flags反应进程的状态信息,用于内核识别当前进程的状态,它的取值范围如下:

      

 /** Per process flags*/#define PF_EXITING      0x00000004      /* getting shut down */#define PF_EXITPIDONE   0x00000008      /* pi exit done on shut down */#define PF_VCPU         0x00000010      /* I'm a virtual CPU */#define PF_WQ_WORKER    0x00000020      /* I'm a workqueue worker */#define PF_FORKNOEXEC   0x00000040      /* forked but didn't exec */#define PF_MCE_PROCESS  0x00000080      /* process policy on mce errors */#define PF_SUPERPRIV    0x00000100      /* used super-user privileges */#define PF_DUMPCORE     0x00000200      /* dumped core */#define PF_SIGNALED     0x00000400      /* killed by a signal */#define PF_MEMALLOC     0x00000800      /* Allocating memory */#define PF_NPROC_EXCEEDED 0x00001000    /* set_user noticed that RLIMIT_NPROC was exceeded */#define PF_USED_MATH    0x00002000      /* if unset the fpu must be initialized before use */#define PF_USED_ASYNC   0x00004000      /* used async_schedule*(), used by module init */#define PF_NOFREEZE     0x00008000      /* this thread should not be frozen */#define PF_FROZEN       0x00010000      /* frozen for system suspend */#define PF_FSTRANS      0x00020000      /* inside a filesystem transaction */#define PF_KSWAPD       0x00040000      /* I am kswapd */#define PF_MEMALLOC_NOIO 0x00080000     /* Allocating memory without IO involved */#define PF_LESS_THROTTLE 0x00100000     /* Throttle me less: I clean memory */#define PF_KTHREAD      0x00200000      /* I am a kernel thread */#define PF_RANDOMIZE    0x00400000      /* randomize virtual address space */#define PF_SWAPWRITE    0x00800000      /* Allowed to write to swap */#define PF_NO_SETAFFINITY 0x04000000    /* Userland is not allowed to meddle with cpus_allowed */#define PF_MCE_EARLY    0x08000000      /* Early kill for mce process policy */#define PF_MUTEX_TESTER 0x20000000      /* Thread belongs to the rt mutex tester */#define PF_FREEZER_SKIP 0x40000000      /* Freezer should not count it as freezable */#define PF_SUSPEND_TASK 0x80000000      /* this thread called freeze_processes and should not be frozen */

       

4.表示进程亲属关系的成员

       

/* * pointers to (original) parent process, youngest child, younger sibling, * older sibling, respectively.  (p->father can be replaced with * p->real_parent->pid) */struct task_struct __rcu *real_parent; /* real parent process */struct task_struct __rcu *parent; /* recipient of SIGCHLD, wait4() reports *//* * children/sibling forms the list of my natural children */struct list_head children;      /* list of my children */struct list_head sibling;       /* linkage in my parent's children list */struct task_struct *group_leader;       /* threadgroup leader */

       


5.ptrace系统调用

        ptrace提供了一种父进程,用来控制子进程的运行,常被用于断点调试,当被设置为0时则不需要追踪.

        

/* * Ptrace flags * * The owner ship rules for task->ptrace which holds the ptrace * flags is simple.  When a task is running it owns it's task->ptrace * flags.  When the a task is stopped the ptracer owns task->ptrace. */#define PT_SEIZED       0x00010000      /* SEIZE used, enable new behavior */#define PT_PTRACED      0x00000001#define PT_DTRACE       0x00000002      /* delayed trace (used on m68k, i386) */#define PT_PTRACE_CAP   0x00000004      /* ptracer can follow suid-exec */#define PT_OPT_FLAG_SHIFT       3/* PT_TRACE_* event enable flags */#define PT_EVENT_FLAG(event)    (1 << (PT_OPT_FLAG_SHIFT + (event)))#define PT_TRACESYSGOOD         PT_EVENT_FLAG(0)#define PT_TRACE_FORK           PT_EVENT_FLAG(PTRACE_EVENT_FORK)#define PT_TRACE_VFORK          PT_EVENT_FLAG(PTRACE_EVENT_VFORK)#define PT_TRACE_CLONE          PT_EVENT_FLAG(PTRACE_EVENT_CLONE)#define PT_TRACE_EXEC           PT_EVENT_FLAG(PTRACE_EVENT_EXEC)#define PT_TRACE_VFORK_DONE     PT_EVENT_FLAG(PTRACE_EVENT_VFORK_DONE)#define PT_TRACE_EXIT           PT_EVENT_FLAG(PTRACE_EVENT_EXIT)#define PT_TRACE_SECCOMP        PT_EVENT_FLAG(PTRACE_EVENT_SECCOMP)#define PT_EXITKILL             (PTRACE_O_EXITKILL << PT_OPT_FLAG_SHIFT)#define PT_SUSPEND_SECCOMP      (PTRACE_O_SUSPEND_SECCOMP << PT_OPT_FLAG_SHIFT)/* single stepping state bits (used on ARM and PA-RISC) */#define PT_SINGLESTEP_BIT       31#define PT_SINGLESTEP           (1<<PT_SINGLESTEP_BIT)#define PT_BLOCKSTEP_BIT        30#define PT_BLOCKSTEP            (1<<PT_BLOCKSTEP_BIT)



6.进程调度

       

int prio, static_prio, normal_prio;unsigned int rt_priority;

成员描述信息static_prio用来保存静态优先级,可以调用nice系统直接来修改取值范围为100~139rt_priority用来保存实时优先级,取值范围为0~99prio用来保存动态优先级normal_prio它的值取决于静态优先级和调度策略


7.进程的地址空间

         

struct mm_struct *mm, *active_mm;/* per-thread vma caching */u32 vmacache_seqnum;struct vm_area_struct *vmacache[VMACACHE_SIZE];#if defined(SPLIT_RSS_COUNTING)struct task_rss_stat    rss_stat;#endif/*  http://lxr.free-electrons.com/source/include/linux/sched.h?V=4.5#L1484  */#ifdef CONFIG_COMPAT_BRKunsigned brk_randomized:1;#endif

成员描述信息mm进程所拥有的内存空间描述符,对于内核线程的mm为NULLactive_mm指进程运行时所使用的进程描述符rss_stat被用来记录缓冲信息如果当前内核线程被调度之前运行的也是另外一个内核线程时候,那么其mm和avtive_mm都是NULL

    

     总结:对于linux中的task_struct只介绍这些,有兴趣的童鞋可以自己参考上面的给出的源码连接进行剖析。。。总之PCB的创建代表着进程的创建,同时PCB的撤销也意味着进程生命周期的结束.

0 0
原创粉丝点击