进程:process, 过程(有开始有结束)
MMU: Memory Management Unit
内存保护机制
实现内存虚拟化:
CPU 32bit: 2^32=4GB 所以在32位架构上每一个程序都认为自己是有4G内存可以使用的。
这种叫做线性地址空间
物理地址空间:RAM+ROM
CPU 一加电就会读读ROM里面的程序使主机启动,如果没有ROM主机就无法启
MMU这种机制将内存地址一个一个的分成页框,能够存储固定大小单元的数据, 每个单元就成为页(Page)。
4G的内存,其中给了1G是给内核使用的,Kernel space 在内存空间的最高段。其他3G分给指令(text segment),数据(data segment),变量段(BSS segment),堆(heap),内存映射段(Memory mapping segment)栈(stack)。
程序是静态的,而进程是动态的。
进程树:pstree
进程:init(1) --> fork() -->
所以进程都来自init,除了init进程没有父进程,其他都有父进程。
init进程是由内核创建的。子进程由父进程创建,父进程由init进程创建。
进程间通信:IPC, Inter Process Communication
signal(信号), shm(共享内存), semerphor
进程分为两类:
CPU-Bound: CPU密集型进程(需要大量占用CPU的进程)
IO-Bound:IO密集型进程(需要大量占用IO的进程)
进程分为三类:
批处理进程(通常是CPU密集型进程如服务类进程或者守护进程)
实时进程(以实时为主要目的)
交互式进程
调度器:
进程优先级:
动态优先级:
惩罚措施:
静态优先级:用户类进程
100-139:数字越小,优先级越高;
nice值:-20, 19
100, 139
实时优先级:内核类线程
1-99:数字越大,优先级越高;
Linux 2.6: O(1)
进程切换:Context Switch, 上下文切换
内核模式,用户模式
内核空间,用户空间
ring0: 特权指令,敏感指令
ring3:普通指令 --> 系统调用
IO:
poll: 轮询, 忙等待;
interupt: 中断, 中断的上半部和下半部 (当某个信号到来的时候会中断通知CPU),一个中断会打打断一个进程的运行过程。
中断就一些不可预知的但是又必须处理的信号。
DMA:
进程的状态:
Ready:
Running:
5ms, 2ms,
Sleeping(当外部条件没能满足的时候被切换出去了)
Interruptable Sleeping (可中断睡眠,可以叫醒继续运行)
Uninterruptable Sleeping(非可中断睡眠,可能是因为外部的IO还没有准备好,所以叫不醒它)
Stopped: (停止状态,叫它也不会醒)
Zombie: 僵死态
COW: Copy On Write: 写时复制;
内存泄露:内存分出去的可用空间收不回来,导致没有可用空间使用了。
线程是进程的一个子单位,在linux中 线程只是被简化的进程
进程管理类的命令:
pstree, ps, top, vmstat, htop, pmap
pstree: 查看进程树;
ps: 显示系统向前进程状态的命令;process status
进程:
跟终端相关的进程
跟终端无关的进程
a: 所有跟终端相关的进程
x: 所有跟终端无关的进程
STAT:
S:可中断睡眠
D:不可中断睡眠
R:运行或可运行;
T:停止
Z:僵死
s: session leader
l: 多线程进程;
+: 前台进程;
N: 低优先级进程;
<: 高优先级进程;
u: 以用户为中心显示进程相关信息
%CPU: cputime/realtime
%MEM:
VSZ: Virtual memory SiZe线性地址大小
RSS: 常驻内存集;
PSR:表示运行在哪个cpu上
-ef:
-e: 显示所有进程;entire progress
-f: 完整格式列表;full format
-eFH
-F:显示额外信息;
-H: 显示进程层次关系;
-o 要显示的字段: 自定义显示格式
ps axo pid,command
pgrep pattern: process grep
例如:pgrep bash
选项:
-U USERNAME:显示相关用户的进程;
-G GROUPNAME:相关组的进程;
pidof: 找到某个程序的进程ID pidof:process pid of program.
top:是个交互式命令。默认是按cpu 来排序的
参数:
M: 按内存空间占用大小排序;
P:按CPU时间占用大小排序;
T:按累计时间排序;
k: 杀死一个进程;
m: 是否显示内存摘要信息;
t: 是否显示CPU和进程的统计信息;
l: 是否显示负载信息
q: 退出
显示信息:
us,sy,ni,id,wa,hi,si,st,
us:user 用户占用cpu百分比
sy:系统内核占用cpu百分比
ni:表示调整nice值占用cpu百分比
i:idle表示空闲cpu百分比
wa:wait表示等待IO 完成所占cpu百分比
hi:硬件中断所占cpu百分比
si:软件中断所占cpu百分比
st:被偷走时间所占cpu百分比
PID:进程号
USER:用户
PR:priority优先级RT:实时优先级 , 数子表示优先级
NI:nice值
VIRI:虚拟优先级
RES:实际优先级
SHR:share memory共享内存级
S:status 状态
TIME+:进程使用cpu时间的总计,单位是百分之一秒。
COMMAND:有哪个命令启动这个进程的
选项:
-d #: 刷新延迟;
-b : 批次显示;
-n #: 指定批次显示时显示的批数;
htop: 增强版top,比top更好用,系统没有的话需要安装,
ps、pstree、pidof、pgrep、top、htop
vmstat:virtual memory status
procs
r: 运行或等待CPU时间片的进程的个数;
b: 被阻塞(通常为等待IO完成)的进程队列的长度;b表示block
memory
swpd: 从物理内存交换至交换分区的数据量;
free: 未使用的物理内存空间;
buff: buffer cache的空间大小;通常是缓存写操作相关的数据;
cache: page cache的空间大小;通常是缓存读操作的相关数据;
swap:
si: swap in, 数据进入交换分区数据量,即从内存至交换分区中去;(kb/s)
so: swap out, 数据离开交换分区数据量,即从交换分区至内存;
io:
bi: block in,从块设备读入的数据量, (kb/s)
bo: block out,保存至块设备的数据量, (kb/s)
system:
in: interrupt,中断发生的速率,通常意为每秒多个次中断请求发生;
cs: context switch, 上下文切换的速率;
cpu:
us: 用户进程所占用CPU时间的百分比;
sy: 内核
id: CPU空闲百分比;
wa: CPU用于等待IO完成的时间百分比;
st: 被虚拟化占去的时间百分比;
sar -u
sar -P ALL 显示所有cpu相关信息
iostat -c : 也能显示CPU 相关信息的
dstat -c :指定显示cpu的信息
dstat -C 0,3
进程间通信:IPC :只要涉及到进程间交换数据都叫进程间通信。
共享内存,shm
信号:signal
引用信号的方式有三种:1
1)引用信号名称
2)引用信号ID号
3)引用信号名称简写,
信号:给别人发生简短的信息。以下信号需要记住:
1:SIGHUP, 让进程不用终止,而重读其配置文件;
2: SIGINT, 中断正在运行的进程, 相当于Ctrl+c;
9:SIGKILL, 杀死; 类似于秘密杀死
15: SIGTERM, 终止; 类似于人道杀死
19: SIGSTOP, 停止; 让进程停一会
18:SIGCONT:唤醒,可以把停止的进程再次唤醒继续运行。
向其它进程传递信号,使用kill
kill -信号 PID #根据PID 来杀死进程
kill -9 2031 = kill -SIGKILL 2031 #我们可以使用数字或者名称全名或者名称简称
killall -信号 进程名 #根据名称来杀死进程
killall -9 crond #杀死所有crond进程,这里必须使用进程名了不能使用进程ID
killall5 #向所有进程发生命令。
kill -l #查看支持的信号
调整进程nice值:
普通用户:调大数字,调低优先级;
-20, 19 #默认nice值为0,nice值越小优先级越高
100, 139 #默认优先级为120 ,数字越大优先级越低。
nice -n # COMMAND
renice # PID #把某个PID的进程的nice值重新调整为#
Linux作业控制:
前台:占用着终端;前台作业
后台:无须占用终端;
前台-->后台:Ctrl+z #但是作业此时为停止状态。
后台-->前台:fg %JOB_ID #
jobs 查看后台作业,我就是经常使用ctrl+z 来退出文本编辑,看来是不对的。只是把当前的作业送傲后台而已。
我们可以通过#fg %JOB_ID 来把后台进程调回前台。
bg [[%]JOB_ID]:让作业在后台运行;
启动时,让作业直接运行于后台,它是可以继续在后台运行的,只有把进程从前台送到后台时,进程状态为stoped 停止的。
# COMMAND & #通过在命令后面加上&可以把命令放在后台执行。
# nohup COMMAND & #退出终端也可以继续在后台执行, nohup 不需要终端
作业也可被终止:
kill [%JOB_ID] #结束作业,需要在kill命令后面加% 再加上作业id
axel -n 5 -o ./ http://a.b.c.d/abc.iso &
screen:#把当前终端分成多个屏幕,默认没装,这样就可以实现把某个需要长时间运行的任务放在screen中运行,这样即使关闭了当前终端,
任务也会在screen中继续运行, 当再次登录终端时可以通过screen -r 回到screen中。
screen #打开一个screen
screen -ls #查看所有屏幕
screen -r SCREEN_ID #回到某个screen
exit #终止screen
Linux终端:
控制台:/dev/console
物理终端:
虚拟终端:/dev/tty[1-6]
模拟终端: /dev/pts/#
串行终端: /dev/ttyS#
练习:
1、如何获取当前系统上下文切换的次数?sar、iostat或dstat是否可以?
/proc:内核映射,伪文件系统;
PID #每个进程启动的时候在/proc目录下面有一个以进程pid为名称的目录。这个目录里面存放着这个进程相关属性,
每个进程目录里面都有一个maps。它记录着当前进程所依赖的库文件在内存中的地址。
# cat /proc/PID/maps #查看进程运行的物理地址空间映射;
# pmap PID: #查看进程运行的物理地址空间映射;
多处理器:
mpstat
补充资料:关于mmap
系统调用mmap()可以将某文件映射至内存(进程空间),如此可以把对文件的操作转为对内存的操作,以此避免更多的lseek()与read()、write()操作,这点对于大文件或者频繁访问的文件而言尤其受益。
1、 Linux采用了投机取巧的分配策略,用到时,才分配物理内存。也就是说进程调用brk()或mmap()时,只是占用了虚拟地址空间,并没有真正占用物理内存。这也正是free –m中used并不意味着消耗的全都是物理内存。
2、 mmap()通过指定标志(flag) MAP_ANONYMOUS来表明该映射是匿名内存映射,此时可以忽略fd,可将它设置为-1。如果不支持MAP_ANONYMOUS标志的类unix系统,可以映射至特殊设备文件/dev/zero实现匿名内存映射。
3、 调用mmap()时就决定了映射大小,不能再增加。换句话说,映射不能改变文件的大小。反过来,由文件被映射部分,而不是由文件大小来决定进程可访问内存空间范围(映射时,指定offset最好是内存页面大小的整数倍)。
4、通常使用mmap()的三种情况.提高I/O效率、匿名内存映射、共享内存进程通信。
mmap将一个文件或者其它对象映射进内存。文件被映射到多个页上,如果文件的大小不是所有页的大小之和,最后一个页不被使用的空间将会清零。
当使用mmap映射文件到进程后,就可以直接操作这段虚拟地址进行文件的读写等操作,不必再调用read,write等系统调用.但需注意,直接对该段内存写时不会写入超过当前文件大小的内容.
采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝。对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共享内存则只拷贝两次数据:一次从输入文件到共享内存区,另一次从共享内存区到输出文件。
进程:
使用命令 pmap -x <pid> 可以查看进程的内存占用信息; lsof -a -p <pid> 可以查看一个进程打开的文件信息。ps -Lf <pid> 可以查看进程的线程数。
另外procfs也是一个分析进程结构的好地方。procfs是一个虚拟的文件系统,它把系统中正在运行的进程都显现在/proc/<pid>目录下。