进程是Linux系统里面非常重要的一个概念:进程是指处于运行状态的程序。

 

简单的说一个源程序经过编译链接,成为一个可以运行的程序,当可执行程序被加载到内存空间运行的时候,就成为了进程。程序是保存在磁盘上静态的代码和数据的集合,进程是动态的概念。

 

进程的属性:

 

进程创建后,系统内核为其分配了一系列的数据结构,这些数据结构保存了进程的相关属性。

标识符:内核为每个进程分配的唯一一个进程标识符,范围0-32767。进程ID是循环使用的,大于最大值时候重新从0开始寻找可以用的值。

进程的父进程标识符:除了init进程外,其他的都有父进程。

进程的用户标识:运行改程序的用户ID,当一个程序呗某个用户执行而变为进程时候,用户就是这个进程的用户标识符。

进程的有效用户标识符:该进程运行过程有效的用户身份,在运行文件权限许可等检查时候,以该用户标识符为依据。

进程有效组标识:当前进程的有效组标识,在运行文件权限许可等检查时候,以该有效组标识为依据,进程的用户和组相关的4个标识用于检查对文件系统的访问权限

进程的进程组标识符:一个进程可以属于某个进程组,通过设置进程组,可以实现向一组进程发送信号等进程操作。

进程回话标识符:每个进程都有唯一的会话,在进程的属性里面包含了进程的回话ID信息。

 

这些属性可以通过PS命令查询:

USER :进程的属主。

PID:进程的标识符

%CPU:CPU的百分比

%MEM:进程占用内存的百分比。

VSZ:进程占用虚拟内存的大小,单位KB

RSS:进程常驻集的大小。

TTY:终端的编号,tty1-tty6为文本模式下的控制台,pts/n是在图形陌生下打开的shell窗口或者远程登录打开的模拟控制台,没有终端显示“?”

 

STAT::进程的状态:常见的D (不可中断,通常为I/O操作),R(正在运行),S(睡眠模式),T(暂停),Z(僵尸),<(高优先级),N(低优先级),s(包含子进程),+(位于后台的进程组),I(多线程)

 

START:进程的开始时间

TIME:进程的运行时间

COMMAND:所执行的指令

 

Linux系统允许通过函数调用,查看进程的信息。常用的如下:

Getpid();获取进程ID。

Getppid ();获取进程的父进程ID

Getpgrp();调用getpgrp获取进程的进程组ID

Getuid();获取用户的真实用户ID

Getgid();获取真实的用户组ID。

Geteuid();获取进程的有效用户ID。

Getegid();获取进程的有效用户组ID。

 

 

进程的内存映像:

 

一个进程分为

代码段:存放可执行文件的指令,是可执行程序在内存里面的映像。只读。

数据段:存放已经初始化的全局变量。

BSS段:为初始化的全局变量。

堆:进程的内存空间,用于进程运行过程中动态分配内存。

栈:局部变量内存区,还用来保留函数调用时候的现场,函数调用时候,函数的参数被压入栈,有函数从栈中取出、函数返回时候,将返回值压入栈,由主函数从栈取出,栈由系统自动分配。

 

 

进程组:

每个进程都唯一的归属与某个进程组:在shell环境里面。一条Linux命令就可以成为一个进程,这个命令可以只包含一个命令,也可以是通过管道连接起来的若干命令,每个进程组都有一个组长进程,进程组的ID就是这个组长的ID,当进程组内的所有进程都结束,或者都加入到其他的进程组内部时候,该进程组结束。

 

 

Int setpgid(_pid_t _pid,_pid_t_ tpgid);

_pid.用于指定要修改的进程的ID,如果该参数为0,则指向当前进程的ID,

_pgid用于指定新的进程组的ID,如果参数为0,则只当前进程。

 

进程的会话:

 

当用户登录一个新的shell环境时候,一个新的会话产生,一个会话可以包含若干个进程组,但是这些进程组里面只能有一个是前台进程,前台进程通过其组长进程与控制终端相连接,接收来自终端的输入及信号。一个会话有会话ID来标识,会话ID是会话首进程的ID。

 

Linux提供了setsid函数用来产生一个新的对话,但是调用setsid的进程应该保证不是某个进程组的组长进程。Setsid调用成功后产生一个新的会话,新会话的ID是调用进程的进程ID,新会话里面只包含一个进程:即调用setsid的进程,且该会会话没有控制终端。

Setsid 函数调用成功返回进程组的ID,否则出错可以用errno捕捉,典型错误是调用进程为某个进程组组长,错误码 EPERM。

 

 

前台进程:运行过程中和控制终端相连接的进程,随时可以通过控制终端和前台进程进行交互,例如用户登录的时候shell进程。

后台进程没有控制终端:linux系统下的各种守护进程就属于后台进程。

 

 

进程的控制终端:

Linux系统支持多个用户同时从终端登录操作系统,类似与windows下的远程桌面连接,用户通过终端输入请求,提交给主机运行,并显示主机运行结果,传统的Linux系统终端是RS232串口通信协议的串口终端,终端与主机间的通信通过主机的串口进行。因为距离短,速度慢,网络终端与主机通过以太网连接,数据速度传输快,网络终端占主流。

 

Linux系统里面,每一个终端设备都有一个设备文件和它关联,这些终端设备成为tty,zaishell环境下,可以通过执行tty命令,查看当前终端的名子,用户可以通过telnet远程登录到某个linux系统,此时其实没有真正的终端设备,linux系统为用户自动分配一个“伪终端”的设备,设备名字类似与:/dev/pts/xxx.

 

控制终端:是只一个进程运行,进程与用户交互的界面。一个进程从终端启动后,这个进程的运行过程就和控制终端密切相关。可以通过控制终端输入/ 输出,也可以通过控制终端向进程发信号,如(CTRL+C),当控制终端被关闭的时,该控制终端所关联的进程收到SIGHUP信号,系统对该信号默认是终止进程。

 

进程的状态:

 

可运行态:

有两种情况,一种是正在运行,一种是处于就绪状态。处于就绪状态只要得到CPU就可以运行,要等待系统按照时间片轮转规则将CPU分给它。

 

等待状态:表明进程等待某个事件发生或者某个资源就绪。

该状态可分为两种:可中断和不可中断。可中断进程既可以被信号中断,也可以由于资源就绪而被唤醒进入运行状态。而不可中断在任何情况下都不可中断,一旦资源就绪就必须立即运行。

 

暂停状态:进程接收到某个信号,暂时停止运行,大多数进程是由于处于调试,才会出现。

 

僵死:结束但是没有消亡,结束运行就处于僵死状态,进程退出前回向父进程发送SIGCLD信号。父进程调用wait(),函数为子进程退出做收尾工作,如果父进程没有做该工作,子进程虽然退出,但是通过ps依然可以看到,要避免这种状态。

 

Top命令可以动态输出进程信息。

 

进程的优先级:

 

作为一个多任务操作系统,Linux系统允许多个进程同时进行,但是cpu数量少于同时运行的进程数量时候,不可能实现真正的同时运行,以单CPU的计算机为例,如果系统存在两个进程同时运行,则同一时刻只有一个进程占用CPU运行。

 

为了实现多任务的目标,Linux系统使用了一种“时间片轮转”的进程调度方式,为每个进程指派一定的与运行时间,这个时间片通常很短,以毫秒甚至更小单位级别,系统和核心依照某种规则,从大量的进程中选取一个进程投入,其余等待,当运行的那个进程时间片用完或者进程的执行完毕退出,系统开始新的调度,因为每个时间片时间很短,所以看似同时运行一样。

 

进程的优先级定义了进程的优先顺序,优先级的数值越低,进程越是优先被调度。

优先级是由进程的优先级别(PR)和进程的谦让度(NI)两个因素合成决定的,一个进程优先级别是由父进程继承来的,用户进程不可更改。

 

为了方便更改进程的优先级,提供了nice系统调用,来修改进程的谦让度,进程的谦让度在创建时候默认为0,系统运行的谦让度范围为最高优先级的-20到最低优先级的19,通过nice调用可以改变。

 

函数原型:intnice(int_inc);位置:<unistd.h>

_inc是谦让度,返回0表示成功。Nice函数只能更改自身谦让度。

函数 setpriority可以修改其他进程谦让度。位于<sys/resource.h>。

 intsetpriority(_priority_which_t_which,id_t_who,int_prio);

参数含义:_which,制定设置谦让度的目标类型。_who:设置谦让度的目标。

_prio 要设置的谦让度。