进程

进程、父进程、fork and exec

程序是存放在存储媒体中以实体文件的形式存在的,程序被触发后会在内存中形成进程,进程记录了执行者的权限和属性、程序的程序代码和需要的数据,进程的唯一标识符是PID,对于同一个程序,执行者不同,PID也不同。

程序的执行是有关联性的,连续执行两个bash后,第二个bash的父进程就是第一个bash,一个线程的父进程可以用Parent PID(PPID)来查看,执行ps -l就可以查看一个进程的PPID。有一个特点是子进程可以取到父进程的环境变量。有时手动关闭一个进程会发现过段时间进程被重新打开,这是因为某些系统工作排程在运行父进程的过程中产生了子进程,此时就要手动杀掉父进程。

在linux中进程间的呼叫被称为fork and exec,进程都会由父进程以复制(fork)的方式产生一个一模一样的子进程,然后被复制出来的子进程再以exec的方式来执行程序,整个流程如下:

 

在进程中有一类比较特殊的进程,它们常驻内存,在系统中不停的运行,通常负责一些系统所提供的功能用来服务用户执行各项任务,这类程序或进程被称为服务(daemon)

查看进程

查阅自己bash相关的进程:ps -l

 

第一个字段F代表进程旗标,4代表此进程的权限是root,1代表此子进程仅进行复制(fork)而没有实际执行(exec)。

第二个字段S代表进程状态,R(running)代表运行中,S(sleep)代表正在睡眠状态,D代表不可唤醒的睡眠状态,如等待IO,T(stop)代表停止状态,如背景暂停或traced,Z(zombie)代表僵尸状态,代表已经终止但还没有移除内存。

C代表CPU使用率,单位为百分比。

PRI/NI代表进程被CPU执行的优先级,数字越小代表CPU越快被执行。

ADDR/SZ/WCHAN分别代表kernel function(进程在内存中的部分,-代表进程正在运行)、进程用掉的内存、进程是否正在运作(-代表进程正在运行)。

TTY是登入者的终端机位置,如果是远程登录则使用动态终端接口(pts/n)。

TIME是实际运行使用掉的CPU时间。

CMD是触发该进程的指令。

查看系统所有进程:ps auxps -le这两个命令是一样的,前者是unix格式,后者是linux格式。执行结果:

 

上述结果的解释:

 

 

TTY如果是?说明是内核直接产生的。通过COMMAND可以查看具体是什么命令产生该进程,可以通过命令来判断到底是什么进程。

查看cron和rsyslog这两个服务相关的进程情况:ps aux | egrep '(cron|rsyslog)'

ps -l的形式查看所有进程:ps -lA

列出类似进程树的进程显示:ps axjf

查看进程树:pstree [选项],-p可以显示进程的PID,-u可以显示进程的所属用户,-A可以显示

终止进程

kill命令:kill [信号代号] pid,信号信息可以用kill -l查看,常用的如下:

 

常用的有三个,正常终止15,强制终止9,重启1。不加信号代号默认是15。

killall命令可以根据进程名杀死进程:killall [选项][信号] 进程名,选项有-i表示交互式,询问是否要杀死某个进程;-I表示忽略进程名的大小写。此时要杀的进程可能有多个,用来杀死服务对应的多个进程比较方便,如:killall -9 httpd

可以杀死进程是linux稳定的主要原因之一,如果在文字界面遭遇卡死,可以直接用alt+f1-f7来切换终端机页面,然后在该页面手动杀死错误的进程,这样就能恢复正常了。

进程执行顺序

当所有进程被同时唤醒时,CPU要对唤醒的进程进行排序然后执行。

进程的优先执行序priority就是PRI,这个值越低进程就越优先,它是内核调整的,用户无法直接修改PRI,如果用户想要调整进程的优先执行序需要通过Nice值,也就是NI。两者的相关性如下:

PRI(new) = PRI(old) + NI

这个公式并不是绝对的,如果NI调整成5,原来的PRI是50,新PRI不会是55,因为它是系统动态决定的,NI只是一定程度上影响PRI的值,最终PRI是要经过系统分析才能决定的,如果要提升进程的优先级就可以把NI设置成负值,但是注意只有root可以设置成负值,一般使用者只能设置自己进程的NI值,只能设置成正数,且只能将NI越调越高(NI的值为-20到19)

NI值可以在开始执行程序的时候就设置:nice -n -5 命令,表示该命令的nice值设置为5,一般需要放在后台工作的,比较不重要的进程可以设置nice值较大一些,如备份命令。

NI值也可以对已存在的进程调整:renice -5 14836,这条命令会把指定PID的进程nice值设置为5。

子进程会继承父进程的nice值。

内存中的数据/proc/*

进程都是存在内存中,而内存中的数据都是存在/proc/*目录下,各个进程的PID都是以目录的形态存在于该目录下,进入对应PID目录可以发现一些进程的信息,如进入/proc/1中,目录下有两个文件比较重要,一个是cmdline,它记录了进程被启动的指令串;一个是environ,它记录了进程的环境变量内容。

proc目录下还有一些文件记录了整个linux系统相关参数:

 

查看进程相关的文件

从文件查进程fuser

找出对应目录的PID、所属账号和权限:fuser -uv 目录

 

权限有几种:c代表此进程在当前的目录下、e代表可被触发为执行状态、f是一个被开启的文件、r代表顶层目录、F代表文件被开启但在等待回应中、m代表可能为分享的动态函式库。

查找有多少进程占用当前文件系统:fuser -muv 目录,这个m选项会直接向上找到文件系统的最高层。输出的格式和上面的一样。当无法取消挂载时,可以用这个命令查看进程然后一个一个清除。

查看存取单个文件的进程:fuser -uv 文件

从进程查文件lsof

列出某个进程打开或使用的文件信息lsof [选项],选项:

-c字符串: 只列出以字符串开头的进程打开 的文件
-u用户名: 只列出某个用户的进程打开的文 件
-ppid: 列出某个PID进程打开的文件

查看系统中所有被开启的文件:lsof

列出关于root的进程开启的socket:lsof -u root -a -U,这里-U代表找出socket文件,-a代表同时满足多个限制。

列出所有被进程启动的装置:lsof +d /dev