·进程概念
简单来讲,进程是程序的一个执行实例;是一个正在执行的程序。
进程与程序的关系:进程是由程序代码和代码相关联的数据集组成。
进程与程序的区别:
①进程是动态的,程序是静态的
②进程只能存在于一段时间,而程序可以长期存在
③进程是可以被调度器调度,并且进程具有运行时的堆桟开销
总得来说:进程是程序加载到内存后,操作系统会衍生出一个PCB结构体来存放该进程的信息。
·PCB
即进程控制块(Process Control Block),是进程中的一部分,它描述了进程的基本信息,记录了操作系统所需要的、用于描述进程情况以及进程运行状态的全部信息。Linux内核的进程控制块是task_struct结构体。
·task_struct
task_struct是Linux内核的一种数据结构(可以在include/linux/sched.h中找到它),它会被装载到RAM里并且包含着进程的信息。
task_struct包含了这些内容:
标识符:描述本进程的唯一标识符,用来区别其他进程
状态:任务状态,退出代码,退出信号等
优先级:相对于其他进程的优先级
程序计数器:程序中即将被执行的下一条指令的地址
内存指针:包括程序代码和程序相关的指针,还有和其他进程共享内存块的指针
上下文数据:进程执行过程中处理器的寄存器中的数据
I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表
记账信息:可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
接下来我们着重分析task_struct结构体:
1.进程状态
volatile long 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_DEAD 16
#define EXIT_ZOMBIE 32
#define EXIT_TRACE (EXIT_ZOMBIE | EXIT_DEAD)
/* in tsk->state again */
#define TASK_DEAD 64
#define TASK_WAKEKILL 128 /** wake on signals that are deadly **/
#define TASK_WAKING 256
#define TASK_PARKED 512
#define TASK_NOLOAD 1024
#define TASK_STATE_MAX 2048
/* Convenience macros for the sake of set_task_state */
#define TASK_KILLABLE (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE)
#define TASK_STOPPED (TASK_WAKEKILL | __TASK_STOPPED)
#define TASK_TRACED (TASK_WAKEKILL | __TASK_TRACED)
2.进程标识符(PID)
pid_t pid;
pid_t tgid;
pid用来标识进程,ppid用来标识父进程,而关于tgid的解释是:一个线程组所有线程与领头线程具有相同的pid,存入tgid字段。getpid()返回的是当前进程的tgid而不是pid。
在CONFIG_BASE_SMALL配置为0的情况先,PID的取值范围是0到32767,即系统中的进程数最大为32768个。
3.进程内核栈
void *stack;
进程内核栈与进程描述符的关系:
对进程内核栈的认识可以参考这篇文章:http://blog.chinaunix.net/uid-20543672-id-2996319.html
4.进程标记
unsigned int flags; /* per process flags, defined below */
反应进程的状态信息,而不是运行状态,用于内核识别进程当前的状态,以备下一步操作。
flags成员的可能取值:
#define PF_EXITING 0x00000004 /* getting shut down */
#define PF_EXITPIDONE 0x00000008 /* pi exit done on shut down */
#define PF_VCPU 0x00000010 /* I'm a virtual CPU */
#define PF_WQ_WORKER 0x00000020 /* I'm a workqueue worker */
#define PF_FORKNOEXEC 0x00000040 /* forked but didn't exec */
#define PF_MCE_PROCESS 0x00000080 /* process policy on mce errors */
#define PF_SUPERPRIV 0x00000100 /* used super-user privileges */
#define PF_DUMPCORE 0x00000200 /* dumped core */
#define PF_SIGNALED 0x00000400 /* killed by a signal */
#define PF_MEMALLOC 0x00000800 /* Allocating memory */
#define PF_NPROC_EXCEEDED 0x00001000 /* set_user noticed that RLIMIT_NPROC was exceeded */
#define PF_USED_MATH 0x00002000 /* if unset the fpu must be initialized before use */
#define PF_USED_ASYNC 0x00004000 /* used async_schedule*(), used by module init */
#define PF_NOFREEZE 0x00008000 /* this thread should not be frozen */
#define PF_FROZEN 0x00010000 /* frozen for system suspend */
#define PF_FSTRANS 0x00020000 /* inside a filesystem transaction */
#define PF_KSWAPD 0x00040000 /* I am kswapd */
#define PF_MEMALLOC_NOIO 0x00080000 /* Allocating memory without IO involved */
#define PF_LESS_THROTTLE 0x00100000 /* Throttle me less: I clean memory */
#define PF_KTHREAD 0x00200000 /* I am a kernel thread */
#define PF_RANDOMIZE 0x00400000 /* randomize virtual address space */
#define PF_SWAPWRITE 0x00800000 /* Allowed to write to swap */
#define PF_NO_SETAFFINITY 0x04000000 /* Userland is not allowed to meddle with cpus_allowed */
#define PF_MCE_EARLY 0x08000000 /* Early kill for mce process policy */
#define PF_MUTEX_TESTER 0x20000000 /* Thread belongs to the rt mutex tester */
#define PF_FREEZER_SKIP 0x40000000 /* Freezer should not count it as freezable */
#define PF_SUSPEND_TASK 0x80000000 /* this thread called freeze_processes and should not be frozen */
5.表示进程亲属关系的成员
struct task_struct __rcu *real_parent; /* real parent process */
struct task_struct __rcu *parent; /* recipient of SIGCHLD, wait4() reports */