看一眼进程
我们可以使用$ps命令来查询正在运行的进程,比如$ps -eo pid,comm,cmd,下图为执行结果:(-e表示列出全部进程,-o pid,comm,cmd表示我们需要PID,COMMAND,CMD信息)
每一行代表了一个进程。每一行又分为三列。第一列PID(process IDentity)是一个整数,每一个进程都有一个唯一的PID来代表自己的身份,进程也可以根据PID来识别其他的进程。第二列COMMAND是这个进程的简称。第三列CMD是进程所对应的程序以及运行时所带的参数。
(第三列有一些由中括号[]括起来的。它们是内核的一部分功能,被打扮成进程的样子以方便操作系统管理。我们不必考虑它们。)
我们看第一行,PID为1,名字为init。这个进程是执行/bin/init这一文件(程序)生成的。当Linux启动的时候,init是系统创建的第一个进程,这一进程会一直存在,直到我们关闭计算机。
如何创建一个进程
实际上,当计算机开机的时候,内核(kernel)只建立了一个init进程。Linux内核并不提供直接建立新进程的系统调用。剩下的所有进程都是init进程通过fork机制建立的。
新的进程要通过老的进程复制自身得到,这就是fork。fork是一个系统调用。进程存活于内存中。每个进程都在内存中分配有属于自己的一片空间 (address space)。
当进程fork的时候,Linux在内存中开辟出一片新的内存空间给新的进程,并将老的进程空间中的内容复制到新的空间中,此后两个进程同时运行。
老进程成为新进程的父进程(parent process),而相应的,新进程就是老的进程的子进程(child process)。一个进程除了有一个PID之外,还会有一个PPID(parent PID)来存储的父进程PID。如果我们循着PPID不断向上追溯的话,总会发现其源头是init进程。所以说,所有的进程也构成一个以init为根的树状结构。
如下,我们查询当前shell下的进程:
root@vamei:~# ps -o pid,ppid,cmd
PID PPID CMD
16935 3101 sudo -i
16939 16935 -bash
23774 16939 ps -o pid,ppid,cmd
我们可以看到,第二个进程bash是第一个进程sudo的子进程,而第三个进程ps是第二个进程的子进程。
还可以用$pstree命令来显示整个进程树:
init─┬─NetworkManager─┬─dhclient
│ └─2*[{NetworkManager}]
├─accounts-daemon───{accounts-daemon}
├─acpid
├─apache2─┬─apache2
│ └─2*[apache2───26*[{apache2}]]
├─at-spi-bus-laun───2*[{at-spi-bus-laun}]
├─atd
├─avahi-daemon───avahi-daemon
├─bluetoothd
├─colord───2*[{colord}]
├─console-kit-dae───64*[{console-kit-dae}]
├─cron
├─cupsd───2*[dbus]
├─2*[dbus-daemon]
├─dbus-launch
├─dconf-service───2*[{dconf-service}]
├─dropbox───15*[{dropbox}]
├─firefox───27*[{firefox}]
├─gconfd-2
├─geoclue-master
├─6*[getty]
├─gnome-keyring-d───7*[{gnome-keyring-d}]
├─gnome-terminal─┬─bash
│ ├─bash───pstree
│ ├─gnome-pty-helpe
│ ├─sh───R───{R}
│ └─3*[{gnome-terminal}]
进程的状态
进程又分为以下几种状态:
- 运行(正在运行或在运行队列中等待)
- 中断(休眠中, 受阻, 在等待某个条件的形成或接受到信号)
- 不可中断(收到信号不唤醒和不可运行, 进程必须等待直到有中断发生)
- 僵死(进程已终止, 但进程描述符存在, 直到父进程调用wait4()系统调用后释放)
- 停止(进程收到SIGSTOP, SIGSTP, SIGTIN, SIGTOU信号后停止运行运行)
其对应在ps上的相应状态码如下:
状态 | 定义 |
---|---|
R | running 运行中 |
S | Interruptible Sleep.等待调用 |
D | Uninterruptible Sleep.等待磁盘IO |
T | Stoped.暂停或者跟踪状态 |
X | Dead.即将被撤销 |
Z | Zombie.进程已经结束,仅映像名留存 |
W | Paging.内存交换 |
N | 优先级低的进程 |
< | 优先级高的进程 |
s | 进程的领导者 |
L | 锁定状态 |
l | 多线程状态 |
+ | 前台进程 |
平时在查看linux进程状态时,查看最多的三个状态是R S D :
- R状态,不必多说,R就是running的缩写,即运行中的进程。
- S 即 sleep进程,休眠进程。其又分为两种:
- Interruptible Sleep(可中断睡眠,在ps命令中显示“S”)。处在这种睡眠状态的进程是可以通过给它发送signal来唤醒的,比如发HUP信号给nginx的master进程可以让nginx重新加载配置文件而不需要重新启动nginx进程;
- Uninterruptible Sleep(不可中断睡眠,在ps命令中显示“D”)。处在这种状态的进程不接受外来的任何signal,这也是为什么之前我无法用kill杀掉这些处于D状态的进程,无论是“kill”, “kill -9”还是“kill -15”,因为它们压根儿就不受这些信号的支配。
D 即上面提到的Uninterruptible Sleep ,如果从广义上来分,D状态算是一种特殊的S状态进程。进程为什么会被置于D状态呢?
D状态的进程通常是在等待IO,比如磁盘IO,网络IO,其他外设IO,如果进程正在等待的IO在较长的时间内都没有响应,那么就很会不幸地被ps看到了,同时也就意味着很有可能有IO出了问题,可能是外设本身出了故障,也可能是比如NFS挂载的远程文件系统已经不可访问了。
前台进程和后台进程
前台进程
指一个进程控制着标准输入/输出,在程序运行时,shell被暂时挂起,直到程序运行结束。在这个过程中,用户不能执行其他程序。
后台进程
用户不必等待这个任务结束就可以运行其它进程。
一个终端只能运行一个前台进程,但是可以运行多个后台进程。
运行后台进程
可以在命令之后加上一个 & 来讲进程放到后台执行。
sleep 60 &
但是,放到后台运行的进程仍然会在termital 退出的时候退出。
如果当前程序已经在前台运行,想把它转到后台运行,可以使用ctr+z将其挂起,然后利用bg命令将其转到后台运行。
如果需要将一个命令转到前台运行,可以使用命令fg。
root@ubuntu:~# sleep 60
^Z
[1]+ Stopped sleep 60
root@ubuntu:~# bg
[1]+ sleep 60 &
root@ubuntu:~# jobs
[1]+ Running sleep 60 &
root@ubuntu:~# fg
sleep 60
另外,可以使用jobs查看后台挂起的进程。
root@ubuntu:~# sleep 111
^Z
[1]+ Stopped sleep 111
root@ubuntu:~# bg
[1]+ sleep 111 &
root@ubuntu:~# sleep 112
^Z
[2]+ Stopped sleep 112
root@ubuntu:~# bg
[2]+ sleep 112 &
root@ubuntu:~# sleep 113
^Z
[3]+ Stopped sleep 113
root@ubuntu:~# bg
[3]+ sleep 113 &
root@ubuntu:~# jobs
[1] Running sleep 111 &
[2]- Running sleep 112 &
[3]+ Running sleep 113 &
使用jobs需要在同一个terminal,在另外一个terminal 是看不到当前的jobs信息的。
- 第一列表示任务号
- + 表示当前任务
- - 表示当前任务之前开始的任务
root@ubuntu:~# jobs
root@ubuntu:~# jobs
任务运行结束后,执行状态由running变成done。
root@ubuntu:~# jobs
[1] Done sleep 111
[2]- Done sleep 112
[3]+ Done sleep 113
nohup
刚刚看到执行的命令在terminal退出之后就退出了,如果希望运行的命令在terminal退出之后不退出,那么可以使用nohup。
nohup sleep 60 &
进程的nice值和优先级
在任务队列中的进程不享有相同的优先级,每个进程都有一个指定的nice值(优先级权值),从 -20 到19。
- 可以使用
nice
命令查看缺省的优先级。
root@ubuntu:~# nice
0
- 可以使用
ps -l [pid]
查看指定进程的优先级。
root@ubuntu:~# ps -l 1831
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 S 112 1831 1 0 80 0 - 85927 poll_s ? 0:00 /usr/lib/x86_64-linux-gnu/notify-osd
调整进程的优先级
可以在进程启动的时候调整进程的优先级,使用命令:nice
在进程启动的时候指定进程的优先级,命令格式:
nice -n 命令 &
n 是优先级的增量,如果:
- n 是正数:表示增加nice 的值,也就是降低进程的优先级。
- n 是负数:表示减少nice 的值,也就是增加进程的优先级。
- 若为缺省:则是10, 表示增加nice值10 。
注:
普通用户只能增加nice值,只有管理员才能降低一个进程的nice值。
进程运行后调整nice值
使用renice命令修改已经运行的进程的nice值, 例如:
renice 5 2673
增加进程2673 的nice值。
普通用户一旦增加了nice值,就无法恢复到原来的nice值。