所在文件
task_struct结构体
位于内核文件/include/linux/sched.h
中。
分析
去GitHub上查看源码中的该结构体,分析如下:
struct task_struct {
/*
* 进程状态。
*/
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
/*
* 进程的基本信息。
*/
struct thread_info *thread_info;
atomic_t usage;
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
*/
prio_array_t *array;
/*
* 进程的平均睡眠时间
*/
unsigned long sleep_avg;
/*
* timestamp:进程最近插入运行队列的时间。或涉及本进程的最近一次进程切换的时间
* last_ran:最近一次替换本进程的进程切换时间。
*/
unsigned long long timestamp, last_ran;
/*
* 进程被唤醒时所使用的代码。
* 0:进程处于TASK_RUNNING状态。
* 1:进程处于TASK_INTERRUPTIBLE或者TASK_STOPPED状态,而且正在被系统调用服务例程或内核线程唤醒。
* 2:进程处于TASK_INTERRUPTIBLE或者TASK_STOPPED状态,而且正在被ISR或者可延迟函数唤醒。
* -1:表示从UNINTERRUPTIBLE状态被唤醒
*/
int activated;
/*
* 进程的调度类型:sched_normal,sched_rr或者sched_fifo
*/
unsigned long policy;
/*
* 能执行进程的CPU的位掩码
*/
cpumask_t cpus_allowed;
/*
* time_slice:在进程的时间片中,还剩余的时钟节拍数。
* first_time_slice:如果进程肯定不会用完其时间片,就把该标志设置为1。
*
* Dagger-axe注:目的为加速子进程的返回,防止内存中进程过多。
*/
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.
*/
/*
* 链表的头。该链表包含所有被debugger程序跟踪的P的子进程。
*/
struct list_head ptrace_children;
/*
* 指向所跟踪进程的实际父进程链表的前一个下一个元素。
*/
struct list_head ptrace_list;
/*
* mm:指向内存区描述符的指针
*/
struct mm_struct *mm, *active_mm;
/* task state */
struct linux_binfmt *binfmt;
long exit_state;
int exit_code, exit_signal;
int pdeath_signal; /* The signal sent when the parent dies */
unsigned long personality;
/*
* 进程发出execve系统调用的次数。
*/
unsigned did_exec:1;
/*
* 进程PID
*/
pid_t pid;
/*
* 线程组领头线程的PID。
*/
pid_t tgid;
/*
* pointers to (original) parent process, youngest child, younger sibling,
* older sibling, respectively. (p->father can be replaced with
* p->parent->pid)
*/
/*
* 指向创建进程的进程的描述符。
* 如果进程的父进程不再存在,就指向进程1的描述符。
* 因此,如果用户运行一个后台进程而且退出了shell,后台进程就会成为init的子进程。
*/
struct task_struct *real_parent; /* real parent process (when being debugged) */
/*
* 指向进程的当前父进程。这种进程的子进程终止时,必须向父进程发信号。
* 它的值通常与real_parent一致。
* 但偶尔也可以不同。例如:当另一个进程发出监控进程的ptrace系统调用请求时。
*/
struct task_struct *parent; /* parent process */
/*
* children/sibling forms the list of my children plus the
* tasks I'm ptracing.
*/
/*
* 链表头部。链表指向的所有元素都是进程创建的子进程。
*/
struct list_head children; /* list of my children */
/*
* 指向兄弟进程链表的下一个元素或前一个元素的指针。
*/
struct list_head sibling; /* linkage in my parent's children list */
/*
* P所在进程组的领头进程的描述符指针。
*/
struct task_struct *group_leader; /* threadgroup leader */
/* PID/PID hash table linkage. */
/*
* PID散列表。通过这四个表,可以方便的查找同一线程组的其他线程,同一会话的其他进程等等。
*/
struct pid pids[PIDTYPE_MAX];
struct completion *vfork_done; /* for vfork() */
/*
* 子进程在用户态的地址。这些用户态地址的值将被设置或者清除。
* 在do_fork时记录这些地址,稍后再设置或者清除它们的值。
*/
int __user *set_child_tid; /* CLONE_CHILD_SETTID */
int __user *clear_child_tid; /* CLONE_CHILD_CLEARTID */
/*
* 进程的实时优先级。
*/
unsigned long rt_priority;
/*
* 以下三对值用于用户态的定时器。当定时器到期时,会向用户态进程发送信号。
* 每一对值分别存放了两个信号之间以节拍为单位的间隔,及定时器的当前值。
*/
unsigned long it_real_value, it_real_incr;
cputime_t it_virt_value, it_virt_incr;
cputime_t it_prof_value, it_prof_incr;
/*
* 每个进程的动态定时器。用于实现ITIMER_REAL类型的间隔定时器。
* 由settimer系统调用初始化。
*/
struct timer_list real_timer;
/*
* 进程在用户态和内核态下经过的节拍数
*/
cputime_t utime, stime;
unsigned long nvcsw, nivcsw; /* context switch counts */
struct timespec start_time;
/* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
unsigned long min_flt, maj_flt;
/* process credentials */
uid_t uid,euid,suid,fsuid;
gid_t gid,egid,sgid,fsgid;
struct group_info *group_info;
kernel_cap_t cap_effective, cap_inheritable, cap_permitted;
unsigned keep_capabilities:1;
struct user_struct *user;
#ifdef CONFIG_KEYS
struct key *session_keyring; /* keyring inherited over fork */
struct key *process_keyring; /* keyring private to this process (CLONE_THREAD) */
struct key *thread_keyring; /* keyring private to this thread */
#endif
int oomkilladj; /* OOM kill score adjustment (bit shift). */
char comm[TASK_COMM_LEN];
/* file system info */
/*
* 文件系统在查找路径时使用,避免符号链接查找深度过深,导致死循环。
* link_count是__do_follow_link递归调用的层次。
* total_link_count调用__do_follow_link的总次数。
*/
int link_count, total_link_count;
/* ipc stuff */
struct sysv_sem sysvsem;
/* CPU-specific state of this task */
struct thread_struct thread;
/* filesystem information */
/*
* 与文件系统相关的信息。如当前目录。
*/
struct fs_struct *fs;
/* open file information */
/*
* 指向文件描述符的指针
*/
struct files_struct *files;
/* namespace */
struct namespace *namespace;
/* signal handlers */
/*
* 指向进程的信号描述符的指针
*/
struct signal_struct *signal;
/*
* 指向进程的信号处理程序描述符的指针
*/
struct sighand_struct *sighand;
/*
* blocked:被阻塞的信号的掩码
* real_blocked:被阻塞信号的临时掩码(由rt_sigtimedwait系统调用使用)
*/
sigset_t blocked, real_blocked;
/*
* 存放私有挂起信号的数据结构
*/
struct sigpending pending;
/*
* 信号处理程序备用堆栈的地址
*/
unsigned long sas_ss_sp;
/*
* 信号处理程序备用堆栈的大小
*/
size_t sas_ss_size;
/*
* 指向一个函数的指针,设备驱动程序使用这个函数阻塞进程的某些信号
*/
int (*notifier)(void *priv);
/*
* 指向notifier函数可能使用的数据
*/
void *notifier_data;
sigset_t *notifier_mask;
void *security;
struct audit_context *audit_context;
/* Thread group tracking */
u32 parent_exec_id;
u32 self_exec_id;
/* Protection of (de-)allocation: mm, files, fs, tty, keyrings */
spinlock_t alloc_lock;
/* Protection of proc_dentry: nesting proc_lock, dcache_lock, write_lock_irq(&tasklist_lock); */
spinlock_t proc_lock;
/* context-switch lock */
spinlock_t switch_lock;
/* journalling filesystem info */
/*
* 当前活动日志操作处理的地址。
* 正在使用的原子操作对象。
*/
void *journal_info;
/* VM state */
struct reclaim_state *reclaim_state;
struct dentry *proc_dentry;
struct backing_dev_info *backing_dev_info;
struct io_context *io_context;
unsigned long ptrace_message;
siginfo_t *last_siginfo; /* For ptrace use. */
/*
* current io wait handle: wait queue entry to use for io waits
* If this thread is processing aio, this points at the waitqueue
* inside the currently handled kiocb. It may be NULL (i.e. default
* to a stack based synchronous wait) if its doing sync IO.
*/
wait_queue_t *io_wait;
/* i/o counters(bytes read/written, #syscalls */
u64 rchar, wchar, syscr, syscw;
#if defined(CONFIG_BSD_PROCESS_ACCT)
u64 acct_rss_mem1; /* accumulated rss usage */
u64 acct_vm_mem1; /* accumulated virtual memory usage */
clock_t acct_stimexpd; /* clock_t-converted stime since last update */
#endif
#ifdef CONFIG_NUMA
struct mempolicy *mempolicy;
short il_next;
#endif
};
参考资料
https://github.com/jasonactions/linux2.6.11_comment/blob/master/include/linux/sched.h