进程启动的方式

在 Linux 系统中,每个进程都有一个唯一的进程号(PID),方便系统识别和调度进程。通过简单地输出运行程序的程序名,就可以运行该程序,其实也就是启动了一个进程。

总体来说,启动一个进程主要有 2 种途径,分别是通过手工启动和通过调度启动(事先进行设置,根据用户要求,进程可以自行启动),接下来就一一介绍这 2 中方式。

Linux手工启动进程

手工启动进程指的是由用户输入命令直接启动一个进程,根据所启动的进程类型和性质的不同,其又可以细分为前台启动和后台启动 2 种方式。

前台启动进程

这是手工启动进程最常用的方式,因为当用户输入一个命令并运行,就已经启动了一个进程,而且是一个前台的进程,此时系统其实已经处于一个多进程的状态(一个是 Shell 进程,另一个是新启动的进程)。

假如启动一个比较耗时的进程,然后再把该进程挂起,并使用 ps 命令查看,就会看到该进程在 ps 显示列表中,例如:

1
2
3
4
5
6
7
8
[root@localhost ~]# find / -name demo.jpg <--在根目录下查找 demo.jpg 文件,比较耗时
#此处省略了该命令的部分输出信息
#按“CTRL+Z”组合键,即可将该进程挂起
[root@localhost ~]# ps <--查看正在运行的进程
PID TTY TIME CMD
2573 pts/0 00:00:00 bash
2587 pts/0 00:00:01 find
2588 pts/0 00:00:00 ps

将进程挂起,指的是将前台运行的进程放到后台,并且暂停其运行。

通过运行ps命令查看进程信息,可以看到,刚刚执行的find命令的进程号为 2587,同时ps进程的进程号为 2588。

后台启动进程

进程直接从后台运行,用的相对较少,除非该进程非常耗时,且用户也不急着需要其运行结果的时候,例如,用户需要启动一个需要长时间运行的格式化文本文件的进程,为了不使整个 Shell 在格式化过程中都处于“被占用”状态,从后台启动这个进程是比较明智的选择。

从后台启动进程,其实就是在命令结尾处添加一个 “ &” 符号(注意,& 前面有空格)。输入命令并运行之后,Shell 会提供给我们一个数字,此数字就是该进程的进程号。然后直接就会出现提示符,用户就可以继续完成其他工作,例如:

1
2
3
[root@localhost ~]# find / -name install.log &
[1] 1920
#[1]是工作号,1920是进程号

以上介绍了手工启动的 2 种方式,实际上它们有个共同的特点,就是新进程都是由当前 Shell 这个进程产生的,换句话说,是 Shell 创建了新进程,于是称这种关系为进程间的父子关系,其中 Shell 是父进程,新进程是子进程。

值得一提的是,一个父进程可以有多个子进程,通常子进程结束后才能继续父进程;当然,如果是从后台启动,父进程就不用等待子进程了。

Linux调度启动进程

在 Linux 系统中,任务可以被配置在指定的时间、日期或者系统平均负载量低于指定值时自动启动。

例如,Linux 预配置了重要系统任务的运行,以便可以使系统能够实时被更新,系统管理员也可以使用自动化的任务来定期对重要数据进行备份。

实现调度启动进程的方法有很多,例如通过 crontab、at 等命令。

ps命令:查看正在运行的进程

ps 命令是最常用的监控进程的命令,通过此命令可以查看系统中所有运行进程的详细信息。

ps 命令有多种不同的使用方法,这常常给初学者带来困惑。在各种 Linux 论坛上,询问 ps 命令语法的帖子屡见不鲜,而出现这样的情况,还要归咎于 UNIX 悠久的历史和庞大的派系。在不同的 Linux 发行版上,ps 命令的语法各不相同,为此,Linux 采取了一个折中的方法,即融合各种不同的风格,兼顾那些已经习惯了其它系统上使用 ps 命令的用户。

ps 命令的基本格式如下:
[root@localhost ~]# ps aux
#查看系统中所有的进程,使用 BS 操作系统格式
[root@localhost ~]# ps -le
#查看系统中所有的进程,使用 Linux 标准命令格式

选项:
a:显示一个终端的所有进程,除会话引线外;
u:显示进程的归属用户及内存的使用情况;
x:显示没有控制终端的进程;
-l:长格式显示更加详细的信息;
-e:显示所有进程;
可以看到,ps 命令有些与众不同,它的部分选项不能加入”-“,比如命令”ps aux”,其中”aux”是选项,但是前面不能带“-”。

大家如果执行 “man ps” 命令,则会发现 ps 命令的帮助为了适应不同的类 UNIX 系统,可用格式非常多,不方便记忆。所以,我建议大家记忆几个固定选项即可。比如:
“ps aux” 可以查看系统中所有的进程;
“ps -le” 可以查看系统中所有的进程,而且还能看到进程的父进程的 PID 和进程优先级;
“ps -l” 只能看到当前 Shell 产生的进程;

有这三个命令就足够了,下面分别来查看。

【例 1】
[root@localhost ~]# ps aux
#查看系统中所有的进程
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.2 2872 1416 ? Ss Jun04 0:02 /sbin/init
root 2 0.0 0.0 0 0 ? S Jun04 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? S Jun04 0:00 [migration/0]
root 4 0.0 0.0 0 0 ? S Jun04 0:00 [ksoftirqd/0]
…省略部分输出…
表 1 中罗列出了以上输出信息中各列的具体含义。

表 1 ps命令输出信息含义
表头 含义
USER 该进程是由哪个用户产生的。
PID 进程的 ID。
%CPU 该进程占用 CPU 资源的百分比,占用的百分比越高,进程越耗费资源。
%MEM 该进程占用物理内存的百分比,占用的百分比越高,进程越耗费资源。
VSZ 该进程占用虚拟内存的大小,单位为 KB。
RSS 该进程占用实际物理内存的大小,单位为 KB。
TTY 该进程是在哪个终端运行的。其中,tty1 ~ tty7 代表本地控制台终端(可以通过 Alt+F1 ~ F7 快捷键切换不同的终端),tty1~tty6 是本地的字符界面终端,tty7 是图形终端。pts/0 ~ 255 代表虚拟终端,一般是远程连接的终端,第一个远程连接占用 pts/0,第二个远程连接占用 pts/1,依次増长。
STAT 进程状态。常见的状态有以下几种:
-D:不可被唤醒的睡眠状态,通常用于 I/O 情况。
-R:该进程正在运行。
-S:该进程处于睡眠状态,可被唤醒。
-T:停止状态,可能是在后台暂停或进程处于除错状态。
-W:内存交互状态(从 2.6 内核开始无效)。
-X:死掉的进程(应该不会出现)。
-Z:僵尸进程。进程已经中止,但是部分程序还在内存当中。
-<:高优先级(以下状态在 BSD 格式中出现)。
-N:低优先级。
-L:被锁入内存。
-s:包含子进程。
-l:多线程(小写 L)。
-+:位于后台。
START 该进程的启动时间。
TIME 该进程占用 CPU 的运算时间,注意不是系统时间。
COMMAND 产生此进程的命令名。
【例 2】”ps aux”命令可以看到系统中所有的进程,”ps -le”命令也能看到系统中所有的进程。由于 “-l” 选项的作用,所以 “ps -le” 命令能够看到更加详细的信息,比如父进程的 PID、优先级等。但是这两个命令的基本作用是一致的,掌握其中一个就足够了。
[root@localhost ~]# ps -le
F S UID PID PPID C PRI Nl ADDR SZ WCHAN TTY TIME CMD
4 S 0 1 0 0 80 0 - 718 - ? 00:00:02 init
1 S 0 2 0 0 80 0 - 0 - ? 00:00:00 kthreadd
1 S 0 3 2 0 -40 - - 0 - ? 00:00:00 migration/0
1 S 0 4 2 0 80 0 - 0 - ? 00:00:00 ksoflirqd/0
1 S 0 5 2 0 -40 - - 0 - ? 00:00:00 migration/0
…省略部分输出…
表 2 罗列出以上输出信息中各列的含义。

表 2 ps -le 命令输出信息
表头 含义
F 进程标志,说明进程的权限,常见的标志有两个:
1:进程可以被复制,但是不能被执行;
4:进程使用超级用户权限;
S 进程状态。具体的状态和”psaux”命令中的 STAT 状态一致;
UID 运行此进程的用户的 ID;
PID 进程的 ID;
PPID 父进程的 ID;
C 该进程的 CPU 使用率,单位是百分比;
PRI 进程的优先级,数值越小,该进程的优先级越高,越早被 CPU 执行;
NI 进程的优先级,数值越小,该进程越早被执行;
ADDR 该进程在内存的哪个位置;
SZ 该进程占用多大内存;
WCHAN 该进程是否运行。”-“代表正在运行;
TTY 该进程由哪个终端产生;
TIME 该进程占用 CPU 的运算时间,注意不是系统时间;
CMD 产生此进程的命令名;
【例 3】如果不想看到所有的进程,只想查看一下当前登录产生了哪些进程,那只需使用 “ps -l” 命令就足够了:
[root@localhost ~]# ps -l
#查看当前登录产生的进程
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 18618 18614 0 80 0 - 1681 - pts/1 00:00:00 bash
4 R 0 18683 18618 4 80 0 - 1619 - pts/1 00:00:00 ps
可以看到,这次从 pts/1 虚拟终端登录,只产生了两个进程:一个是登录之后生成的 Shell,也就是 bash;另一个是正在执行的 ps 命令。

我们再来说说僵尸进程。僵尸进程的产生一般是由于进程非正常停止或程序编写错误,导致子进程先于父进程结束,而父进程又没有正确地回收子进程,从而造成子进程一直存在于内存当中,这就是僵尸进程。

僵尸进程会对主机的稳定性产生影响,所以,在产生僵尸进程后,一定要对产生僵尸进程的软件进行优化,避免一直产生僵尸进程;对于已经产生的僵尸进程,可以在查找出来之后强制中止。

top命令:持续监听进程运行状态

pstree命令:查看进程树

lsof命令:列出进程调用或打开的文件信息

进程优先级

nice和renice命令:改变进程优先级

常用信号(进程间通信)

进程的管理主要是指进程的关闭与重启。我们一般关闭或重启软件,都是关闭或重启它的程序,而不是直接操作进程的。比如,要重启 apache 服务,一般使用命令”service httpd restart”重启 apache的程序。

那么,可以通过直接管理进程来关闭或重启 apache 吗?答案是肯定的,这时就要依赖进程的信号(Signal)了。我们需要给予该进程号,告诉进程我们想要让它做什么。

系统中可以识别的信号较多,我们可以使用命令”kill -l”或”man 7 signal”来查询。命令如下:

1
2
3
4
5
[root@localhost ~]#kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11)SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15)SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG
24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN +4 39) SIGRTMIN +5 40) SIGRTMIN+6 41)SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN +9 44) SIGRTMIN +10 45) SIGRTMIN+11 46) SIGRTMIN+1247) SIGRTMIN+13 48) SIGRTMIN +14 49) SIGRTMIN +15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX

常见的进程信号:

| 信号代号 | 信号名称 | 说 明 |

| 1 | SIGHUP | 该信号让进程立即关闭.然后重新读取配置文件之后重启 |
| 2 | SIGINT | 程序中止信号,用于中止前台进程。相当于输出 Ctrl+C 快捷键 |
| 8 | SIGFPE | 在发生致命的算术运算错误时发出。不仅包括浮点运算错误,还包括溢出及除数为 0 等其他所有的算术运算错误 |
| 9 | SIGKILL | 用来立即结束程序的运行。本信号不能被阻塞、处理和忽略。般用于强制中止进程 |
| 14 | SIGALRM | 时钟定时信号,计算的是实际的时间或时钟时间。alarm 函数使用该信号 |
| 15 | SIGTERM | 正常结束进程的信号,kill 命令的默认信号。如果进程已经发生了问题,那么这 个信号是无法正常中止进程的,这时我们才会尝试 SIGKILL 信号,也就是信号 9 |
| 18 | SIGCONT | 该信号可以让暂停的进程恢复执行。本信号不能被阻断 |
| 19 | SIGSTOP | 该信号可以暂停前台进程,相当于输入 Ctrl+Z 快捷键。本信号不能被阻断 |

其中最重要的就是 “1”、”9”、”15”这三个信号,我们只需要记住这三个信号即可。

kill命令:终止进程

kill命令只是用来向进程发送一个信号,至于这个信号是什么,是用户指定的。

也就是说,kill命令的执行原理是这样的,kill命令会向操作系统内核发送一个信号(多是终止信号)和目标进程的PID,然后系统内核根据收到的信号类型,对指定进程进行相应的操作。

1
[root@localhost ~]# kill [信号] PID

kill命令是按照PID来确定进程的,所以kill命令只能识别PID,而不能识别进程名。Linux 定义了几十种不同类型的信号,可以使用kill -l命令查看所有信号及其编号。

kill命令常用信号及其含义:

信号编号 信号名 含义
0 EXIT 程序退出时收到该信息。
1 HUP 挂掉电话线或终端连接的挂起信号,这个信号也会造成某些进程在没有终止的情况下重新初始化。
2 INT 表示结束进程,但并不是强制性的,常用的 “Ctrl+C” 组合键发出就是一个 kill -2 的信号。
3 QUIT 退出。
9 KILL 杀死进程,即强制结束进程。
11 SEGV 段错误。
15 TERM 正常结束进程,是 kill 命令的默认信号。

需要注意的是,表中省略了各个信号名称的前缀SIG,也就是说,SIGTERMTERM这两种写法都对,kill命令都可以理解。

示例

标准 kill 命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@localhost ~】# service httpd start
#启动RPM包默认安装的apache服务
[root@localhost ~]# pstree -p 丨 grep httpd | grep -v "grep"
#查看 httpd 的进程树及 PID。grep 命令査看 httpd 也会生成包含"httpd"关键字的进程,所以使用“-v”反向选择包含“grep”关键字的进程,这里使用 pstree 命令来查询进程,当然也可以使用 ps 和 top 命令
|-httpd(2246)-+-httpd(2247)
| |-httpd(2248)
| |-httpd(2249)
| |-httpd(2250)
| |-httpd(2251)
[root@localhost ~]# kill 2248
#杀死PID是2248的httpd进程,默认信号是15,正常停止
#如果默认信号15不能杀死进程,则可以尝试-9信号,强制杀死进程
[root@localhost ~]# pstree -p | grep httpd | grep -v "grep"
|-httpd(2246>-+-httpd(2247)
| |-httpd(2249)
| |-httpd(2250)
| |-httpd(2251)
#PID是2248的httpd进程消失了

使用“-1”信号,让进程重启。

1
2
3
4
5
6
7
8
9
[root@localhost ~]# kill -1 2246
使用“-1 (数字1)”信号,让httpd的主进程重新启动
[root@localhost ~]# pstree -p | grep httpd | grep -v "grep"
|-httpd(2246)-+-httpd(2270)
| |-httpd(2271)
| |-httpd(2272)
| |-httpd(2273)
| |-httpd(2274)
#子httpd进程的PID都更换了,说明httpd进程已经重启了一次

使用“-19”信号,让进程暂停。

1
2
3
4
5
6
7
8
9
[root@localhost ~]# vi test.sh #使用vi命令编辑一个文件,不要退出
[root@localhost ~]# ps aux | grep "vi" | grep -v "grep"
root 2313 0.0 0.2 7116 1544 pts/1 S+ 19:2.0 0:00 vi test.sh
#换一个不同的终端,查看一下这个进程的状态。进程状态是S(休眠)和+(位于后台),因为是在另一个终端运行的命令
[root@localhost ~]# kill -19 2313
#使用-19信号,让PID为2313的进程暂停。相当于在vi界面按 Ctrl+Z 快捷键
[root@localhost ~]# ps aux | grep "vi" | grep -v "grep"
root 2313 0.0 0.2 7116 1580 pts/1 T 19:20 0:00 vi test.sh
#注意2313进程的状态,变成了 T(暂停)状态。这时切换回vi的终端,发现vi命令已经暂停,又回到了命令提示符,不过2313进程就会卡在后台。如果想要恢复,可以使用"kill -9 2313”命令强制中止进程,

使用kill命令一定可以终止一个进程吗?

答案是否定的。kill命令只是“发送”一个信号,因此,只有当信号被程序成功“捕获”,系统才会执行kill命令指定的操作;反之,如果信号被“封锁”或者“忽略”,则kill命令将会失效。

打赏

扫一扫,分享到微信

微信分享二维码
  • Copyrights © 2017-2023 WSQ
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信