一.进程
1.什么是进程
1.进程 ID ( Process ID , PID )号码被用来标记各个进程2.UID 、 GID 语境决定对文件系统的存取和访问权限 通常从执行进程的用户来继承3. 存在生命周期4.都由其父进程创建
进程创建
init :第一个进程,从 CentOS7 以后为 systemd进程:都由其父进程创建, fork() ,父子关系,CoW : Copy On Write 写实更新,有数据写入子进程需要新的内存空间
2.进程的特征
动态性:进程是程序的一次执行过程,是临时的,有生命期的,是动态产生,动态消亡的;并发性:任何进程都可以同其他进程一起并发执行;独立性:进程是系统进行资源分配和调度的一个独立单位; 硬件资源分配的最小单位结构性:进程由程序(代码)、数据(需要调用的文件)和进程控制块(开发)三部分成。
3.进程--线程--协程
1.进程
进程是一个具有一定独立功能的程序在一个数据集上的一次动态执行的过程,是操作系统进行资源分配和调度的一个独立单位,是应用程序运行的载体。进程是一种抽象的概念,从来没有统一的标准定义。进程的组成进程一般由程序、数据集合和进程控制块三部分组成。程序用于描述进程要完成的功能,是控制进程执行的指令集;数据集合是程序在执行时所需要的数据和工作区;程序控制块 (Program Control Block ,简称 PCB) ,包含进程的描述信息和控制信息,是进程存在的唯一标志。进程具有的特征:动态性:进程是程序的一次执行过程,是临时的,有生命期的,是动态产生,动态消亡的;并发性:任何进程都可以同其他进程一起并发执行;独立性:进程是系统进行资源分配和调度的一个独立单位;结构性:进程由程序、数据和进程控制块三部分组成。
2.线程
在早期的操作系统中并没有线程的概念,进程是能拥有资源和独立运行的最小单位,也是程序执行的最小单 位。任务调度采用的是时间片轮转的抢占式调度方式,而进程是任务调度的最小单位,每个进程有各自独立的 一块内存,使得各个进程之间内存地址相互隔离。 后来,随着计算机的发展,对 CPU 的要求越来越高,进程之间的切换开销较大,已经无法满足越来越复杂的程 序的要求了。于是就发明了线程。线程是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度和分派的基本单位。一 个进程可以有一个或多个线程,各个线程之间共享程序的内存空间 ( 也就是所在进程的内存空间 ) 。一个标准的 线程由线程 ID 、当前指令指针 (PC) 、寄存器和堆栈组成。而进程由内存空间 ( 代码、数据、进程空间、打开的 文件 ) 和一个或多个线程组成。
3.协程
协程,英文 Coroutines ,是一种基于线程之上,但又比线程更加轻量级的存在,这种由程序员自己写程序来 管理的轻量级线程叫做『用户空间线程』,具有对内核来说不可见的特性。因为是自主开辟的异步任务,所以很多人也更喜欢叫它们纤程( Fiber ),或者绿色线程( GreenThread )。正如一个进程可以拥有多个线程一样,一个线程也可以拥有多个协程。协程的目的在传统的 J2EE 系统中都是基于每个请求占用一个线程去完成完整的业务逻辑(包括事务)。所以系统的吞吐能 力取决于每个线程的操作耗时。如果遇到很耗时的 I/O 行为,则整个系统的吞吐立刻下降,因为这个时候线程一直处于阻塞状态,如果线程很多的时候,会存在很多线程处于空闲状态(等待该线程执行完才能执行),造 成了资源应用不彻底。 最常见的例子就是 JDBC (它是同步阻塞的),这也是为什么很多人都说数据库是瓶颈的原因。这里的耗时其实 是让 CPU 一直在等待 I/O 返回,说白了线程根本没有利用 CPU 去做运算,而是处于空转状态。而另外过多的线 程,也会带来更多的 ContextSwitch 开销。 对于上述问题,现阶段行业里的比较流行的解决方案之一就是单线程加上异步回调。其代表派是 node.js 以及 Java 里的新秀 Vert.x 。 而协程的目的就是当出现长时间的 I/O 操作时,通过让出目前的协程调度,执行下一个任务的方式,来消除 ContextSwitch 上的开销。协程的特点线程的切换由操作系统负责调度,协程由用户自己进行调度,因此减少了上下文切换,提高了效率。 线程的默认 Stack 大小是 1M ,而协程更轻量,接近 1K 。因此可以在相同的内存中开启更多的协程。 由于在同一个线程上,因此可以避免竞争关系而使用锁。 适用于被阻塞的,且需要大量并发的场景。但不适用于大量计算的多线程,遇到此种情况,更好实用线程去解 决。协程的原理当出现 IO 阻塞的时候,由协程的调度器进行调度,通过将数据流立刻 yield 掉(主动让出),并且记录当前栈 上的数据,阻塞完后立刻再通过线程恢复栈,并把阻塞的结果放到这个线程上去跑,这样看上去好像跟写同步 代码没有任何差别,这整个流程可以称为 coroutine ,而跑在由 coroutine 负责调度的线程称为 Fiber 。比 如 Golang 里的 go 关键字其实就是负责开启一个 Fiber ,让 func 逻辑跑在上面。 由于协程的暂停完全由程序控制,发生在用户态上;而线程的阻塞状态是由操作系统内核来进行切换,发生在 内核态上。 因此,协程的开销远远小于线程的开销,也就没有了 ContextSwitch 上的开销。
4.进程和线程的区别
1.线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位;2.一个进程由一个或多个线程组成,线程是一个进程中代码的不同执行路线;3.进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间 ( 包括代码段、数据集、堆等 ) 及一些进4.程级的资源 ( 如打开文件和信号 ) ,某进程内的线程在其它进程不可见;5.调度和切换:线程上下文切换比进程上下文切换要快得多。
查看进程中的线程
[root@jay ~]# grep -i threads /proc/进程号/status
二.进程管理相关命令
系统中可以识别的信号较多,我们可以使用命令"kill -l"或"man 7 signal"来查询
信号代号 | 信号名称 | 说明 |
1 | SIGHUP | 该信号让进程立即关闭.然后重新读取配置文件之后重启 |
2 | SIGINT | 程序中止信号,用于中止前台进程。相当于输出 Ctrl+C 快捷键 |
3 | SIGQUIT | 退出 |
8 | SIGFPE | 在发生致命的算术运算错误时发出。不仅包括浮点运算错误,还包括溢出及除数为 0 等其他所有的算术运算错误 |
9 | SIGKILL | 用来立即结束程序的运行。本信号不能被阻塞、处理和忽略。一般用于强制中止进程 |
14 | SIGALRM | 时钟定时信号,计算的是实际的时间或时钟时间。alarm 函数使用该信号 |
15 | SIGTERM | 正常结束进程的信号,kill 命令的默认信号。如果进程已经发生了问题,那么这 个信号是无法正常中止进程的,这时我们才会尝试 SIGKILL 信号,也就是信号 9 |
18 | SIGCONT | 该信号可以让暂停的进程恢复执行。本信号不能被阻断 |
19 | SIGSTOP | 该信号可以暂停前台进程,相当于输入 Ctrl+Z 快捷键。本信号不能被阻断 |
1、查看进程信息:PS命令
1.1.ps aux
[root@jay ~]# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.6 128164 6824 ? Ss 09:19 0:02 /usr/lib/systemd/systemd --switched-root --system --deserialize 21
root 2 0.0 0.0 0 0 ? S 09:19 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? S 09:19 0:00 [ksoftirqd/0]
root 5 0.0 0.0 0 0 ? S< 09:19 0:00 [kworker/0:0H]
root 7 0.0 0.0 0 0 ? S 09:19 0:00 [migration/0]
root 8 0.0 0.0 0 0 ? S 09:19 0:00 [rcu_bh]
各列的解释
USER∶进程的用户PID∶进程的ID%
CPU∶进程占用的
CPU 百分比%
MEM∶占用内存的百分比
VSZ∶该进程使用的虚拟内存量(KB)
RSS∶该进程占用的物理内存量(KB)
TTY∶启动进程的终端名。不是从终端启动的进程则显示为 ?
STAT∶该进程的状态(D∶不可中断的休眠状态;R∶正在运行状态;s∶处于休眠状态,可被唤醒;T∶停止状态,可能是在后台暂停或进程处于跟踪调试状态;z∶僵尸进程,进程已经中止,但是部分程序还在内存当中)
START∶该进程被触发启动时间TIME∶该进程实际使用CPU运行的时间
COMMAND∶进程的启动命令
僵尸进程
一个进程结束了,但是如果该进程的父进程已经先结束了,那么该进程就不会变成僵尸进程,因为每个进程结束的时候,系统都会扫描当前系统中所运行的所有进程,看有没有哪个进程是刚刚结束的这个进程的子进程,如果是的话,就由Init来接管它,成为它的父进程,子进程退出后init会回收其占用的相关资源。但是当子进程比父进程先结束,而父进程又没有回收子进程,释放子进程占用的资源,此时子进程将成为一个僵尸进程。
[root@jay ~]# bash
[root@jay ~]# echo $BASHPID
8103
[root@jay ~]# echo $PPID
6871
[root@jay ~]# kill -19 6871
[root@jay ~]# kill -9 8103
查看结果
[root@jay ~]# ps aux|grep "bash"
root 792 0.0 0.0 115256 932 ? S 09:19 0:00 /bin/bash /usr/sbin/ksmtuned
root 6871 0.0 0.3 116704 3660 pts/0 Ts 15:20 0:00 -bash
root 8103 0.0 0.0 0 0 pts/0 Z+ 16:49 0:00 [bash] <defunct>
1.2.ps -elf:
显示系统中的所有进程的详细信息
[root@jay ~]# ps -elf
F S UID PID PPID C PRI NI ADDR SZ WCHAN STIME TTY TIME CMD
4 S root 1 0 0 80 0 - 32041 ep_pol 09:19 ? 00:00:03 /usr/lib/systemd/systemd --switched-root --system --des
1 S root 2 0 0 80 0 - 0 kthrea 09:19 ? 00:00:00 [kthreadd]
1 S root 3 2 0 80 0 - 0 smpboo 09:19 ? 00:00:00 [ksoftirqd/0]
1 S root 5 2 0 60 -20 - 0 worker 09:19 ? 00:00:00 [kworker/0:0H]
1 S root 7 2 0 -40 - - 0 smpboo 09:19 ? 00:00:00 [migration/0]
1 S root 8 2 0 80 0 - 0 rcu_gp 09:19 ? 00:00:00 [rcu_bh]
1 R root 9 2 0 80 0 - 0 - 09:19 ? 00:00:00 [rcu_sched]
各列的解释
F∶内核分配给进程的系统标记(常见的标志有两个: 1:进程可以被复制,但是不能被执行;4:进程使用超级用户权限)
S∶进程的状态
UID∶启动这些进程的用户ID
PID∶进程的ID
PPID∶父进程的ID(如果该进程是由另一个进程启动的)
C∶ 进程生命周期中的CPU利用率
PRI∶进程的优先级 (数值越小,该进程的优先级越高,越早被 CPU 执行;系统定义不可以人为修改)
NI∶ 进程的优先级,数值越小,该进程越早被执行;可以人为修改 修改 NI 的值就可以改变进程的优先级。NI 值越小,进程的 PRI 就会降低,该进程就越优先被 CPU 处理;反之,NI 值越大,进程的 PRI 值就会増加,该进程就越靠后被 CPU 处理。 修改 NI 值时有几个注意事项:
NI 范围是 -20~19。普通用户调整 NI 值的范围是 0~19,而且只能调整自己的进程。普通用户只能调高 NI 值,而不能降低。如原本 NI 值为 0,则只能调整为大于 0。只有 root 用户才能设定进程 NI 值为负值,而且可以调整任何用户的进程。
ADDR∶进程的内存地址
Sz∶该进程占用多大内存
WCHAN∶该进程是否运行。"-"代表正在运行
STIME∶ 进程启动时的系统时间 TTY∶ 进程启动时的终端设备
TIME∶ 该进程占用 CPU 的运算时间,注意不是系统时间
CMD∶ 进程的启动命令
1.3.prtstat :
查看进程信息
[root@jay ~]# prtstat 8506
Process: kworker/0:0 State: S (sleeping)
CPU#: 0 TTY: 0:0 Threads: 1
Process, Group and Session IDs
Process ID: 8506 Parent ID: 2
Group ID: 0 Session ID: 0
T Group ID: -1Page Faults
This Process (minor major): 0 0
Child Processes (minor major): 0 0
CPU Times
This Process (user system guest blkio): 0.00 1.42 0.00 0.10
Child processes (user system guest): 0.00 0.00 0.00
Memory
Vsize: 0 B
RSS: 0 B RSS Limit: 18446744073709 MB
Code Start: 0 Code Stop: 0
Stack Start: 0
Stack Pointer (ESP): 0 Inst Pointer (EIP): 0
Scheduling
Policy: normal
Nice: 0 RT Priority: 0 (non RT)
2.查看进程信息:top命令
top 命令的输出内容是动态的,默认每隔 3 秒刷新一次。命令的输出主要分为两部分:
- 第一部分是前五行,显示的是整个系统的资源使用状况,我们就是通过这些输出来判断服务器的资源使用状态的;
- 第二部分从第六行开始,显示的是系统中进程的信息;
2.1.top常用选项
-d 秒数:指定 top 命令每隔几秒更新。默认是 3 秒;
-b:使用批处理模式输出。一般和"-n"选项合用,用于把 top 命令重定向到文件中;
-n 次数:指定 top 命令执行的次数。一般和"-"选项合用;
-p 进程PID:仅查看指定 ID 的进程;
-s:使 top 命令在安全模式中运行,避免在交互模式中出现错误;
-u 用户名:只监听某个用户的进程;
在 top 命令的显示窗口中,还可以使用如下按键,进行一下交互操作:
在 top 命令的显示窗口中,还可以使用如下按键,进行一下交互操作:
? 或 h:显示交互模式的帮助;p:按照 CPU 的使用率排序,默认就是此选项;
c:切换显示命令名称和完整命令行
M:按照内存的使用率排序;
N:按照 PID 排序;
T:按照 CPU 的累积运算时间排序,也就是按照 TIME+ 项排序;
k:按照 PID 给予某个进程一个信号。一般用于中止某个进程,信号 9 是强制中止的信号;
r:按照 PID 给某个进程重设优先级(Nice)值;
q:退出 top 命令;
数字1 键:显示CPU个数和状态
top -H∶显示所有线程
top -H -p ∶ 显示特定进程中的线程
2.2.格式:top( 动态的进程信息)
[root@jay ~]# top
top - 17:40:50 up 8:21, 2 users, load average: 0.00, 0.01, 0.05
Tasks: 143 total, 1 running, 142 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.3 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 999696 total, 248928 free, 347704 used, 403064 buff/cache
KiB Swap: 5119996 total, 5119996 free, 0 used. 437012 avail Mem
第一行:任务队列信息
- 14:24:57—系统当前时间
- up 6:34—系统已运行时长
- 3 user —当前登录用户数
- load average:0.00,0.01, 0.0.5—系统负载,即单位时间内系统处理的任务数,后面三个数值分别为1分钟,5分钟,15分钟提前到现在的平均值
第二行:进程信息
- Tasks—总进程数
- running—正在运行的进数
- sleeping—休眠的进程数
- stopped—中止的进程数
- zombie—僵死的进程数,如果不是 0,则需要手工检查僵尸进程
第三行:CPU的信息
- us—用户占用
- sy—系统模式占用
- ni—优先级调度占用
- id—空闲CPU,要了解空闲的 CPU 百分比,主要看%id 部分
- wa—I/O 等待占用
- hi—硬件中断占用
- si—软件中断占用
- st—虚拟化占用
第四行:内存的信息
total—总内存空间
free—空闲内存
used—己用内存
buff/cache—物理内存和交换内存的缓冲区总和(读写缓存)
缓冲(buffer)和缓存(cache)的区别:
缓存(cache)是在读取硬盘中的数据时,把最常用的数据保存在内存的缓存区中,再次读取该数据时,就不去硬盘中读取了,而在缓存中读取。
缓冲(buffer)是在向硬盘写入数据时,先把数据放入缓冲区,然后再一起向硬盘写入,把分散的写操作集中进行,减少磁盘碎片和硬盘的反复寻道,从而提高系统性能。
简单来说,缓存(cache)是用来加速数据从硬盘中"读取"的,而缓冲(buffer)是用来加速数据"写入"硬盘的。
第五行:交换分区的信息
- total—总交换空间
- free—空闲交换空间
- used—已用交换空间
- avail Mem—可用物理空间
2.3.进程信息区各列解释
PID:进程IDUSER:进程所有者的用户名
PR:优先级,数值越小优先级越高Nl:谦让度值。 负值表示高优先级, 正值表示低优先级
VIRT:进程使用的虚拟内存总量,单位kb
RES:进程使用的物理内存大小,单位kb
SHR:共享内存大小,单位kb S进程状态
%CPU:上次更新到现在的CPU时间占用百分比
%MEM :进程使用的物理内存百分比
TIME+:进程使用的CPU时间总计,单位1/100秒
COMMAND:命令名/命令行
3、查看指定的进程信息:pgrep命令
3.1.常用选项
-U:指定用户
-l: 显示进程名
-a: 显示完整格式的进程名
-P pid: 显示指定进程的子进程
pidof nginx
4、查看进程树:pstree命令
格式:pstree -aup
常用选项:
-a 显示启动每个进程对应的完整指令,包括启动进程的路径、参数等
-p 显示PID
-T 不显示线程thread,默认显示线程
-u 显示用户切换
-H pid 高亮显示指定进程及其前辈进程
pstree -ap 用户名 只查看属于指定用户的进程树结构
5、查看系统中已经被打开的文件列表:lsof
格式:lsof [选项]
选项 | 功能 |
---|---|
-c 字符串 | 只列出以字符串开头的进程打开的文件 |
+d 目录名 | 列出某个目录中所有被进程调用的文件 |
-u 用户名 | 只列出某个用户的进程打开的文件 |
-p pid | 列出某个 PID 进程打开的文件 |
6、内存:free
free -h #查看内存使用情况
free -m #以m为单位查看内存使用情况
echo 3 > /proc/sys/vm/drop_caches #清除缓存
pmap 1073 #查看进程占用内存的详细信息
7、iostat
iostat 可以提供更丰富的IO性能状态数据
常用选项:
-c 只显示CPU行
-d 显示设备〈磁盘)使用状态
-k 以千字节为为单位显示输出
-t 在输出中包括时间戳
-x 在输出中包括扩展的磁盘指标
123456
8、其他相关命令
iotop #监视磁盘I/Oiftop -ni ens33 #网络流量
uptime #系统运行了多久时间
mpstat #显示CPU相关统计
dstat #系统资源统计
————————————————
三、进程控制
1、进程的启动方式
1.1 手动启动
-
前台启动:用户输入命令,直接执行程序
-
后台启动:在命令行尾加入“&”符号,输出信息中包括后台任务序号、PID号
1.2 调度启动
-
使用at命令,设置一次性计划任务
-
使用crontab命令,设置周期性计划任务
1.3 进程的前后台调度
-
“命令后跟&”,把命令放入后台执行
-
Ctrl+Z组合键:将当前的进程挂起,即调入后台并停止执行
查看后台任务列表 jobs
jobs -l :查看处于后台的任务列表
调出后台任务 fg
将后台的进程恢复到前台运行,可指定任务序号,不指定任务序号表示所有后台任务全部恢复至前
-
并行执行任务,命令之间用“&”连接
如:ping 127.0.0.1&ping 127.0.0.2&ping 127.0.0.3&
2.终止进程的运行
2.1 Ctrl+C组合键
中断正在执行的命令
2.2 kill、killall命令
killall [选项] [信号] 进程名
killall -i sshd #交互杀死 sshd
kill用于终于指定PID号的进程
killall用于终止指定名称相关的所有进程
-9选项用于强制终止
2.3 pkill命令
根据特定条件终止相应的进程
pkill [信号] 进程名
-U:根据进程所属的用户名终止相应进程
-t:根据进程所在的终端终止相应程序
四、at命令设置计划任务
1、at命令:一次性计划任务
2、一次性任务创建步骤
第一步:at [HH:MM] [yyyy-mm-dd] 不携带日期表示为当天
第二步:输入指定命令
第三步:Ctrl+D提交任务
3、atq命令
- 查看未执行的任务列表
4、atrm命令
-
删除指定未执行任务
-
格式:atrm 任务序号
五、crontab计划任务配置
1、crontab命令
1.1 按照预先设置的时间周期(分钟、小时、日、月、周)重复执行用户指定的命令操作
1.2 属于周期性计划任务
1.3 主要设置文件
-
全局配置文件,位于文件:/etc/crontab
-
系统默认的设置,位于目录:/etc/cron.*/
-
用户定义的设置,位于文件:/var/spool/cron/用户名
2、管理cronta计划任务
选项 | 功能 |
-u user | 用来设定某个用户的 crontab 服务,例如 “-u demo” 表示设备 demo 用户的 crontab 服务,此选项一般有 root 用户来运行 |
-e | 编辑某个用户的 crontab 文件内容。如果不指定用户,则表示编辑当前用户的 crontab 文件 |
-l | 显示某用户的 crontab 文件内容,如果不指定用户,则表示显示当前用户的 crontab 文件内容 |
-r | 从 /var/spool/cron 删除某用户的 crontab 文件,如果不指定用户,则默认删除当前用户的 crontab 文件 |
-i | 在删除用户的 crontab 文件时,给确认提示 |
2.1 编辑计划任务
crontab -e [-u 用户名] -u缺省时默认是针对当前用户
2.2 查看计划任务
crontab -l [-u 用户名]
2.3 删除计划任务
crontab -r [-u 用户名]
3、crontab任务配置的格式
3.1 格式:时间周期设置 任务内容设置
时间周期设置:分钟 小时 日期 月份 星期
任务内容设置:命令或者脚本文件
项目 | 含义 | 范围 |
第一个"*" | 一小时当中的第几分钟(minute) | 0~59 |
第二个"*" | 一天当中的第几小时(hour) | 0~23 |
第三个"*" | 一个月当中的第几天(day) | 1~31 |
第四个"*" | 一年当中的第几个月(month) | 1~12 |
第五个"*" | 一周当中的星期几(week | 0~7(0和7都代表星期日) |
3.2 时间数制的特殊表示方法
特殊符号 | 含义 |
*(星号) | 代表任何时间。比如第一个"*"就代表一小时种每分钟都执行一次的意思 |
,(逗号) | 代表不连续的时间。比如"0 8,12,16***命令"就代表在每天的 8 点 0 分、12 点 0 分、16 点 0 分都执行一次命令 |
-(中杠) | 代表连续的时间范围。比如"0 5 ** 1-6命令",代表在周一到周六的凌晨 5 点 0 分执行命令 |
/(正斜线) | 代表每隔多久执行一次。比如"/10***命令",代表每隔 10 分钟就执行一次命令 |
4、设置周期任务的方法
4.1 crontab -e编辑
30 1 * * * /usr/bin/cp -a /var/log/messages /root/log-$(date +%Y%m%d) 每天1点半将系统日志复制到root目录下并重命名为log加日期标注
常用日期表达命令
date +%F显示格式为YYYY-MM-DD
date +%Y%m%d显示格式为YYYYMMDD
4.2 echo重定向追加
echo ‘30 1 * * * /usr/bin/cp -a /var/log/messages /root/log-$(date +%Y%m%d)’ >> /var/spool/cron/root
4.3 vim /etc/crontab编辑
此方法需指定执行任务的用户,且无法通过crontab命令进行查看、编辑以及删除,如需操作需进入/etc/crontab,编辑格式如下:
30 1 * * * root /usr/bin/cp -a /var/log/messages /root/log-$(date +%Y%m%d)