进程: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>目录下。