Skip to content

Latest commit

 

History

History
532 lines (313 loc) · 22.5 KB

2.11_20170327_进程和作业管理.md

File metadata and controls

532 lines (313 loc) · 22.5 KB

进程和作业管理

内核有进程管理、文件系统、网络功能、内存管理、驱动程序、安全功能等功能。模式切换(context switch)指的是在用户模式和内核模式之间切换。

推荐阅读:《linux内核设计与实现》 《深入理解linux内核》

进程相关知识背景

进程的概念和进程标识符

进程(Process)是计算机程序运行的实例,每一个进程都是由父进程派生的,每个进程都有一个PID来标识,由内核进行分配,进程号的范围是2-32768,进程号可以重用,当一个进程终止后,其进程 ID 就可以再次使用了。大多数 UNIX 系统实现延迟重用算法,使得赋予新建进程的 ID 不同于最近终止进程所使用的 ID。当进程号用尽时,会从2开始新一轮循环。

linux系统启动时,第一个运行的进程是init,进程号为1,系统启动后产生的所有进程都由 init 进程衍生而来,是所有进程的父进程。当子进程终止时,它与父进程会保持关联,直到父进程正常结束,如果父进程异常终止,子进程会将init作为父进程,init发现僵尸进程时会将其释放。

每个进程除了有 PID 还会有 PPID,也就是父进程 ID,通过 PPID 可以找到父进程的信息。系统启动后所有的进程都由 init 进程衍生而来。因为所有进程都来自于一个进程,所以 Linux 的进程模型也叫做进程树。使用 pstree 命令可以查看系统当前的进程树

进程的调度

在同一个时刻,一个 CPU 核心上只能运行一个进程,CPU 在某一个时刻运行哪个进程需要依靠操作系统内核来进行调度。操作系统为每个进程分配一个优先级,系统内核根据优先级来调度进程运行。

进程的优先级

Linux 中共有 0~139 种优先级,其中 1-99 被称为实时优先级,数字越大优先级越高。100-139 被称为动态优先级,数字越小,优先级越高,内核可以调整进程的动态优先级,还可以使用 nicerenice 指令调整进程的动态优先级,nice的值为-20-19

Linux 系统使用了抢占式的进程调度。这意味着,当一个进程进入 TASK_RUNNING 状态(即准备运行状态)时,内核检查次进程的优先级,并与当前正在运行的进程的优先级进行比较,如果次进程的优先级更大,当前运行的进程被中断,又调度器重新挑选一个进程运行。

调度策略

Linux 系统对每种优先级都维护一个运行队列和过期队列,系统每次从优先级最高的运行队列中挑选进行运行,然后放入其过期队列中。当运行队列中的进程全部进入过期队列后,再将过期队列和运行队列对调。

进程的内存空间

在一个多任务操作系统当中,可能存在着上千个进程,而物理内存只有一个,为了防止进程访问原本不属于本进程的内存空间,现代操作系统都会使用「内存保护」技术。

每一个进程都运行在它自己的内存沙箱(sandbox)中,这个沙箱被称作「虚拟地址空间」(virtual address space),在 32 位的系统中,它是一个 4GB 大小的内存地址空间,虚拟内存是线性可编址的,其使用单位是页(page),对应的物理内存被称为页框(page frame)。这些虚拟的地址通过页表(page table)映射至真实的物理内存,页表由操作系统内核和处理器(内存管理单元)负责管理。每个进程都有它自己的页表。这里需要注意,所有的进程都运行在「虚拟内存」中,即使是内核本身也一样。因此虚拟地址空间中的一部分是专门供内核使用的。

进程的状态

系统中可能存在大量进程,而 CPU 的数量是有限的,因此进程并不一定处于运行状态。在 Linux 系统中,进程有下面这些状态:

Executing/Running: 进程正在 CPU 上运行。

Ready: 进程处于准备运行状态,它被放置在一个运行队列中,等待系统分配 CPU 资源给它。

Stopped: 进程被停止,通常是通过接收一个信号,正在被调试的进程可能处于停止状态。暂停于内存中,但不会被调度,除非手动启动

Uninterruptible: 不可中断睡眠,处于这个状态的进程通常需要等待某个资源,而且在等待过程中进程会忽略任何信号。被磁盘设备 I/O 所阻塞的进程可能处于这个状态。

Interrruptible: 可中断睡眠状态,进程需要等待某个特定的条件为真,才会继续运行,可中断睡眠状态的进程可以被信号唤醒。

Zombie: 子进程已经结束,而父进程没有调用 wait() 或者 waitpid() 系统调用获取子进程的终止状态,导致进程的进程描述符没有被回收。

进程的描述符

为了管理进程,内核需要追踪每个进程的运行状态,例如进程的优先级,PID,进程的地址空间等信息。内核使用一个 task_struct 类型的结构体来保存进程信息,它被称为进程描述符,对于每个进程,内核都为其创建一个进程描述符,内核使用双向链表的结构来存储这些进程描述符。多个任务的task struct组成的链表叫做task list。

进程的产生方式

进程不是凭空创建的,每个进程都是由其父进程衍生而来,在 Linux 系统中,父进程通常使用 fork()vfork()clone() 等系统调用来生成子进程。

fork 创建的进程成被称为「子进程」(child process)。例如,在 shell 中执行一个命令时,shell 进程就会调用 fork() 产生一个子进程,然后子进程调用 exec() 执行命令程序,进程结束后返回控制至父进程 shell 进程。

写时复制

在 Linux 系统中,进程使用 fork() 产生的子进程时,并没有立即为子进程分配物理页框。Linux 系统使用了写时复制(Copy On Write, COW)技术。这意味着子进程被创建时,与其父进程共享相同的物理页框(page frame),子进程实际使用的是其父进程的堆栈空间,内核将这些共享区域标记为只读。当父、子进程中的任一个试图修改这些区域时,内核会为修改区域的那块内存制作一个副本,并标记为可写,对于原来的共享内存页框,内核会检查是否此页框只被一个进程所使用,如果只被一个进程使用,那么此页框也为可写。这样做的原因是子进程的生命周期可能很短,使用「写时复制」技术可以按需为进程分配内存,使得内存的分配更加高效。

僵尸进程(Zombie)

当一个进程完成它的工作终止之后,它的父进程需要调用 wait() 或者waitpid() 系统调用取得子进程的终止状态。

一个进程使用 fork 创建子进程,如果子进程退出,而父进程并没有调用 wait 或 waitpid 获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中而未被释放。 这种进程称之为僵死进程。

孤儿进程(Orphan Process)

如果父进程产生子进程后终止了,且子进程继续运行,子进程被称为孤儿进程,孤儿进程由 init 进程收养,它的 PPID 变为 1。

进程的类型

守护进程(daemon):是一种后台服务进程,它们通常不与终端关联,用户空间守护进程的父进程是 init 进程。Linux 中的很多服务都以守护进程模式运行,它们不会随着终端的退出和登录而改变进程状态。

用户进程/前台进程:和终端相关,通过终端启动的进程,也可以在前台启动的进程,以守护模式运行

根据cpu和io来区分进程类型又可分为 cpu-bound(cpu密集型)和io-bound(io密集型)

linux进程查看及管理工具

pstree

pstree可以查看系统当前的进程树,pstree命令在psmisc软件包中,包中还有fuser、killall、和pstree.x11命令。pstree.x11命令和pstree功能一样,只不过pstree.x11退出需确认。

ps

ps(process status)进程状态快照查看,单独使用ps会显示当前用户在当前终端所运行的进程。

回顾:终端

Linux中默认提供了六个命令行终端和一个图形终端:tty1tty7。其中tty1tty6是命令行终端(就是全屏,黑底白字的控制台),tty7是图形终端(也就是平时我们启动桌面版时默认登录的图形用户界面,也是全屏的)。可以通过Ctrl+Alt+F1~F7切换这7个终端。除了这7个基本的“大环境”终端,我们还可以在tty7中开很多不是全屏的终端,也就是我们平时用来输入命令行的图形终端(ctrl + shift + T快捷键),这些终端的名字是以pts开头的。pts是pseudo terminal slave的缩写,表示“伪终端从属”。如果我新开一个图形终端,那么显示名称为pts/0,如果再开一个图形终端,那么它的名字就是pts/1,依次类推。

/proc目录下有大量数字目录,每一个数字都代表一个进程号,每个数字目录下的文件都是进程的状态信息,在数字目录下有一个文件是cmdline可以查看此进程是由哪个命令启动的。

ps支持两种风格的选项格式,一种是Unix风格,另外一种是BSD风格

ps的常用选项

eu/axu:以用户为中心显示所有进程。中括号表示的是内核线程
	a:与终端相关的进程
	x:与终端无关的进程
	e:显示所有进程
	u:以用户为中心组织进程状态信息显示
-ef:以完整格式显示所有进程
	-f:显示完整格式的程序信息
-eFH:以层级格式显示进程相关信息,类似的还有-ejH
	-F:显示更完整格式的进程信息
	-H:以层级格式显示
	-j:任务格式,实际也是显示不同的字段
-eo\axo [指定要显示的字段]:显示自定义字段的进程列表,eg.ps -eo pid,psr,command
	-o:自定义先是字段
	常用的字段有:ni(nice值);pri(优先级);psr(processor CPU);rtptrio(实时优先级);ppid(父进程)等
-u USERNAME:列出此用户运行的进程。此处比运行ps多了许多进程,因为这些进程不运行在此前的终端中

ps axu各字段的含义

USER PID VSZ/VIRT RSS/RES STAT START TIME
进程属主 进程号 virtual memory size虚拟内存集 resident size常驻内存集 进程状态 启动时间 进程运行占用cpu的累计时间

STAT状态的含义

R:running,正在运行或在队列中的进程 S:interruptable sleeping,睡眠,通常是等待信号 D:uninterruptable sleeping,不可中断的睡眠,例如等待IO T:stopped Z:zombie

+:前台进程 l:多线程进程

N:低优先级进程 <:高优先级进程

s:session leader包含子进程

pgrep和pkill

pgrep、pkill的一般使用格式pgrep|pkill [options] pattern。例如pgrep -u root -l

-u uid:effective user
-U uid:real user
-t terminal:与指定终端相关的进程
-l:显示进程名,只对pgrep有效
-a:显示完整格式的进程名,只对pgrep有效
-P pid:显示其父进程为此处指定的进程的进程列表

pidof

pidof可以根据进程名获取其pid。一般用法pidof 进程名

top和htop、glances

ps命令是静态查看当前的系统的统计信息,无法动态刷新,top命令可以实时显示进程状态,默认每3秒刷新一次。top不会显示全部的进程,只显示排在前的一部分。

top命令默认以已占据的cpu百分比排序,也可以在top界面按M键以占据内存百分比排序,T键按累计占用排序,P键按占据的cpu百分比排序。

img

  • 首部uptime信息

    首部top信息显示了关于计算机的运行时间和平均负载等信息,这些信息也可以使用uptime来查看。uptime信息的显示和隐藏使用l键,不过只在CentOS 7中有效。

    load average是平均负载,表示一段时间内的平均活跃进程数,三个数字分别表示一分钟、五分钟、十五分钟负载。0.05就表示15分钟内平均有0.05个进程使用CPU,CPU有5%的时间是活跃的。

    单核cpu超过1即为过载,双核cpu超过2即为负载,依此类推。

    tload命令可以显示随时间变化的负载曲线。

  • 任务和task信息

    此行显示的是进程和cpu的统计信息,使用t可以显示和隐藏,cpu单独统计使用数字1键。

  • memory信息

    此行提示的内存和交换分区的统计,显示或隐藏使用m键。这一行信息也可以一用free -m来显示

退出top使用q键,修改刷新时间间隔使用s键然后指定刷新时间,终止指定进程用k键,以用户过滤显示使用u键。

常用选项

-d number:指定默认刷新频率
-b:以批次方式,-n NUM:显示多少批次

htop和top相似,但比top命令功能更多一些,界面也更直观一些,安装要使用Fedora-epel源。

在htop命令中常用的内建命令:

s:跟踪选定进程的系统调用,如果提示没有安装strace,则要安装strace,yum -y install strace

l:显示选定进程打开的文件列表

a:将选定的进程绑定至某指定cpu核心

t:显示进程树

-d NUM:指定刷新时间
-u UNAME:仅显示指定用户的进程

glances是一个跨平台的系统监控工具,基于python,支持cs架构,glances也有很多内建命令,使用h获取帮助。glances也需要epel源。

在glances中绿色表示OK,蓝色表示Careful,紫色表示Warning,红色表示Critical。

-b:以字节byte为单位显示网卡速率
-d:关闭磁盘io模块
-f /path/to/somewhere:输出文件位置及其格式
-o {HTML|CSV}:输出格式
-m:禁用mount模块
-n:禁用网络模块
-t num:延迟时间间隔
-l:每个cpu的相关数据单独显式

c/s模式的glances使用

服务模式:glances -s -B IPADDR(指明监听于本机的哪个地址)直接使用glances -s会使用默认的绑定地址0.0.0.0,这样会监听所有网络的指定接口。-B用于绑定地址,-p用于绑定监听端口

客户端模式:glances -c Server_ipaddr(要连入的服务器地址),-p用于指定服务器端口

需要注意的是glances的密码是明文传输的,最好不要使用默认端口,并且是在内部使用。

vmstat和dstat、pmap

vmstate查看虚拟内存状态,是比较早期的linux命令,一般使用格式vmstat [options][delay [count]] 。

vmstat各字段含义

procs

​ r:等待运行的进程的个数

​ b:处于阻塞状态(不可中断睡眠态)的进程个数

memory

​ swpd:交换内存的使用总量

​ free:空闲物理内存总量

​ buffer:用于buffer的内存总量

​ cache:用于cache的内存总量

swap

​ si:数据进入swap中的数据速率,单位是kb/s

​ so:数据离开swap的数据速率

io

​ bi:从块设备读入数据到系统的速率,单位是kb/s

​ bo:保存数据到块设备的速率

system

​ in:interrupts,中断速率

​ cs:context switch,进程切换速率

cpu

​ us: 用户空间占据cpu的比例

​ sy:内核空间占据cpu的比例

​ id:idle空闲比例

​ wa:等待io完成所消耗的时间比例

​ st:被偷走的时间比例

-s:显示统计数据

dstat是vmstat的替换工具, 统计系统资源并显示

-c:显示cpu的相关信息,dstat默认会显示cpu的相关信息
-C:单独指定某颗cpu的信息
-d:显示磁盘的读写速率,默认显示
-D:单独显示指定的某块硬盘
-g:显示page的相关信息
-i:显示中断的统计信息
-l:显示load的统计信息
-m:显示memory相关统计信息
-n:显示network相关统计信息
-p:显示进程统计数据
-r:显示io请求相关的统计数据
-s:显示swapped相关统计数据
--top-cpu:显示最占用cpu的进程
--top-io:显示最占用io的进程
--top-mem:显示最占用内存的进程
--top-lantency:显示延迟最大的进程
--ipc:进程间通信的相关统计数据

pmap报告进程的内存映射关系,一般使用格式pmap [options] pid。pmap实际上也是读取/proc/PID/maps文件

-x:显示详细格式的信息

kill和killall

kill通过向进程发送控制信号来对进程进行管理。显示当前系统的可用信号可以使用kill -l也可以使用man 7 signal。

例如kill PID1 PID2 PID3 ...,使用kill -9 PID强制结束进程

常用的信号:

  1. SIGHUP:无需关闭进程而让其重读其配置文件

  2. SIGINT:中止正在运行的进程;相当于ctrl+c

  3. SIGKILL:杀死正在运行的进程

  4. SIGTERM:终止正在运行的进程

  5. SIGCONT

  6. SIGSTOP

指定信号的方法:

信号的数字标识:1,2,9

信号的完整名称:SIGHUP

信号的简写名称:HUP

**向进程发信号:**kill [ -SIGNAL] PID

终止"名称"之下的所有进程:killall [ -SIGNAL ] Program

linux的作业控制

一个作业可能会包含一个或多个进程,主要是完成一个完整任务。

前台作业:通过终端启动,运行时一直占用终端

后台作业:可以通过终端启动,但启动后即转入后台运行(释放终端)

如何让作业运行于后台?

(1)运行中的作业:ctrl+z

(2)尚未启动的作业:COMMAND &

此类作业虽然被送到后台运行,但其依然与终端相关。如果希望送往后台后,剥离与终端的关系,要使用nohup COMMAND &

查看所有作业:jobs,作业号后的加号代表系统会默认操作此作业,减号的次之

作业控制:

fg [[%] JOB_NUM]:把指定的后台作业调回前台

bg [[%] JOB_NUM]:让送往后台的作业在后台继续运行

kill [%JOB_NUM]:终止指定作业

进程优先级调整-nice和renice

调整静态优先级100-139使用nice和renice。进程默认启动时的nice值为0,优先级为120

nice命令的一般使用格式:nice [option] [COMMAND [ARG]...]

renice可以对已经运行的进程进行调整nice值,一般使用格式:renice [-n] priority [-gpu] pid...,普通用户无法降低nice值

查看调整的效果:ps axo pid,comm,ni

linux任务计划、周期性任务执行

在未来的时间点执行一次任务:at、batch

周期性的运行某任务:cron

at命令

at命令的一般使用格式at [option] TIME,作业的执行结果以邮件通知相关用户

时间指定:

HH:MM[YYYY-mm-dd];noon|midnight|teatime;tomorrow;now+num{minutes,hours,days,weeks}

ctrl+d提交任务

at -l 列出等待运行的作业,也可以使用atq

at -d 作业号:删除作业

-q QUEUE:
-l:列出指定队列中等待运行的作业,相当于atq
-d:删除指定的作业,相当于atrm
-c:查看具体作业任务
-f /path/from/somefile:从指定的文件读取任务

linux的邮件服务:

smtp(简单邮件传输协议),用于传送邮件;

pop3(post office protocol)和imap4(Internet mail access protocol):用于接收邮件

mailx是一个简单的,纯命令行的MUA,在centos6是mail。一般使用格式mailx [ -s "subject"] username[@hostname]

邮件正文的生成:

--直接给出,ctrl+d结束输入

--输入重定向

--通过管道echo -e “how are you/nhow old are you” |mail

batch命令

让系统自行选择空闲时间去执行此处指定的任务

周期性任务计划:cron

在centos7中有3各相关程序包:cronie主程序包,提供了crond守护进程以及相关辅助工具;cronie-anacron是cronie的补充程序,用于监控cronie任务执行状况。如果cronie中的任务在过去该运行的时间点未能正常运行,则anacron会随后启动一次此任务;crontabs包含centos提供系统维护任务。

在centos7中使用systemctl status crond来查看crond守护进程是否运行,这也是后续一切工作正常运行的前提。在centos6中使用service crond status查看。

计划要周期性执行的任务提交给crond,由其来实现定时运行。有两种方法来提交周期性任务,对于系统cron任务(系统维护任务),使用/etc/crontab文件来实现;对于用户cron任务,使用crontab命令来实现。

运行结果以邮件通知给相关用户,如果不想接收邮件,可以使用COMMAND > /dev/null或COMMAND &> /dev/null

对cron任务来讲,%有特殊用途,使用需要转义,单引号内的%可以不用转义。

系统cron任务

作业的指定格式:

例如:每天晚上9:10分运行echo命令:10 21 * * * simon /bin/echo “HI” ,最好使用绝对路径

时间表示法:

(1)特定值

​ 给定时间点有效取值范围内的值

(2)*

​ 给定时间上有效取值范围内的所有值

(3)离散取值:,

​ #,#,#

(4)连续取值:-

​ #-#

(5)在指定时间范围内定义步长

​ /#:#即为步长

​ 每三小时运行echo命令:0 */3 * * * simon /bin/echo " How old are you!"

用户cron任务

每个用户都有专用的cron任务文件,在/var/spool/cron/USERNAME

用户使用crontab -e定义任务,使用contab -l列出自己定义的任务,使用contab -r移除所有任务

-i:交互式模式,同-r一起使用,可以有选择的移除指定的任务
-u USER:仅root可执行,代为为指定用户管理cron任务

思考:

如何实现秒级运行任务?* * * * * for min in 0 1 2;do echo "hi" ; sleep 20; done---每20秒运行一次

如何实现每7分钟运行一次任务?不能被整除不会精确运行,利用sleep命令

练习

1、每4小时备份一次/etc目录至/backup目录中,保存的文件名称格式为“etc-yyyy-mm-dd-HH.tar.xz”;

2、每周2, 4, 7备份/var/log/messages文件至/logs目录中,文件名形如“messages-yyyymmdd”;

3、每两小时取出当前系统/proc/meminfo文件中以S或M开头的信息追加至/tmp/meminfo.txt文件中;

4、工作日时间内,每小执行一次“ip addr show”命令;