Linux下的进程描述

进程
OS:程序的一个执行实例。
正在执重点内容行的程序。
能分配处理器并由处理器执行的实体。
内核观点:担当分配系统资源(CPU时间,内存)的实体。
进程的两个基本元素是程序代码(可能被执行相同程序的其他进程共享)和代码相关联的数据集。进程是一种动态描述,但是并不代表所有的进程都在运⾏行。(进程在内存中因策略或调度需求,会处于各种状态)

进程控制块(PCB)
每个进程在内核中都有一个进程控制块(PCB)来维护进程相关的信息,Linux内核的进程控制块是task_struct结构体。
Linux内核通过一个被称为进程描述符的task_struct结构体来管理进程,这个结构体包含了一个进程所需的所有信息。它定义在linux-2.6.38.8/include/linux/sched.h文件中。

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

task_struct结构注释:

==========================

  long state 任务的运行状态(-1 不可运行,0 可运行(就绪),>0 已停止)。

  long counter 任务运行时间计数(递减)(滴答数),运行时间片。

  long priority 运行优先数。任务开始运行时counter = priority,越大运行越长。

  long signal 信号。是位图,每个比特位代表一种信号,信号值=位偏移值+1。

  struct sigaction sigaction[32] 信号执行属性结构,对应信号将要执行的操作和标志信息。

  long blocked 进程信号屏蔽码(对应信号位图)。

  --------------------------

  int exit_code 任务执行停止的退出码,其父进程会取。

  unsigned long start_code 代码段地址。

  unsigned long end_code 代码长度(字节数)。

  unsigned long end_data 代码长度 + 数据长度(字节数)。

  unsigned long brk 总长度(字节数)。

  unsigned long start_stack 堆栈段地址。

  long pid 进程标识号(进程号)。

  long father 父进程号。

  long pgrp 父进程组号。

  long session 会话号。

  long leader 会话首领。

  unsigned short uid 用户标识号(用户id)。

  unsigned short euid 有效用户id。

  unsigned short suid 保存的用户id。

  unsigned short gid 组标识号(组id)。


  unsigned short egid 有效组id。

  unsigned short sgid 保存的组id。

  long alarm 报警定时值(滴答数)。

  long utime 用户态运行时间(滴答数)。

  long stime 系统态运行时间(滴答数)。

  long cutime 子进程用户态运行时间。

  long cstime 子进程系统态运行时间。

  long start_time 进程开始运行时刻。

  unsigned short used_math 标志:是否使用了协处理器。

  --------------------------

  int tty 进程使用tty 的子设备号。-1 表示没有使用。

  unsigned short umask 文件创建属性屏蔽位。

  struct m_inode * pwd 当前工作目录i 节点结构。

  struct m_inode * root 根目录i 节点结构。

  struct m_inode * executable 执行文件i 节点结构。

  unsigned long close_on_exec 执行时关闭文件句柄位图标志。(参见include/fcntl.h)

  struct file * filp[NR_OPEN] 进程使用的文件表结构。

  --------------------------

  struct desc_struct ldt[3] 本任务的局部表描述符。0-空,1-代码段cs,2-数据和堆栈段ds&ss。

  --------------------------

  struct tss_struct tss 本进程的任务状态段信息结构。

  ==========================

task_struct所有成员及用法
1、进程标识符(PID):
描述本进程的唯一标示符,用来区别其他进程。

 pid_t pid;
 pid_t tgid;

在CONFIG_BASE_SMALL配置为0的情况下,PID的取值范围是0到32767,即系统中的进程数最大为32768个。

/* linux-2.6.38.8/include/linux/threads.h */
   #define PID_MAX_DEFAULT (CONFIG_BASE_SMALL ? 0x1000 : 0x8000)

在Linux系统中,一个线程组中的所有线程使用和该线程组的领头线程(该组中的第一个轻量级进程)相同的PID,并被存放在tgid成员中。只有线程组的领头线程的pid成员才会被设置为与tgid相同的值。注意,getpid()系统调用返回的是当前进程的tgid值而不是pid值。

2、进程状态
任务状态,退出代码,退出信号等。

volatile long state;      //表示进程的当前状态
int exit_state;

state成员的可能取值如下:

#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_ZOMBIE     16
#define EXIT_DEAD       32
/* in tsk->state again */
#define TASK_DEAD       64
#define TASK_WAKEKILL       128
#define TASK_WAKING     256

系统中的每个进程都必然处于以上所列进程状态中的一种。

 TASK_RUNNING          //表示进程要么正在执行,要么正要准备执行。

 TASK_INTERRUPTIBLE   //表示进程被阻塞(睡眠),直到某个条件变为真。条件一旦达成,进程的状态就被设                                                   置为TASK_RUNNING。

TASK_UNINTERRUPTIBLE  //与TASK_INTERRUPTIBLE类似,除了不能通过接受一个信号来唤醒以外。

__TASK_STOPPED        //表示进程被停止执行。

__TASK_TRACED         //表示进程被debugger等进程监视。

EXIT_ZOMBIE      //表示进程的执行被终止,但是其父进程还没有使用wait()等系统调用来获知它的终止信息。

EXIT_DEAD        //表示进程的最终状态。

EXIT_ZOMBIE和EXIT_DEAD   //也可以存放在exit_state成员中。

进程状态的切换过程:
这里写图片描述

3、优先级:
相对于其他进程的优先级。

int prio, static_prio, normal_prio;
    unsigned int rt_priority;
    const struct sched_class *sched_class;
    struct sched_entity se;
    struct sched_rt_entity rt;
    unsigned int policy;
    cpumask_t cpus_allowed;

实时优先级范围是0到MAX_RT_PRIO-1(即99),而普通进程的静态优先级范围是从MAX_RT_PRIO到MAX_PRIO-1(即100到139)。值越大静态优先级越低。

/* linux-2.6.38.8/include/linux/sched.h */
#define MAX_USER_RT_PRIO    100
#define MAX_RT_PRIO     MAX_USER_RT_PRIO

#define MAX_PRIO        (MAX_RT_PRIO + 40)
#define DEFAULT_PRIO        (MAX_RT_PRIO + 20)
static_prio用于保存静态优先级,可以通过nice系统调用来进行修改。

rt_priority用于保存实时优先级。

normal_prio的值取决于静态优先级和调度策略。

prio用于保存动态优先级。

policy表示进程的调度策略,目前主要有以下五种:

#define SCHED_NORMAL        0
#define SCHED_FIFO      1
#define SCHED_RR        2
#define SCHED_BATCH     3
/* SCHED_ISO: reserved but not implemented yet */
#define SCHED_IDLE      5
SCHED_NORMAL用于普通进程,通过CFS调度器实现。SCHED_BATCH用于非交互的处理器消耗型进程。     

SCHED_IDLE是在系统负载很低时使用。

SCHED_FIFO(先入先出调度算法)和SCHED_RR(轮流调度算法)都是实时调度策略。

sched_class结构体表示调度类,目前内核中有实现以下四种:

/* linux-2.6.38.8/kernel/sched_fair.c */ 
static const struct sched_class fair_sched_class;
/* linux-2.6.38.8/kernel/sched_rt.c */
static const struct sched_class rt_sched_class;
/* linux-2.6.38.8/kernel/sched_idletask.c */
static const struct sched_class idle_sched_class;
/* linux-2.6.38.8/kernel/sched_stoptask.c */
static const struct sched_class stop_sched_class;
se和rt都是调用实体,一个用于普通进程,一个用于实时进程,每个进程都有其中之一的实体。

4、上下文数据
进程执行时处理器的寄存器中的数据。

(1) struct desc_struct *ldt;

  进程关于CPU段式存储管理的局部描述符表的指针,用于仿真WINE Windows的程序。其他情况下取值NULL,进程的ldt就是arch/i386/traps.c定义的default_ldt。

  (2) struct thread_struct tss;

  任务状态段,其内容与INTEL CPU的TSS对应,如各种通用寄存器.CPU调度时,当前运行进程的TSS保存到PCB的tss,新选中进程的tss内容复制到CPU的TSS。结构定义在include/linux/tasks.h中。

   (3) unsigned long saved_kernel_stack;

  为MS-DOS的仿真程序(或叫系统调用vm86)保存的堆栈指针。

  (4) unsigned long kernel_stack_page;

  在内核态运行时,每个进程都有一个内核堆栈,其基地址就保存在kernel_stack_page中。

5、记账信息
可能包括处理器时间总和,使⽤用的时钟数总和,时间限制,记账号等。

(1) unsigned long timeout;

  用于软件定时,指出进程间隔多久被重新唤醒。采用tick为单位。

  (2) unsigned long it_real_value,it_real_iner;

  用 于itimer(interval timer)软件定时。采用jiffies为单位,每个tick使it_real_value减到0时向进程发信号SIGALRM,并重新置初值。初值由 it_real_incr保存。具体代码见kernel/itimer.c中的函数it_real_fn()。

  (3) struct timer_list real_timer;

  一种定时器结构(Linux共有两种定时器结构,另一种称作old_timer)。数据结构的定义在include/linux/timer.h中,相关操作函数见kernel/sched.c中add_timer()和del_timer()等。

  (4) unsigned long it_virt_value,it_virt_incr;

  关 于进程用户态执行时间的itimer软件定时。采用jiffies为单位。进程在用户态运行时,每个tick使it_virt_value减1,减到0时 向进程发信号SIGVTALRM,并重新置初值。初值由it_virt_incr保存。具体代码见kernel/sched.c中的函数 do_it_virt()。

  (5) unsigned long it_prof_value,it_prof_incr;

  同样是 itimer软件定时。采用jiffies为单位。不管进程在用户态或内核态运行,每个tick使it_prof_value减1,减到0时向进程发信号 SIGPROF,并重新置初值。初值由it_prof_incr保存。 具体代码见kernel/sched.c中的函数do_it_prof。

  (6) long utime,stime,cutime,cstime,start_time;

  以上分别为进程在用户态的运行时间、进程在内核态的运行时间、所有层次子进程在用户态的运行时间总和、所有层次子进程在核心态的运行时间总和,以及创建该进程的时间。

5、内存指针
包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。

struct mm_struct *mm;

  在linux 中,采用按需分页的策略解决进程的内存需求。task_struct的数据成员mm指向关于存储管理的mm_struct结构。其中包含了一个虚存队列 mmap,指向由若干vm_area_struct描述的虚存块。同时,为了加快访问速度,mm中的mmap_avl维护了一个AVL树。在树中,所有的 vm_area_struct虚存块均由左指针指向相邻的低虚存块,右指针指向相邻的高虚存块。 结构定义在include/linux/sched.h中。

task_struct的定义:

struct task_struct {
volatile long state;  //说明了该进程是否可以执行,还是可中断等信息
unsigned long flags;  //Flage 是进程号,在调用fork()时给出
int sigpending;    //进程上是否有待处理的信号
mm_segment_t addr_limit; //进程地址空间,区分内核进程与普通进程在内存存放的位置不同
                        //0-0xBFFFFFFF for user-thead
                        //0-0xFFFFFFFF for kernel-thread
//调度标志,表示该进程是否需要重新调度,若非0,则当从内核态返回到用户态,会发生调度
volatile long need_resched;
int lock_depth;  //锁深度
long nice;       //进程的基本时间片
//进程的调度策略,有三种,实时进程:SCHED_FIFO,SCHED_RR, 分时进程:SCHED_OTHER
unsigned long policy;
struct mm_struct *mm; //进程内存管理信息
int processor;
//若进程不在任何CPU上运行, cpus_runnable 的值是0,否则是1 这个值在运行队列被锁时更新
unsigned long cpus_runnable, cpus_allowed;
struct list_head run_list; //指向运行队列的指针
unsigned long sleep_time;  //进程的睡眠时间
//用于将系统中所有的进程连成一个双向循环链表, 其根是init_task
struct task_struct *next_task, *prev_task;
struct mm_struct *active_mm;
struct list_head local_pages;       //指向本地页面      
unsigned int allocation_order, nr_local_pages;
struct linux_binfmt *binfmt;  //进程所运行的可执行文件的格式
int exit_code, exit_signal;
int pdeath_signal;     //父进程终止时向子进程发送的信号
unsigned long personality;
//Linux可以运行由其他UNIX操作系统生成的符合iBCS2标准的程序
int did_exec:1; 
pid_t pid;    //进程标识符,用来代表一个进程
pid_t pgrp;   //进程组标识,表示进程所属的进程组
pid_t tty_old_pgrp;  //进程控制终端所在的组标识
pid_t session;  //进程的会话标识
pid_t tgid;
int leader;     //表示进程是否为会话主管
struct task_struct *p_opptr,*p_pptr,*p_cptr,*p_ysptr,*p_osptr;
struct list_head thread_group;   //线程链表
struct task_struct *pidhash_next; //用于将进程链入HASH表
struct task_struct **pidhash_pprev;
wait_queue_head_t wait_chldexit;  //供wait4()使用
struct completion *vfork_done;  //供vfork() 使用
unsigned long rt_priority; //实时优先级,用它计算实时进程调度时的weight值

//it_real_value,it_real_incr用于REAL定时器,单位为jiffies, 系统根据it_real_value
//设置定时器的第一个终止时间. 在定时器到期时,向进程发送SIGALRM信号,同时根据
//it_real_incr重置终止时间,it_prof_value,it_prof_incr用于Profile定时器,单位为jiffies。
//当进程运行时,不管在何种状态下,每个tick都使it_prof_value值减一,当减到0时,向进程发送
//信号SIGPROF,并根据it_prof_incr重置时间.
//it_virt_value,it_virt_value用于Virtual定时器,单位为jiffies。当进程运行时,不管在何种
//状态下,每个tick都使it_virt_value值减一当减到0时,向进程发送信号SIGVTALRM,根据
//it_virt_incr重置初值。
unsigned long it_real_value, it_prof_value, it_virt_value;
unsigned long it_real_incr, it_prof_incr, it_virt_value;
struct timer_list real_timer;   //指向实时定时器的指针
struct tms times;      //记录进程消耗的时间
unsigned long start_time;  //进程创建的时间
//记录进程在每个CPU上所消耗的用户态时间和核心态时间
long per_cpu_utime[NR_CPUS], per_cpu_stime[NR_CPUS]; 
//内存缺页和交换信息:
//min_flt, maj_flt累计进程的次缺页数(Copy on Write页和匿名页)和主缺页数(从映射文件或交换
//设备读入的页面数); nswap记录进程累计换出的页面数,即写到交换设备上的页面数。
//cmin_flt, cmaj_flt, cnswap记录本进程为祖先的所有子孙进程的累计次缺页数,主缺页数和换出页面数。
//在父进程回收终止的子进程时,父进程会将子进程的这些信息累计到自己结构的这些域中
unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap;
int swappable:1; //表示进程的虚拟地址空间是否允许换出
//进程认证信息
//uid,gid为运行该进程的用户的用户标识符和组标识符,通常是进程创建者的uid,gid
//euid,egid为有效uid,gid
//fsuid,fsgid为文件系统uid,gid,这两个ID号通常与有效uid,gid相等,在检查对于文件
//系统的访问权限时使用他们。
//suid,sgid为备份uid,gid
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;
int keep_capabilities:1;
struct user_struct *user;
struct rlimit rlim[RLIM_NLIMITS];  //与进程相关的资源限制信息
unsigned short used_math;   //是否使用FPU
char comm[16];   //进程正在运行的可执行文件名
 //文件系统信息
int link_count, total_link_count;
//NULL if no tty 进程所在的控制终端,如果不需要控制终端,则该指针为空
struct tty_struct *tty;
unsigned int locks;
//进程间通信信息
struct sem_undo *semundo;  //进程在信号灯上的所有undo操作
struct sem_queue *semsleeping; //当进程因为信号灯操作而挂起时,他在该队列中记录等待的操作
//进程的CPU状态,切换时,要保存到停止进程的task_struct中
struct thread_struct thread;
  //文件系统信息
struct fs_struct *fs;
  //打开文件信息
struct files_struct *files;
  //信号处理函数
spinlock_t sigmask_lock;
struct signal_struct *sig; //信号处理函数
sigset_t blocked;  //进程当前要阻塞的信号,每个信号对应一位
struct sigpending pending;  //进程上是否有待处理的信号
unsigned long sas_ss_sp;
size_t sas_ss_size;
int (*notifier)(void *priv);
void *notifier_data;
sigset_t *notifier_mask;
u32 parent_exec_id;
u32 self_exec_id;

spinlock_t alloc_lock;
void *journal_info;
};
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值