【linux】学习笔记Chap_26_系统进程管理
系统进程管理
- 在Unix中,所有信息都由某个文件或程序提供,简单来说,文件只是个输入输出对象,而一个进程才是执行的对象
本章将搞懂 :
- 进程从哪来?进程如何被系统控制?如何控制自己的进程?
系统如何控制进程
- 准确说:进程是一个被装载到内存的程序,全部的程序数据、信息也会被放入内存中。
所有的进程被内核kernel管理,当一个进程创建时,内核指定一个 Process ID(identification number)给进程,以便追踪进程信息。
-
- 内核会管一个进程信息表,由**PID和进程名构成,**有了这个表,内核将掌握控制进程的必要信息。
小型Unix系统可以同时执行100多进程,大Unix可达到上千进程。
Cpu time
先介绍Cpu time, 以前电脑只有一个cpu,而单个cpu要面对不同进程任务,为了雨均沾,给每个进程设置一个cputime 如10毫秒。cpu从 等待执行的进程列表中选出一个进程,让其执行10毫秒,时间一到就选出下一个进程,而上一个进程就要记录当前运行的状态,以便下次再继续。
System call
当一个程序要执行时,要向内核(kernel)发出一条call,让系统准备不同操作
- 最重要的system calls 有fork exec wait exit
fork
fork 用来创建一个当前进程的复制进程,源进程为父进程,复制的进程为子进程
wait
wait 可以将进程暂停
exec
exec 可以将当前正在执行的进程改变成其他进程
exit
exit 退出当前进程(如,对刚登陆的shell使用,则会退出) shell本身也是个进程,也有PID
1 | 可以用echo $$ 查看当前shell的PID |
kill 用来结另一个进程
一个进程如何被执行
Unix有两种命令 内部和外部命令,内部命令是内置在Unix中的,所以不用创建新的进程
对于外部命令或外部程序,以下为Unix执行过程
在shell中输入一个sl命令
则Unxi会用fork(system call ) 创建一个当前进程的复制进程(子进程) ,
- 然后将子进程用exec将当前进程改变到要执行的外部命令sl
- 同时,将父进程用wait暂停执行,直到子进程完成.
进入shell后打开文档进行编辑也是这个过程,父进程将等待到vim退出编辑
- 在子进程结束后,将执行exit,然后转到父进程中。并将子进程所用的文件、内存全部释放,让其它进程再使用,此时,像子进程这种已经失效的进程成为Zombie ,在进程表中仍然保留其信息,当父进程恢复后,可以查看子进程在进程表的信息,随后系统将自动将信息删除。
Q:上面提到了fork 可以创建一份复制进程和一个父进程,但如何辨识两个进程是父还是子进程?
A:fork对父进程产生一个返回值(return value) 是进程原PID ,对子进程返回0
最初的进程 init
Q:既然所有进程都由fork创建的子进程,那终极父进程是谁?
A:init进程
unix启动时
系统会**”手动“创建一个特殊进程**(不用fork创建),并给一个PID为0(#0)被称为”空闲进程“。
- 他执行一些重要功能如初始化数据
- 随后**#0进程开始分枝(fork)出进程#1**
#1被#0分支出来的,就是init进程,而init进程会打开系统的控制台并挂载到根文件系统。
然后#1运行/etc/inittab这里的shell脚本,执行脚本过程中,#1用fork产生子进程来执行不同命令,如让用户登陆
- 随后**#0进入无限循环但不做任何事**件(名字由来)
- 当目前无任何进程时,系统将进入#0进程,并不做任何事。
综上所述
#0这个空闲进程才是真正的终极父进程,#1 init也是个子进程,但考虑到#0完成任务后就消失了(不做任何事,但进程还运行runing),因此,将#1称为 在活着的(living) 终极父进程
如果某个父进程在子进程结束前先没了,子进程将变成(orphans)孤儿,但init将领养这个孤儿,让他继续完成未完成的任务。
前台和后台进程
后台进程(background)
让进程自己运行,不用监看他运行,shell将不会等待进程完成,就会提示输入下一条命令
后台的进程也被称为自治进程
如:
要对一大堆数据排序,要花较长时间,则可以让进程自己运行,人可以再执行一些其它命令。可以用&(ampersan) 实现,告诉进程让他自己运行不用交互。
在一般命令后添加一个&
1 | sort < file > res & |
如果一行有多个命令
1 | (sleep 5;cat /etc/passwd) & #要用括号包起来 |
前台进程(foreground)
shell将等进程完成后再让输入下一命令
后台进程注意点
- 对于某些需要在进程执行还要输入信息的情况,如果进程得不到输入,就会一直等待到有输入,这时可以用:
fg命令
将此进程移到前台并输入相关信息
- 后台正在的进程会将输出到监视器或指定要某个文件中(推荐)
- 后台进程的输入会被用/dev/nul代替,并且无法用ctrl+c或其它方式中断。当然,可以用
kill
来结束后台进程
当后台进程完成时,shell会发送一条信息如
1 | [1] Done ls>temp #表示进程完成 |
当然,shell不会不识相的突然打断正在进行的工作并发出这条提醒,而在下一次正常提示其它命令信息时附加这条完成信息
- 如不想要提示信息
1 | set -o notify 就没了 |
sleep命令#让进程延迟启动
语法
1 | sleep interval[s|m|h|d] #interval是延迟时间 |
如
1 | sleep 5 5秒(默认以秒为单位) |
jobs命令#显示全部的工作 #1/#2/#3
1 | ps process status #显示全部进程 |
ctrl + Z 将当前进程悬挂
echo $$显示当前shell 的PID
echo $! 显示上一个被移动到后端的命令
fg命令#将job移动到前端
语法
- fg %[job]
1 | fg %num #则为通用方法 |
若不添加**[job]**则恢复当前正在执行的job(有+)
或者可以用某个命令开头
1 | fg %make / fg %m /fg %?game |
再或者
1 | fg %+ / fg %- |
%常用表
%% 当前job
%+ 当前job
%- 之前job
%n job#n
%name 用具体名字
%?name 命令的一部分
[8]- running make game > res &
[1]+ running gcc program.c &
举例:正在执行vim 编辑,突然想查找cal,可以将vim悬挂到后台按ctrl+z,在shell中输入cal 再将vim从后台中fg出来
ctrl+z
后,shell给出一条提示,表示job#1 被停止
1 | [1]+ Stopped vim testf #表示testf已经停止 |
fg %或fg %vim
后可以恢复vim testf
suspend命令#将当前shell悬挂
按ctrl+z
可以将job悬挂到后台,除了当前shell。如想将当前shell也悬挂,要用suspend
功能:
- 将当前shell悬挂,可以快速切换不同的身份
语法
- suspend [-f]
举例
- 在bash shell下开了tcsh
- 在tcsh下,可以用suspend悬挂tcsh并bg到原bash
多任务同时协作
jobs展示目前执行的
语法:
- jobs [-l]
1 | jobs |
- jobs -l 可以显示进程PID
1 | jobs -l |
- 其中的+表示,current job正在执行的job
- 对应的-表示 之前的job
bg命令#将job移动到后端
语法
- bg [%job]
用法和fg一样,%后可以接数字、命令、命令部分
bg一般配合ctrl+z
使用,如在等待某个程序输出时,此时不能输入命令,按ctrl+z
将进程悬挂,再输入bg
将进程放入后台。
ps命令#查看进程信息
(process status) 查看进程信息
语法
- ps [-aefFly] [-p pid] [-u uid ]
选项
显示哪些文件
- -a 将userid与进程相关
- -e (everything)全部的进程包含系统进程
- -p pid 查找指定PID
- -u uid 查找UID
- -t 只显示系统进程
显示哪些数据
- 默认 PID TTY TIME CMD
- 常用 -f UID PID PPID C TTY TIME CMD
- -ly S UID PID PPID C PRI NI RSS SZ WCHAN TTY TIME CMD
TTY是终端名
CMD是正在执行的命令
TIME是使用cpu时间
PID是当前进程id
PPID是父进程id
WCHAN 等待的状态?有wait/finish等值
S 状态 R runing T suspended S waiting
SZ 物理大小(占用内存情况)
ps -ef 常用,可以查看全部的进程并包含UID
使用ps 查找非系统进程,再显示出PID后再用ps -f -p 1234
显示具体信息
1 | ps |
top命令#实时监视系统进程
功能:
- top可以展示系统实时变化的信息
- 按h可以查看按键帮助
语法:
- top -d delay -n count [-p pid[,pid]]
选项
- -d 1 每隔1秒刷新 /0.1s
- -p PID 可以显示某个进程详细信息
- -p -d 1 -p 1,2,3,4,5 可以展示多个PID
pstree命令
功能:
- 展示进程树
上文提到过 :每个进程都由其它进程复制的,源进程为父,新进程为子,而且子进程也有PID
#0被手动创建后,fork出子进程#1,再由#1执行各种操作,产生其它进程#3.4.5
而这些#3,4,5被称为守护进程,任务是等待事件发生并做出反馈
登陆进程会一直等着用户登陆,一旦用户登陆,登陆进程会创建新进程来执行shell
而shell又会执行命令,创建新进程
于是,每个进程便有唯一的父进程,整个进程系统可以用一棵树结构表示
语法
- pstree [-aAcGnpu] [pid|userid]
选项
- -p PID 指定PID/UID 将展示属于UID的(全部)进程
- -n 按PID排序
- -a 展示整个命令行
- -u 在子进程与父进程不同UID时标记
举例
- 用ps或echo $$查出当前shell的PID,再用pstree -p PID查出当前sh的结构
1 | echo $$ |
Unix如何管理文件和进程
- 文件有文件系统,有文件树,根是root/ 每个文件有I-number 查看文件信息时,用ls 只要查看文件的I-node就行
- 进程有进程系统,进程树,根是#1 init 每个进程有PID 查看进程时,用ps/top 要在进程所在的/proc目录下,找到进程对应文件,再从文件中读取出信息
Q:那有什么命令可以打通文件与进程的关系吗?
fuser
A:可以列出每个进程所用到的文件
1 | find ./ -name '*.mp3' >bar 2>/dev/null & #让find在后台查找全部的mp3 把输出给bar |
kill命令#给job发送一个信号
- 给其它进程发送信号
- 停止一个进程 对某些进程不能用ctrl+c停止时(如后台进程)
停止进程
语法
- kill [-9] PID | jobid
如
- kill 2233或像fg/bg一样
- kill %vim
- kill %+ 停止当前运行进程
如果kill也失效 -9 强制停止,保证一定会停止
kill -9 2233 ----但此方法不会让进程释放使用的资源,可能会导致文件错误关闭,要少用
发送信号
kill本来是用于给不同进程发送信号的,但默认下发送结束进程信号,所以被叫做kill
语法
- kill [-signal] pid | jobid
使用kill -l可以查看全部的信号