前言
在虚拟内存中,我提到了linux虚拟内存区域的结构,但具体其是如何在linux中表示与实现的呢?
我利用了linux2.6的源码进行了浅显的分析。
正文
task_struct
在linux中,进程控制块即PCB的结构为task_struct,我们以linux2.6为例,其源码如下:
struct task_struct {
//表示进程当前运行状态
//volatile避免了读取到缓存在寄存器中的脏数据,而是直接从内存中取
//可以看到state基本有三种,但大于0还分为很多不同的状态
//#define TASK_RUNNING 0
//#define TASK_INTERRUPTIBLE 1
//#define TASK_UNINTERRUPTIBLE 2
//#define TASK_STOPPED 4
//#define TASK_TRACED 8
//#define EXIT_ZOMBIE 16
//#define EXIT_DEAD 32
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
//这个结构体保存了进程描述符中中频繁访问和需要快速访问的字段,内核依赖于该数据结构来获得当前进程的描述符。通过源码可以看到,该struct内拥有指向task_struct的指针
struct thread_info *thread_info;
atomic_t usage;
//进程标志,描述进程当前的状态(不是运行状态),如:PF_SUPERPRIV表示进程拥有超级用户特权。。
unsigned long flags; /* per process flags, defined below */
//系统调用跟踪
unsigned long ptrace;
//内核锁标志(判断是否被上锁)
int lock_depth; /* Lock depth */
//进程优先级
int prio, static_prio;
struct list_head run_list;
//进程调度队列
prio_array_t *array;
//进程平均等待时间
unsigned long sleep_avg;
//timestamp:进程最近插入运行队列的时间或最近一次进程切换的时间
//last_ran:最近一次替换本进程的进程切换时间
unsigned long long timestamp, last_ran;
//进程被唤醒时所使用的条件代码,就是从什么状态被唤醒的。
int activated;
//进程的调度类型
unsigned long policy;
cpumask_t cpus_allowed;
//time_slice:进程的剩余时间片
//first_time_slice:创建后首次获取的时间片,为1表示当前的时间片是从父进程分来的
unsigned int time_slice, first_time_slice;
#ifdef CONFIG_SCHEDSTATS
struct sched_info sched_info;
#endif
struct list_head tasks;
/*
* ptrace_list/ptrace_children forms the list of my children
* that were stolen by a ptracer.
*/
struct list_head ptrace_children;
struct list_head ptrace_list;
//mm:内存描述符,其下有程地址空间下的虚拟内存信息
//actvie_mm:内核线程所借用的地址空间
struct mm_struct *mm,active_mm;
/* task state */
struct linux_binfmt *binfmt;
//进程的退出状态,大于0表示僵死
long exit_state;
//exit_code:存放进程的退出码
//exit_signal:当进程退出时发给父进程的信号,如果是轻量级进程为-1
int exit_code, exit_signal;
int pdeath_signal; /* The signal sent when the parent dies */