说起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_structtask_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所以引入tgid3.进程标记符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< 6.进程调度int prio, static_prio, normal_prio;
unsigned int rt_priority;