在Linux系统中,进程和线程是两个不同的概念,但它们之间有着密切的关系。下面我来逐步讲解两者之间的关系:
进程和线程的定义
进程是正在运行的程序的一个实例,每个进程都有独立的内存空间和系统资源,是操作系统中最基本的单位。每个进程拥有自己的地址空间、堆栈、数据区和代码段等资源,并且可以创建和销毁其他进程。
线程是进程的一部分,是进程内的一个执行单元,也被称为轻量级进程。每个线程共享进程的资源,包括内存空间、文件描述符、信号处理等,但拥有自己的堆栈、程序计数器和局部变量等。线程之间可以共享数据,通过互斥锁、信号量等机制来保证线程之间的同步和互斥。
进程和线程的区别
进程和线程的区别主要在于资源的分配和调度。进程之间相互独立,每个进程都有自己的地址空间和系统资源,需要操作系统进行资源分配和调度。而线程之间共享进程的资源,相互之间可以共享数据,不需要像进程一样进行资源分配和调度,因此开销比较小。
进程和线程的关系
进程和线程之间是一种包含关系,每个进程都至少包含一个线程,称为主线程
。一个进程可以创建多个线程,这些线程共享进程的资源,可以并发地执行不同的任务,从而提高系统的效率。
进程和线程的优缺点
进程的优点是相互独立,安全性高,但开销比较大,不适合大量的并发操作。
线程的优点是开销小,可以并发执行多个任务,但相互之间的数据共享需要注意同步和互斥,否则容易出现竞争条件和死锁等问题。
总之,进程和线程是Linux系统中非常重要的概念,它们之间有着密切的关系。在实际应用中,我们需要根据具体的需求选择使用进程或线程,以达到最优的效果。
ps命令是一个用于查看当前系统进程的命令工具,用于显示当前正在运行的进程信息,包括进程ID、状态、CPU使用率、内存使用率等等
语法
ps 选项(参数) 要操作的对象
选项 | 解释 |
---|---|
-a | 显示所有进程信息,包括其他用户的进程 |
-u | 显示指定用户的进程信息 |
-x | 显示没有控制终端的进程信息 |
-e | 显示所有进程信息,等同于-a选项 |
-f | 显示详细的进程信息,包括进程的父进程ID、进程占用的CPU和内存等 |
-l | 显示长格式的进程信息,包括进程的状态、占用CPU和内存的大小等 |
-p <进程ID> | 显示指定进程的信息 |
-C | 显示指定命令的进程信息,例如ps -C sshd表示显示所有sshd进程的信息 |
ps命令的输出参数解释如下:
以ps -aux为例
显示所有用户的进程信息,包括无控制终端的进程,并以用户为主的格式来显示进程信息的命令
ps -aux
显示所有进程信息
ps -ef
显示指定进程的信息
ps -p ID
显示指定用户的进程信息
ps -u username
ps命令还可以与grep命令结合使用
例如:
显示所有包含关键字“sshd”的进程信息
ps -ef | grep sshd
显示父进程,子进程的目录结构信息
ps -eH
自定义进程查看的格式
ps -eo pid,ppid,command
带减号的参数是用来控制程序的行为,不带减号的参数是用来指定程序处理的对象或数据
简单来说,带减号的参数是用来告诉程序要做什么,不带减号的参数是用来告诉程序要处理哪些数据
下面来看几个实例:
带减号的参数
假设要用ps命令查看进程信息,想要只显示当前用户的进程信息,并且按照CPU使用率排序,可以使用以下命令
ps -U username --sort=-pcpu
其中-U
表示只显示指定用户的进程信息
--sort=-pcpu
表示按照CPU使用率倒序排序
这些带减号的参数都是用来控制程序的行为
不带减号的参数
继续以ps命令为例,假设要查看所有进程的详细信息,可以使用以下命令
ps aux
其中aux
就是不带减号的参数,用来告诉程序要显示哪些数据,即所有进程的详细信息。
如果没有pstree命令就得先安装
yum install -y psmisc
然后使用pstree命令就能够清晰的表达程序之间的层级相互关系
[root@localhost ~]# pstree
systemd─┬─NetworkManager───2*[{NetworkManager}]
├─VGAuthService
├─agetty
├─anacron
├─auditd───{auditd}
├─chronyd
├─crond
├─dbus-daemon───{dbus-daemon}
├─irqbalance
├─lvmetad
├─master─┬─pickup
│ └─qmgr
├─polkitd───6*[{polkitd}]
├─rsyslogd───2*[{rsyslogd}]
├─sshd─┬─sshd─┬─bash───pstree
│ │ ├─bash───top
│ │ └─bash───sleep
│ └─sshd───6*[sftp-server]
├─systemd-journal
├─systemd-logind
├─systemd-udevd
├─tuned───4*[{tuned}]
└─vmtoolsd───2*[{vmtoolsd}]
pgrep命令是一个用于根据进程名或进程ID查找进程的命令工具,可以用于查找正在运行的进程及其进程ID。
语法
pgrep 选项 进程名(进程ID)
查询nginx进程是否存在
pgrep nginx
输出sshd的进程ID号,及进程名
pgrep -l sshd
# 参数
-l 只显示进程ID以及进程名称
kill命令是Linux/Unix操作系统下的一个命令,用于终止进程,通常用于停止一个正在运行的程序。
常用语法
kill 选项
选项
-l :列出所有可用的信号
-f :强制终止进程,不进行任何提示
-u : 指定某个用户的所有进程
-p : 指定要终止的进程ID
-s < 信号 > : 指定终止进程的信号
列出所有可用信号
使用kill命令时,可以通过-s选项来指定要发送的信号
例如
中断PID为1234的进程
kill -s SIGINT 1234
# 上述命令也可以等同于这个命令 kill -2 1234
通过PID终止进程1234
kill 1234
# kill 1234 等同于 kill -15 1234
杀死进程1234
kill -9 1234
终止某个用户的所有进程
kill -u <某个用户>
注意:使用kill命令时,请小心操作,避免误杀重要进程
kill命令的-0选项并不是真正的终止进程,而是用来检查进程是否存在或是否具有发送信号的权限
。
如果指定的进程存在并且当前用户有发送信号的权限,则kill命令返回0,否则返回1。
常见用法如下:
kill -0
例如,以下命令会检查进程ID为1234的进程是否存在:
kill -0 1234
如果不反回数值,输入echo $?看是否返回0
如果进程存在,则命令会返回0,否则返回1。这种用法可以在shell脚本中用来检查进程是否正在运行,从而进行相应的处理。
需要注意的是,-0选项不会发送任何信号,不会影响进程的运行状态。只是用来检查进程是否存在,以及当前用户是否有发送信号的权限。
killall命令可以用来根据进程名杀掉所有对应的进程。与kill命令不同,killall命令使用进程名作为参数,而不是进程ID
。如果有多个进程名匹配,killall会杀掉所有匹配的进程。
常见用法如下:
killall <进程名>
例如,以下命令会杀掉所有名为vim的进程
killall vim
killall命令默认使用SIGTERM信号终止进程,可以通过-s选项来指定要使用的信号。同时,要小心使用killall命令,以免误杀重要进程。建议在使用killall命令前先通过ps命令或top命令等查看进程状态,避免误杀重要进程
pkill命令,用于根据进程名或者其他属性杀掉进程。与killall命令不同,pkill命令不需要指定完整的进程名,可以根据进程名的一部分或其他属性来匹配进程并杀掉
。
常见用法如下:
pkill [选项] <进程名>
例如,以下命令会杀掉所有名字中包含vim的进程:
pkill vim
常用选项:
-f:匹配进程名及其参数,相当于grep选项。
-u :指定某个用户的所有进程。
-s :指定终止进程的信号,默认为15(SIGTERM)。
需要注意的是,pkill命令与killall命令一样,也会杀掉所有匹配的进程,因此要小心使用,避免误杀重要进程。建议在使用pkill命令前先通过ps命令或top命令等查看进程状态,避免误杀重要进程。
pkill命令的-t选项用于指定终止某个终端下的所有进程。可以通过-t选项指定终端的ID或者终端名称来匹配进程并终止。
常见用法如下:
pkill -t <终端ID或名称>
例如,以下命令会终止终端ID为pts/2的所有进程:
[root@localhost ~]# who
root pts/0 2023-04-04 23:44 (gateway)
root pts/1 2023-04-04 23:44 (gateway)
root pts/2 2023-04-05 03:18 (gateway)
root pts/3 2023-04-05 03:18 (gateway
[root@localhost ~]# pkill -t pts/2
使用-t选项会终止指定终端下的所有进程,包括当前用户以及其他用户的进程。因此,要小心使用,避免误杀重要进程。建议在使用pkill命令终止终端下的进程前先通过who命令或者w命令查看当前终端的用户信息,避免误杀其他用户的进程。
nohup命令是一个非常实用的命令,可以在后台运行命令,即使关闭终端或退出登录也不会中断该命令的执行。
语法
nohup [Arg ....] Command [>FileName][&]
Command:要执行的命令
Arg:命令的选项
>FileName:将输出重定向到文件
&:将命令放到后台运行
选项 | 解释 |
---|---|
-n | 不让nohup命令将输出的日志信息保存到nohup.out文件中 |
-p | 指定nohup命令运行的进程号 |
-s | 指定nohup命令运行时的信号 |
在后台运行一个ping命令
[root@localhost ~]# nohup ping 192.168.100.1 &
[1] 88139
[root@localhost ~]# nohup: 忽略输入并把输出追加到"nohup.out"
在后台运行一个目录,并将输出重定向到指定文件
[root@localhost ~]# nohup yes 2 > output.log &
[3] 104383
[root@localhost ~]# nohup: 忽略输入重定向错误到标准输出端
查看nohup目录输出的日志文件
taill -f nohup.out
# tail -f 命令可用于监视另一个进程正在写入的文件的增长
将ping目录放到后台运行,并将输出结果和错误信息都重定向到ping.log文件中
标准错误输出 2
标注输出 1
nohup ping 192.168.100.1 > ping.log 2>&1 &
# 2>表示将标准错误输出重定向到文件。而&1则表示将输出重定向到标准输出(即重定向到文件时,将标准错误输出和标准输出输出到同一个文件中)
把命令放在后台运行,且无论是正确的输出或是错误的输出,都直接扔进黑洞,直接销毁
# 此处有三种方式,可以忽略,标准输出1,标准输出2
nohup ping 192.168.100.1 > /dev/null 2>&1 & # 第一种将程序执行正确/错误的输出结果,都写入到黑洞文件中
nohup ping 192.168.100.1 1>/dev/null 2>/dev/null 同上
nohup ping 192.168.100.1 &>/dev/null 等同于上
# /dev/null是一个特殊的文件,也称为“黑洞”,它可以将所有写入它的数据都直接丢弃,从而实现一种类似垃圾桶的功能。
bg命令用于将一个在后台挂起的作业转为在后台运行。
语法
bg [job_spec]
job_spec:作业的标识符,可以是作业号或者进程号(
如果没有
指定作业标识符,则bg命令将转换最近挂起的前台作业为后台作业)
使用bg命令时,需要注意以下几点:
[root@localhost ~]# ping 192.168.100.1 # 执行完命令按Ctrl + Z将其挂起
PING 192.168.100.1 (192.168.100.1) 56(84) bytes of data.
64 bytes from 192.168.100.1: icmp_seq=1 ttl=128 time=0.265 ms
64 bytes from 192.168.100.1: icmp_seq=2 ttl=128 time=0.294 ms
64 bytes from 192.168.100.1: icmp_seq=3 ttl=128 time=0.261 ms
^Z
[3]+ 已停止 ping 192.168.100.1
然后使用bg命令将其放到后台运行
输入bg
[1]+ ping 192.168.100.1 &
[root@localhost ~]# 64 bytes from 192.168.100.1: icmp_seq=42 ttl=128 time=0.326 ms
6
......
...
此时,可以使用jobs命令查看当前所有作业的状态,可以看到ping命令以及在后台运行了
[1]+ 运行中 ping 192.168.100.1 &
.....
....
.
fg命令主要用于将一个在后台运行的进程切换到前台运行
语法
fg [job_id]
job_id:是指切换到前台运行的进程的作业号(如果没有指定作业号,则默认将当前作业(即最近一个被停止或放到后台的作业)切换到前台运行。)
使用fg命令时,需要注意以下几点:
将一个在后台运行的进程切换到前台运行
假设当前有一个正在后台运行的进程,作业号为1,可以使用fg命令将其切换到前台运行:
输入 bg
[1]+ ping 192.168.100.1 &
输入 fg 1
ping 192.168.100.1
此时,进程已经切换到前台运行,可以在终端中看到进程的输出结果。