往期目录:
这节教程我们来学习Linux系统中的进程管理。
一、进程
进程是操作系统为执行程序分配资源的基本单位。它是程序在系统中运行的一个实例。
每个进程都包含:
- 程序代码:进程正在执行的指令。
- 进程数据:进程运行时使用的变量、堆栈等数据。
- 进程控制块(PCB):操作系统为进程分配的控制信息,包括进程ID、状态、优先级、寄存器、内存地址等。
那么我们思考一下程序和进程它们之间有什么区别呢?
程序是静态的,它只是一段存储在磁盘中的代码,描述了一个待执行的任务,而进程是程序的动态执行实例。当程序被加载到内存并开始执行时,就成为了一个进程。
这里可能大家还是有一点蒙,这里我们就以QQ软件的运行来解释程序和进程的区别。
程序=QQ程序
我们通过官网下载好QQ以后就会在我们的电脑上创建对应的文件夹,它包含了所有需要的代码和资源,它只是一个静态的文件夹。
进程=正在运行的QQ
当我们使用鼠标去点击QQ程序的时候,QQ程序开始执行。操作系统会将它加载到内存中,并为它分配计算资源。此时,QQ开始运行,它变成了一个进程。你可以看到QQ在桌面上打开,能够发消息、接收消息、显示聊天界面等。这时,QQ进程会占用CPU、内存等计算机资源。
当然我们有时候会在电脑上同时去运行多个QQ以登录多个账号,那么运行了多少个QQ就是有多少个QQ进程,因此我们可以总结出一个程序中可以有多个进程。
现在我们已经知道了进程的基本概念,下面我们来了解一下进程的生命周期:
- 新建 (New):进程被创建,但尚未开始执行。
- 就绪 (Ready):进程已经准备好,可以等待 CPU 资源来执行。
- 运行 (Running):进程当前正在使用 CPU 执行任务。
- 阻塞 (Blocked):进程正在等待某些事件或资源(如I/O操作、锁等)。
- 终止 (Terminated):进程执行完毕或被终止,等待系统清理。
最后我们再来了解一下在Linux中关于进程的一些基本概念:
- PID (Process ID):每个进程都有一个唯一的PID。
- 父进程 (Parent Process):启动某个进程的进程称为父进程。
- 子进程 (Child Process):由父进程创建的进程称为子进程。
- 会话 (Session):多个进程可以组成一个会话,通常是由一个shell进程启动的。
- 进程组 (Process Group):进程组是多个进程的集合,用于管理和控制一组进程。
关于进程的更多知识,大家可以自行学习操作系统相关知识。
二、查看进程
2.1 ps命令
ps(process status)命令用于显示当前运行的进程。
ps
我们可以从上图中看出ps命令默认只显示当前终端会话的进程。如果我们想查看所有进程,可以使用-e或者-A参数。
ps -e
ps -A
如果我们想要查看更加详细的信息可以在ps命令上加上-f参数。
上述命令可以查看所有进程的信息,如果我们只是想查看某个特定的进程信息,我们可以使用-p参数。
ps -p 进程ID
假设现在我们想要查看防火墙firewalld服务的进程的id或者相关信息,那么ps -p 进程ID这条命令就不行了,我们可以使用下述命令。
ps相关命令 | grep 进程名称
这里我们再来讲解一个ps命令的参数aux,该参数可以显示出所有用户的进程信息。
ps aux
这里我们可以思考一下-e参数可以查看所有进程的详细信息,而aux可以查看所有用户的详细信息,那么它们之间的区别如何呢?
aux参数和-e参数的区别如下表所示:
参数 | 输出内容 | 详细程度 |
---|---|---|
aux | 列出所有进程及详细信息,包括 PID、进程所有者、CPU/内存占用等。 | 高度详细,适合分析系统状态和进程资源使用情况 |
-e | 列出所有进程的 PID,不显示其他详细信息。 | 简单、精简,适合快速查看进程 ID |
2.2 top命令
top命令提供了一个实时更新(top命令会每隔几秒自动更新显示系统中资源使用最多的进程)的进程列表,可以显示 CPU、内存等资源的使用情况,启动top命令以后按q表示退出,按p表示排序cpu使用情况,按m表示排序内存使用情况。
top
2.3 htop命令
htop命令是top命令的一个增强版。
CentOS 7 的默认软件仓库中没有包含htop,因此我们需要先安装htop包。
yum install htop
执行上述命令以后我们可以发现安装不成功,这是因为我们要去先安装EPEL仓库。
yum install epel-release
安装好EPEL仓库以后我们就可以去安装htop包了。
yum install htop
现在我们就可以使用htop命令了。
htop
通过上述运行过程我们可以看出,htop相比于top命令加载的信息更加详细,它包含的信息如下所示:
- CPU 使用情况:显示 CPU 使用的百分比。
- 内存和交换空间(Swap):显示内存和交换空间的使用情况。
- 进程列表:显示所有进程的详细信息,包括 PID(进程ID)、用户、内存和 CPU 使用等。
- 系统负载:显示系统的负载(1分钟、5分钟和15分钟的平均负载)。
htop命令执行后会加载出来一个彩色的交互界面,该交互界面常见操作如下所示:
- 上下箭头:选择进程。
- F3:搜索进程。
- F6:排序进程(例如按 CPU 或内存使用排序)。
- F9:杀死进程。
- F10:退出 htop。
2.4 pstree命令
ps命令是查看系统中进程树结构的一种方式,该命令执行后会以树形结构显示系统中所有正在运行的进程及其父子关系。
我们在使用pstree命令之前需要先安装pstree包。
注意:在安装pstree包之前先安装EPEL仓库,当然我们前面已经安装好了,如果没有安装就重新安装一遍。
yum install epel-release
我这里表示已经安装好了。
接下来我们就可以安装pstree包了。
yum install pstree
执行命令以后发现没有可用的软件包,因此我们就需要思考一下为啥会出现这样的问题。
虽然我们刚才使用命令安装EPEL仓库,但有时,YUM 缓存可能会导致包信息不准确。我们可以清除 YUM 缓存并更新仓库,看看能否解决问题。
yum clean all
yum makecache
接着我们再来尝试一下安装pstree包。
yum install pstree
我们可以发现现在还是说找不到pstree软件包,那么我们就要考虑在Centos7中pstree的软件包名称可能不是petree,因此我们先去搜索一下pstree相关信息。
yum search pstree
根据执行结果我们可以看出,对于pstree命令,我们应该安装psmisc.x86_64包。
安装好以后我们来执行一下pstree命令。
如果我们想要查看完整的命令行,我们可以在pstree命令后面加上-a参数。
当然我们也可以只是查看特定进程。
我们在执行完ps命令以后可以发现,进程树过于庞大,因此我们可以通过-l参数去控制进程树的深度。
pstree -l 进程深度
我们知道Linux是一个多用户操作系统,也就是说一个Linux可以多个用户同时去操作,因此我们也可以通过-u和-c参数来查看特定用户的进程,其中-u参数可以查看特定用户的进程树,-c可以实现在众多用户线程中高亮显示当前用户的线程。
pstree -u 用户名称
pstree -c
2.5 pgrep命令
grep命令其实我们前面已经接触过了,前面我们将grep命令和ps、pstree等相关命令结合起来查询指定进程的详细信息,当然我们也可以直接使用pgrep命令进行查询。
pgrep -参数 进程名称
三、管理进程
3.1 启动进程
进程通常由用户通过命令行启动,这个命令要根据具体的任务来定。
进程启动命令
如果我们希望进程运行在后台,那么可以使用如下命令。
进程启动命令 &
如果我们想要某个进程启动时以守护进程(Daemon)形式运行,可以参考如下两种方式。
方式一:使用system管理守护进程
CentOS 7 默认使用systemd作为初始化系统,所有的系统服务都是通过systemd来管理的。因此,最推荐的方式是创建一个自定义的systemd服务单元。
步骤1:
创建一个新的systemd服务单元,也就是使用文本编辑器去创建一个service文件,例如/etc/systemd/system/demo1.service。(当然这个文件名字需要根据任务来定,这里作为演示就取名为demo1)
vim /etc/systemd/system/demo1.service
接下来我们就可以来配置demo1这个服务单元。
[Unit]
Description=My Daemon Application
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/myapp
Restart=always
User=nobody
Group=nogroup
Environment=MYAPP_ENV_VAR=value
[Install]
WantedBy=multi-user.target
这里只是随意举个例子。
步骤2:
配置好demo1服务单元以后,我们需要重新加载systemd配置,然后启动demo1服务。
systemclt daemon-reload
systemctl start demo1.service
systemctl enable demo1.service
启动好demo1服务以后可以通过命令去检查服务的运行状态。
systemctl status demo1.service
方式二:使用nohup命令
nohup 进程启动命令 &>日志输出路径 &
上述命令各个参数含义如下所示:
- nohup:使进程忽略挂起信号(
SIGHUP
),即使用户注销,进程仍然继续运行。 - &:将进程放到后台。
- &>日志输出路径:将标准输出和标准错误输出重定向到指定路径,以避免输出到终端。
例如:
nohup /usr/bin/myapp &>/dev/null &
方式三:使用disown命令
在将进程放到后台后,我们可以使用disown命令来让该进程与当前终端会话分离,从而继续在后台运行,也就是在后台启动进程并解除它与终端的绑定,该方式适合用于不依赖systemd的简单场景。
步骤1:启动进程
进程启动命令 &
步骤2:使用disown命令将进程从当前会话中进行分离
disown
3.2 终止进程
如果我们想要终止一个进程可以使用kill命令。
kill命令基本用法如下所示:
-
kill 进程id:根据进程id杀死进程。
-
kill -9 进程id:根据进程id强制终止进程,也就是当我们使用"kill 进程id"命令不能杀死进程的时候就可以使用该命令强制杀死进程。
-
kill 进程名称:根据进程名杀死进程。
-
killall 进程名称:杀死所有跟进程名同名的进程。
kill 进程id
kill -9 进程id
kill 进程名称
killall 进程名称
3.3 后台进程管理
【查看后台进程】
我们可以使用jobs命令查看当前 shell 会话中的后台任务。
jobs
【后台进程转为前台进程】
fg <jobnumber>
[前台进程转为后台进程]
bg <jobnumber>
3.4 进程优先级
3.4.1 nice命令
nice命令用于启动一个进程时设置其优先级。数字越小,优先级越高(负数代表提高优先级)。
nice -n 进程级别数值 进程启动命令
3.4.2 renice命令
renice命令用于改变一个已经运行的进程的优先级。
renice -n 进程级别数值 -p <PID>
3.5 进程状态
进程的状态通常由字母表示,这些字母代表进程的不同状态:
- R (Running or Runnable):运行中或可运行的状态。表示进程正在 CPU 上执行,或者它正在等待 CPU 时间片以便运行。
- S (Sleeping):睡眠状态。表示进程当前处于休眠状态,正在等待某些事件(例如,I/O 操作完成)。这通常是大部分进程的状态。
- Interruptible Sleep:通常可以被信号中断。
- Uninterruptible Sleep:进程正在等待某些系统资源(例如磁盘或网络),在此期间无法中断。
- D (Uninterruptible Sleep):不可中断的睡眠状态,表示进程正在等待某些硬件操作(如磁盘I/O)完成,这时它不能被信号中断。
- T (Stopped):已停止状态。进程已被暂停,通常是通过
SIGSTOP
或SIGTSTP
信号进行的暂停。也可能表示进程正在进行调试。 - Z (Zombie):僵尸进程。进程已经终止,但是父进程尚未获取它的退出状态。此时进程占用系统进程表项,但不再执行任何代码。
- X (Dead):已死状态,表示进程已经终止,但系统尚未清除它的相关信息。
- W (Paging):进程在等待内存分页。通常在系统内存压力大的情况下出现。
- < (High Priority):高优先级进程。表示进程具有较高的调度优先级,通常是内核线程或实时线程。
- N (Low Priority):低优先级进程。表示进程的调度优先级低于正常进程。
3.6 进程调度
在 CentOS 7 中,进程调度由 CFS(Completely Fair Scheduler) 调度器负责,它会根据进程的优先级、等待时间和 CPU 使用情况决定哪个进程获得 CPU 时间。
-
进程优先级:每个进程都有一个 nice 值,这个值越低,进程的优先级越高。默认的
nice
值是 0,负数表示更高的优先级。 -
调度策略:Linux 使用多种调度策略来决定进程的执行顺序,最常见的包括:
- CFS(Completely Fair Scheduler):公平调度器,根据进程的需要分配 CPU 时间。
- 实时调度:如 FIFO(先进先出)和 Round Robin(轮询调度)。
我们可以通过chrt命令来查看或设置进程的调度策略和优先级。
chrt -p 进程ID
3.7 进程通信
-
进程间通信(IPC,Inter-process Communication)是指多个进程之间的数据交换或信号传递。常见的进程间通信方法包括:
-
管道 (Pipe)
- 管道是单向的通信方式,允许一个进程将数据输出到另一个进程。
- 使用
|
管道符号将多个命令链接起来。
-
命名管道 (Named Pipe / FIFO)
- 与普通管道不同,命名管道允许两个没有亲缘关系的进程进行通信。
-
消息队列 (Message Queue)
- 允许进程发送和接收消息,提供了比管道更复杂的通信方式。
-
共享内存 (Shared Memory)
- 通过共享内存,多个进程可以直接访问同一块内存区域进行数据交换。
-
信号 (Signals)
- 信号是操作系统用来通知进程发生了某种事件的机制。例如,SIGINT 用于中断进程,SIGKILL 用于强制结束进程。
本节教程就先到这里,更多将在后续教程中进行展示。