我们都晓得所谓的进程就是正在运行的一个程序,它是由正文段,用户数据段和系统数据段所组成的一个动态实体。系统数据段存放着进程的控制信息。其中包括进程控制块PCB。
而在linux中每一个进程都由task_struct数据结构来定义(也称为任务结构体)。task_struct就是我们通常所说的PCB。它是进程存在的唯一标识,也是Linux进程实体的核心。
当我们调用fork()时,系统会为我们产生一个task_struct结构,然后从父进程,那里继承一些数据, 并把新的进程插入到进程树中,以待进行进程管理。因此task_struct的结构对于我们理解进程调度有着关键作用。
在进行剖析task_struct的定义之前.我们先看一下一个进程基本的要求有哪些:
1,进程状态,将纪录进程在等待,运行,或死锁
2,调度信息,由哪个调度函数调度,怎样调度等
3,进程的通讯状况
4,因为要插入进程树,必须有联系父子兄弟的指针,当然是task_struct型
5,时间信息,比如计算好执行的时间,以便cpu分配
6,标号,决定改进程归属
7,可以读写打开的一些文件信息
8,进程上下文和内核上下文
9,处理器上下文
10,内存信息
只有这些结构存在了,才能满足一个进程的所有要求.
然后我们打开/include/linux/sched.h
找到task_struct的定义:
struct task_struct {
/* these are hardcoded - don't touch */这里是一些硬件设置对程序原来说是透明的.
其中state说明了该进程是否可以执行,还是可以中断等信息.
Flage是进程号,在调用fork()时给出,
addr_limit是区分内核进程与普通进程在内存存放的位置不同
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
unsigned long flags; /* per process flags, defined below */
int sigpending;
mm_segment_t addr_limit; /* thread address space: 0-0xBFFFFFFF for user-thead 0-0xFFFFFFFF for kernelthread */
struct exec_domain *exec_domain;
long need_resched;
/* various fields */
count是计数器 priorrity是优先级
long counter;
long priority;
cycles_t avg_slice;
/* SMP and runqueue state */ 为多处理机定义的变量.
int has_cpu;
int processor;
int last_processor;
int lock_depth; /* Lock depth. We can context switch in and out of holding a syscall kernel lock... */
为了在进程树中排序, 定义的父子,兄弟指针
struct task_struct *next_task, *prev_task;
struct task_struct *next_run, *prev_run;
/* task state */ 定义task运行的状态,以及信号
struct linux_binfmt *binfmt;
int exit_code, exit_signal;
int pdeath_signal; /* The signal sent when the parent dies */
/* 定义可进程的用户号,用户组以及进程组*/
unsigned long personality;
int dumpable:1;
int did_exec:1;
pid_t pid;
pid_t pgrp;
pid_t tty_old_pgrp;
pid_t session;
/* boolean value for session group leader */
是不是进程组的头文件
int leader;
/*
* pointers to (original) parent process, youngest child, younger sibling,
* older sibling, respectively. (p->father can be replaced with * p->p_pptr->pid)
*/
父子进程的一些指针
struct task_struct *p_opptr, *p_pptr, *p_cptr, *p_ysptr, *p_osptr;
/* PID hash table linkage. */ 在调度中用的一些hash表
struct task_struct *pidhash_next;
struct task_struct **pidhash_pprev;
/* Pointer to task[] array linkage. */
struct task_struct **tarray_ptr;
struct wait_queue *wait_chldexit; /* for wait4() 等待队列 */ struct semaphore *vfork_sem; /* for vfork() */
unsigned long policy, rt_priority;
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;
long per_cpu_utime[NR_CPUS], per_cpu_stime[NR_CPUS];定义了时间片的大小
/* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
内存信息
unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap; int swappable:1;
/* process credentials */
uid_t uid,euid,suid,fsuid;
gid_t gid,egid,sgid,fsgid;
int ngroups;
gid_t groups[NGROUPS];
kernel_cap_t cap_effective, cap_inheritable, cap_permitted;
struct user_struct *user;
以下英文注释很清楚
/* limits */
struct rlimit rlim[RLIM_NLIMITS];
unsigned short used_math;
char comm[16]; /* file system info */
int link_count;
struct tty_struct *tty; /* NULL if no tty */
/* ipc stuff */
struct sem_undo *semundo;
struct sem_queue *semsleeping;
/* tss for this task */
struct thread_struct tss;
/* filesystem information */
struct fs_struct *fs;
/* open file information */
struct files_struct *files;
/* memory management info */
struct mm_struct *mm;
/* signal handlers */
spinlock_t sigmask_lock;
/* Protects signal and blocked */
struct signal_struct *sig; sigset_t signal, blocked;
struct signal_queue *sigqueue, **sigqueue_tail;
unsigned long sas_ss_sp;
size_t sas_ss_size;
};
在分析完这个结构之后, 还有很多问题要想要问,也许不能完全理解,但基本的框架要有.要有一个大体的认识,要了解到一个task_struct中基本的结构,这对今后学习进程和线程有着举足轻重的作用。
本文出自 “Waitting” 博客,请务必保留此出处http://cuiyuxuan.blog.51cto.com/10786939/1786385