1、进程的定义html
进程是操做系统的概念,每当咱们执行一个程序时,对于操做系统来说就建立了一个进程,在这个过程当中,伴随着资源的分配和释放。能够认为进程是一个程序的一次执行过程。
2、进程与程序的区别
程序时静态的,它是一些保存 在磁盘上得指令的有序集合,没有任何执行的概念。
进程是一个动态的概念,它是程序执行的过程,包括建立、调度和消亡。
3、linux系统中进程的表示
在linux系统中,进程由一个叫task_struct的结构体描述,也就是说linux中的每一个进程对应一个task_struct结构体。该结构体记录了进程的一切。下面咱们来看看它的核心字段。
struct task_struct
{
//这个是进程的运行状态,-1表明不可运行,0表明可运行,>0表明已经中止。
volatile long state;
/*
flags是进程当前的状态标志,具体以下:
0x0000 0002表示进程正在被建立
0x0000 0004表示进程正准备退出
0x0000 0040表示此进程被fork出,可是并无执行exec
0x0000 0400表示此进程因为其余进程发送相关信号而被杀死
*/
unsigned int flags;
//表示此进程的运行优先级
unsigned int rt_priority;
//该结构体记录了进程内存使用的相关状况
struct mm_struct *mm;
//进程号,是进程的惟一标识
pid_t pid;
//进程组号
pid_t tgid;
//real_parent是该进程的"亲生父亲",无论其是否被"寄养"
struct task_struct *real_parent;
//parent是该进程如今的父进程,有多是"继父"
struct task_struct *parent;
//这里children指的是该进程孩子的链表,能够获得全部孩子的进程描述符
struct list_head children;
//同理,sibling该进程兄弟的链表,也就是其父进程的全部孩子的链表
struct list_head sibling;
//这个是主线程的进程描述符,也许你会奇怪,为何线程用进程描叙符表示,由于linux并无单独实现线程的相关结构体,只用一 个进程来代替线程,而后对其作一些特殊的处理。
struct task_struct *group_leader;
//这个是该进程全部线程的链表
struct list_head thread_group;
//这个是该进程使用cpu时间的信息,utime是在用户态下执行的时间,stime 是在内核态下执行的时间
cputime_t utime,stime;
//comm是保存该进程名字的字符数组,长度最长为15,由于TASK_COMM_LEN为16
char comm[TASK_COMM_LEN];
//打开的文件相关信息结构体
struct files_struct *files;
//信号相关信息的句柄
struct signal_struct *signal;
struct sigband_struct *sighand;
};
task_struct结构体很是庞大,咱们不必去了解它的全部字段,只须要对其中比较重要的字段加以关注就能够了。从上面的分析能够看出,一个进程至少有一下东东
1. 进程号(pid),就像咱们的身份证ID同样,每一个人的都不同。进程ID也是,是其惟一标示。
2.进程的状态,标识进程是处于运行态,等待态,中止态,仍是死亡态
A.运行态:此时进程 或者正在运行,或者准备运行
B.等待态:此时进程在等待一个事件发生或某种系统资源
C.中止态:此时进程被终止
D.死亡态:这是一个已终止的进程,但还在进程向量数组中,占有一个task_struct结构。
3.进程的优先级和时间片。不一样有优先的进程,被调度运行的次序不同,通常是高优先级的进程先运行。时间片标识一个进程将被处理器运行的时间
4.虚拟内存 大多数进程有一些虚拟内存(内核线程和守护进程没有) ,而且Linux必须跟踪内存如何映射到系统物理内存。
5.处理器相关上下文 一个进程能够被认为是系统当前状态的总和。每当一个进程运行时,它要使用处理器的寄存器、栈等,这是进程的上下文(context)。而且,每当一个进程被暂停时,全部的CPU相关上下文必须保存在该进程的task_struct中。当进程被调度器从新启动时其上下文将从这里恢复。
4、linux进程中的文件
linux操做系统中每一个进程有两个数据结构描叙文件相关信息。
第一个:fs_struct,它包含此进程当前工做目录和根目录、umask。umask是新文件被 建立的缺省模式,它能够经过系统调用来改变。
第二个:files_struct,包含此进程正在使用的全部文件的信息。f_mode字段描述该文件是以什么模式建立的:只读、读写、仍是只写。f_pos保存文件中下一个读或写将发生的位置。f_inode描叙文件的VFS索引节点,而f_ops是一个例程向量的指针,每一个表明一个想施加于文件的操做的函数。
每次一个文件被打开时,files_struct中的空闲file指针之一就被用来指向新的file结构。Linux进程在启动时有三个文件描叙符被打开了,他们是标准输入设备、标准输出设备和标准错误设备,而且一般是从建立此进程的父进程继承得来的。全部对文件的访问时经过传递或返回文件描叙符的标准系统调用进行的。这些描述符是进程fd向量的索引,因此标准输入设备、标准输出设备和标准错误设备分别对应文件描述符0、1和2。
5、进程中的虚拟内存
在Linux操做系统中,当咱们运行一个二级制可执行文件时,操做系统将建立一个进程。此时若是将这个可执行二进制文件的所有代码和数据装入物理内存将是浪费的。由于他们不可能同时使用。随着系统中进程数的增多,这种浪费将被成倍的扩大,系统将很是低效地运行。事实上,linux使用一种称为请求调页(demand-paging)的技术:只有当进程要使用时其虚拟内存时,其对应的数据才装入物理内存。因此,不是直接把代码和数据装入物理内存。linux内核只修改进程的页表,标识虚拟内存页存在但其对应的数据不在内存中。当进程想要访问代码或数据时,系统硬件将产生页故障并把控制交给Linux内核来解决。所以,对于进程地址空间中的每个内存区,Linux都须要知道该虚拟内存来自何处,以及如何把它装入内存以解决故障。
当一个进程分配虚拟内存时,Linux并不真正为它保留物理内存。它只是建立一个新vm_area_struct数据结构来描叙虚拟内存,这个结构被链入进程的虚拟内存列表。当进程试图写一个位于新分配虚拟内存区域的虚拟地址时,系统将产生页故障。处理器试图转换该虚拟地址,可是由于没有此内存的页表项,它将放弃并产生一个页故障异常,留给Linux内核来解决。Linux查看被引用的虚拟地址是不是位于当前进程的虚拟内存地址空间。若是是Linux建立适当的PTE并为此进程分配一页物理内存。代码或数据可能须要从文件系统或交换硬盘上读入物理内存。而后进程能够从引发页故障的那条指令处重启,而且由于此次内存物理地址存在,因此它能够继续执行。若是不是,就是你们经常见到的"段错误"。
呵呵,更纤细的介绍请看linux 进程地址空间的一步步探究。
from:http://blog.chinaunix.net/uid-26833883-id-3193588.html