linux进程和task_struct()简介

一、构成进程的要素

在linux系统中,进程主要具备以下要素:

1)有一个程序供其运行。这段程序不一定是进程所专有,可以与其他进程一起使用;

2)有起码的“私有财产”,这就是进程专用的系统堆栈空间;

3)有“身份证”,也就是task_struct结构,也称之为“进程控制块”(PCB)。有了这个数据结构,进程才能成为内核调度的一个基本单位接受内核的调度。同时,这个结构又是进程的“财产登记卡”,记录着进程占用的各项资源。

4)有独立的存储空间,意味着拥有专有的用户空间;还意味着除前述的系统空间堆栈外还有其专有的用户空间堆栈。(PS:进程的系统空间是不能独立的,除了各进程独有的系统堆栈空间外,任何进程都不可能直接改变用户空间的内容)。

以上条件是必要条件,缺少其中一条,都不能称其为“进程”。如果只缺第四条,那就成为“线程”。特别地,如果完全没有用户空间,就称其为“内核线程”;而如果共享用户空间则称其为“用户线程”。在不致引起混淆的场合,二者也往往简称为“线程”。注意!!!这里的线程与有些操作系统中在用户空间的同一进程内实现的“线程”不一样!既然linux提供了对上述内核线程和用户线程的支持,也就没必要再在进程内部,即用户空间内自行实现线程。

关于进程和线程的区分不是十分严格,在linux系统中,许多进程在诞生之初都与其父进程共同用一个存储空间,所以也就是用户线程。但是子进程又可以建立自己的存储空间,并与父进程“分道扬镳”,成为与父进程一样真正意义上的进程。

在linux系统中,“进程”和“任务”是同一个意思,在内核的代码中常混用这两个名词和概念。例如每个进程都要有一个task_struct数据结构,而其号码却又是pid、唤醒一个睡眠进程的函数名为wake_up_process(),之所以有这样的情况是因为,linux源自Unix和i386系统结构,而unix中的进程在Intel的技术资料中称为“任务”,严格来说有点区别,但是对于系统的实现来说是一回事。

linux系统运行的第一个进程是在初始化阶段“捏造出来的”。而此后的线程或进程都是由一个已存在的进程像细胞分裂一样通过系统调用复制出来的,成为“fork()”或者“clone()”。

除了最起码的“财产”,即task_struct数据结构和系统堆栈之外,一个进程还要有一些附加的资源。例如,进程拥有堵路的存储空间,就要有用于虚拟内存管理的mm_struct数据结构以及附属的vm_area数据结构,以及相应的页面目录项和页面表,但这些都从属于task_struct资源。task_struct数据结构在这方面相当于登记卡的作用。

二、task_struct的定义

task_struct结构源代码:

  1 struct task_struct
  2 {
  3     /*
  4      * offsets of these are hardcoded elsewhere - touch with care
  5      */
  6     volatile long state;  /* -1 unrunnable, 0 runnable, >0 stopped */
  7     unsigned long flags;  /* per process flags, defined below */
  8     int sigpending;
  9     mm_segment_t addr_limit;   /* thread address space:
 10     0-0xBFFFFFFF for user-thead
 11     0-0xFFFFFFFF for kernel-thread
 12      */
 13     struct exec_domain *exec_domain;
 14     volatile long need_resched;
 15     unsigned long ptrace;
 16     int lock_depth; /* Lock depth */
 17
 18     /*
 19      * offset 32 begins here on 32-bit platforms. We keep
 20      * all fields in a single cacheline that are needed for
 21      * the goodness() loop in schedule().
 22      */
 23     long counter;
 24     long nice;
 25     unsigned long policy;
 26     struct mm_struct *mm;
 27     int has_cpu, processor;
 28     unsigned long cpus_allowed;
 29
 30     struct list_head run_list;
 31     unsigned long sleep_time;
 32
 33     struct task_struct *next_task, *prev_task;
 34     struct mm_struct *active_mm;
 35     /* task state */
 36     struct linux_binfmt *binfmt;
 37     int exit_code, exit_signal;
 38     int pdeath_signal;  /*  The signal sent when the parent dies  */
 39
 40     unsigned long personality;
 41     int dumpable:1;
 42     int did_exec:1;
 43     pid_t pid;
 44     pid_t pgrp;
 45     pid_t tty_old_pgrp;
 46     pid_t session;
 47     pid_t tgid;
 48     /* boolean value for session group leader */
 49     int leader;
 50     /*
 51      * pointers to (original) parent process, youngest child, younger sibling,
 52      * older sibling, respectively.  (p->father can be replaced with
 53      * p->p_pptr->pid)
 54      */
 55     struct task_struct *p_opptr, *p_pptr, *p_cptr, *p_ysptr, *p_osptr;
 56     struct list_head thread_group;
 57     /* PID hash table linkage. */
 58     struct task_struct *pidhash_next;
 59     struct task_struct **pidhash_pprev;
 60     wait_queue_head_t wait_chldexit; /* for wait4() */
 61     struct semaphore *vfork_sem; /* for vfork() */
 62     unsigned long rt_priority;
 63     unsigned long it_real_value, it_prof_value, it_virt_value;
 64     unsigned long it_real_incr, it_prof_incr, it_virt_incr;
 65     struct timer_list real_timer;
 66     struct tms times;
 67     unsigned long start_time;
 68     long per_cpu_utime[NR_CPUS], per_cpu_stime[NR_CPUS];
 69     /* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
 70     unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap;
 71     int swappable:1;
 72     /* process credentials */
 73     uid_t uid,euid,suid,fsuid;
 74     gid_t gid,egid,sgid,fsgid;
 75     int ngroups;
 76     gid_t groups[NGROUPS];
 77     kernel_cap_t   cap_effective, cap_inheritable, cap_permitted;
 78     int keep_capabilities:1;
 79     struct user_struct *user;
 80     /* limits */
 81     struct rlimit rlim[RLIM_NLIMITS];
 82     unsigned short used_math;
 83     char comm[16];
 84     /* file system info */
 85     int link_count;
 86     struct tty_struct *tty; /* NULL if no tty */
 87     unsigned int locks; /* How many file locks are being held */
 88     /* ipc stuff */
 89     struct sem_undo *semundo;
 90     struct sem_queue *semsleeping;
 91     /* CPU-specific state of this task */
 92     struct thread_struct thread;
 93     /* filesystem information */
 94     struct fs_struct *fs;
 95     /* open file information */
 96     struct files_struct *files;
 97     /* signal handlers */
 98     spinlock_t sigmask_lock; /* Protects signal and blocked */
 99     struct signal_struct *sig;
100
101     sigset_t blocked;
102     struct sigpending pending;
103
104     unsigned long sas_ss_sp;
105     size_t sas_ss_size;
106     int (*notifier)(void *priv);
107     void *notifier_data;
108     sigset_t *notifier_mask;
109
110     /* Thread group tracking */
111     u32 parent_exec_id;
112     u32 self_exec_id;
113     /* Protection of (de-)allocation: mm, files, fs, tty */
114     spinlock_t alloc_lock;
115 };

下面对结构中几个重要的成分做介绍:

1)state(第6行)

该变量表示进程当前运行的状态,具体定义如下:

1 #define TASK_RUNNING              0
2 #define TASK_INTERRUPTIBLE        1
3 #define TASK_UNINTERRUPTIBLE      2
4 #define TASK_ZOMBIE               4  //僵尸进程
5 #define TASK_STOPPED              8

状态TASK_INTERRUPTIBLE和TASK_UNINTERRUPTIBLE均表示进程处于睡眠状态。但是TASK_UNINTERRUPTIBLE表示进程处于“深度睡眠”,而不受“信号”(signal,也称软中断)的打扰,而TASK_INTERRUPTIBLE则可以因信号的到来而被唤醒。内核中提供了不同的函数,让一个进程进入不同深度的睡眠或将进程从睡眠中唤醒。具体地说,函数sleep_on()和wake_up()用于深度睡眠,而interruptible_sleep_on()和wake_up_interruptible()则用于浅度睡眠。深度睡眠一般只用于临界区和关键性的部位,而“可中断”的睡眠那就是通用的了。特别地,当进程在“阻塞性”的系统调用中等待某一事件发生时,应该进入可中断睡眠,否则就不能对别的中断做出反应,别的进程就不能通过发一个信号来“杀掉”这个进程了。

TASK_RUNNING状态并不是表示一个进程正在执行中,或者说这个进程就是“当前进程”,而是表示这个进程可以被调度执行而成为当前进程。当进程处于这样的可执行(或就绪)状态时,内核就将该进程的task_struct结构通过其队列头(见第30行)挂入一个“运行队列”。

TASK_ZOMBIE状态表示进程已经“去世”而户口尚未注销。

TASK_STOPPED主要用于调试的目的,进程接收到 一个SIGSTOP信号后就将运行状态改成     TASK_STOPPED而进入“挂起”状态,然后在接收到SIGCONT信号时又恢复继续运行。

2)flags(第7行)

flags反应进程状态相关信息,但并不是运行状态,而是与管理有关的其他信息。

 1 #define PF_ALIGNWARN        0x00000001      /*print alignment warning msgs*/
 2 #define PF_STARTING         0x00000002      /*being created*/
 3 #define PF_EXITING          0x00000004      /*getting shut down*/
 4 #define PF_FORKNOEXEC       0x00000040      /*forked but did not exec*/
 5 #define PF_SUPERPRIV        0x00000100      /*uses super-user privileges*/
 6 #define PF_DUMPCORE         0x00000200      /*dumped core*/
 7 #define PF_SIGNALED         0x00000400      /*killed by signal*/
 8 #define PF_MEMALLOC         0x00000800      /*Allocating memory*/
 9 #define PF_VFORK            0x00001000      /*wake up parent in mm_release*/
10 #define PF_USEDFPU          0x00100000      /*task used FPU this quantum(SMP)*/

3)sigpending(第8行)

表示进程收到了“信号”但是尚未处理。

4)counter(第23行)

与进程调度有关

5)add_limit

虚拟地址空间的上限,对进程而言是其用户空间的上限,所以是0xbfff ffff;对内核线程而言则是系统空间额的上限,所以是0xffff ffff

6)binfnt

应用程序的文件格式。

7)pgrp,session,leader

当一个用户登录时,就开始了一个进程组(session),此后创建的进程都属于这同一个session。

8)user

指向一个user_struct结构,该数据结构代表进程所属的用户。

9)rlim

这是一个结构数组,表明进程岁各种资源的使用数量所受的限制。

时间: 2024-11-02 18:06:07

linux进程和task_struct()简介的相关文章

Linux进程管理---task_struct

首先了解一下什么是进程? 进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单元. 为了使参与并发执行的每个程序(含数据)都能独立运行,在操作系统中必须为之配置一个专门的数据结构,称之为进程控制块PCB.系统利用PCB来描述进程的基本情况和活动过程,进而控制和管理进程. 进程控制块就是task_struct结构体. task_struct是Linux内核的一种数据结构,每个进程都把它的信息放在task_struct这个数据结构里,task_struct包含了这些内容: 标识符:描述本进

linux进程编程:子进程创建及执行函数简介

子进程创建及执行函数有三个: (1)fork();(2)exec();(3)system();    下面分别做详细介绍.(1)fork()    函数定义:    pid_t fork();    函数说明:    linux下进程在内存中由三部分数据组成:代码段.数据段.堆栈段.在一个进程中,调用fork函数,可以创建.启动一个新进程.新进程与父进程共享代码段,复制父进程的数据段和堆栈段.创建成功后,fork()会向两个进程都有返回值.向父进程的返回值为子进程的进行号,向子进程的返回值为0.

Linux进程描述符task_struct结构体详解--Linux进程的管理与调度(一)【转】

Linux内核通过一个被称为进程描述符的task_struct结构体来管理进程,这个结构体包含了一个进程所需的所有信息.它定义在include/linux/sched.h文件中. 谈到task_struct结构体,可以说她是linux内核源码中最复杂的一个结构体了,成员之多,占用内存之大. 进程状态 /* * Task state bitmask. NOTE! These bits are also * encoded in fs/proc/array.c: get_task_state().

Linux进程创建过程

相关学习资料 linux内核设计与实现+原书第3版.pdf(3.3章) 深入linux内核架构(中文版).pdf 深入理解linux内核中文第三版.pdf <独辟蹊径品内核Linux内核源代码导读> http://www.yanyulin.info/pages/2013/11/linux0.html http://blog.csdn.net/ddna/article/details/4958058 http://www.cnblogs.com/coolgestar02/archive/2010

基于Linux进程模型分析

1.进程与线程  1.0  进程: 进程是正在运行的程序的实例(an instance of a computer program that is being executed). 进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动.它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元. 1.1  线程: 线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元. 1.2  进程与线程的关系和区别:

Linux进程管理与调度-之-目录导航【转】

转自:http://blog.csdn.net/gatieme/article/details/51456569 版权声明:本文为博主原创文章 && 转载请著名出处 @ http://blog.csdn.net/gatieme 目录(?)[-] 项目链接 进程的描述 进程的创建 进程的加载与运行 进程的退出 进程的调度 调度普通进程-完全公平调度器CFS 日期 内核版本 架构 作者 GitHub CSDN 2016-07-21 Linux-4.6 X86 & arm gatieme

Linux进程上下文切换过程context_switch详解--Linux进程的管理与调度(二十一)【转】

转自:http://blog.csdn.net/gatieme/article/details/51872659 版权声明:本文为博主原创文章 && 转载请著名出处 @ http://blog.csdn.net/gatieme 目录(?)[-] 前景回顾 1 Linux的调度器组成 2 调度工作 进程上下文 1 进程上下文的概念 2 上下文切换 context_switch进程上下文切换 1 context_switch完全注释 2 prepare_arch_switch切换前的准备工作

Linux进程概念与管理

一.Linux进程概念 1.进程:Process,是运行中的程序的一个副本,有生命周期,都由其父进程创建 Linux内核存储进程信息的固定格式:taskstruct 多个任务的的taskstruct组件的链表:task list 2.进程优先级:0-139 0:一般不使用 1-99:实时优先级:数字越大优先级越高,系统自动安排 100-139:静态优先级:数字越小优先级越高,可手动更改 3.Nice值:-20至19,对应于100到139 普通用户只能将自己的优先级调低,root用户可以随意调制

第5章 进程环境(1)_进程结构(task_struct)

1. 进程的概念和进程结构 1.1 进程 (1)程序(program):是一些保存在磁盘上有序指令的集合,是存放在磁盘文件中的可执行文件.但没有任何执行的概念,它是静态的. (2)进程(process) ①程序的执行实例被称为进程,是一个动态的概念,它是程序执行的过程,包括创建.调度和消亡. ②进程具有独立的权限与职责,如果系统中某个进程崩溃,它不会影响其余的进程. ③每个进程运行在其各自的虚拟地址空间中,进程之间可以通过由内核控制的机制相互通信. (3)进程ID:每个linux进程都有一个唯一