linux 和 操作系统知识点

常用命令

ps -ef 查询所有进程,包含启动信息,启动用户、进程id
pmap -x 查询进程内存占用
top 查看系统运行情况,查看负载,内存占用,cpu占用,用M按内存排序,用P按照cpu占用排序。top -Hp 制定进程输出线程信息。
du -h --max-depth=1 查看当前一级目录下的文件大小,不指定深度则当前目录下每个字目录都会列出来
df -h df是查看磁盘总使用情况,-h是方便阅读
printf 标准化输出,可以用于输出格式化数。比如pritf %x 转换16进制输出,%d输出10进制,%o输出8进制。
lsof -i:端口号 查看端口占用
netstat -ntlp 查看所有tcp端口占用,通过grep搜索
awk命令
vim命令 dd删除整行数据
free -h 查看内存
grep 查询文本、-a 10查后面10条,-b 查前面,-10查前后。配合tail -n 1只返回对应匹配的最后一行,配合 head -1查询匹配的第一行
less 看日志,FF到最后
tail -f 监控日志,-n 指定输出行
cat 查看文件
cp -rf 复制文件和覆盖
mv 移动和重命名
which 查找配置命令的文件
mkdir 创建文件夹
touch 创建空白文件
awk
sent
tar -xzvf 解压

vim命令大全

Ctrl+u:向文件首翻半屏;
Ctrl+d:向文件尾翻半屏;
Ctrl+f:向文件尾翻一屏;
Ctrl+b:向文件首翻一屏;
Esc:从编辑模式切换到命令模式;
ZZ:命令模式下保存当前文件所做的修改后退出vi;
:行号:光标跳转到指定行的行首;
:$:光标跳转到最后一行的行首;
x或X:删除一个字符,x删除光标后的,而X删除光标前的;
D:删除从当前光标到光标所在行尾的全部字符;
dd:删除光标行正行内容;
ndd:删除当前行及其后n-1行;
nyy:将当前行及其下n行的内容保存到寄存器?中,其中?为一个字母,n为一个数字;
p:粘贴文本操作,用于将缓存区的内容粘贴到当前光标所在位置的下方;
P:粘贴文本操作,用于将缓存区的内容粘贴到当前光标所在位置的上方;
/字符串:文本查找操作,用于从当前光标所在位置开始向文件尾部查找指定字符串的内容,查找的字符串会被加亮显示;
?name:文本查找操作,用于从当前光标所在位置开始向文件头部查找指定字符串的内容,查找的字符串会被加亮显示;
a,bs/F/T:替换文本操作,用于在第a行到第b行之间,将F字符串换成T字符串。其中,“s/”表示进行替换操作;
a:在当前字符后添加文本;
A:在行末添加文本;
i:在当前字符前插入文本;
I:在行首插入文本;
o:在当前行后面插入一空行;
O:在当前行前面插入一空行;
:wq:在命令模式下,执行存盘退出操作;
:w:在命令模式下,执行存盘操作;
:w!:在命令模式下,执行强制存盘操作;
:q:在命令模式下,执行退出vi操作;
:q!:在命令模式下,执行强制退出vi操作;
:e文件名:在命令模式下,打开并编辑指定名称的文件;
:n:在命令模式下,如果同时打开多个文件,则继续编辑下一个文件;
:f:在命令模式下,用于显示当前的文件名、光标所在行的行号以及显示比例;
:set number:在命令模式下,用于在最左端显示行号;
:set nonumber:在命令模式下,用于在最左端不显示行号;

排查cpu占用高

  1. 查找cpu进程占用cpu最高的,top后p根据cpu排序
  2. printf %x 进程id 获得进程id对应16进制的数。
  3. top -Hp 进程id,查找进程中线程占用情况。
    p表示查看指定进程中的线程信息,H表示查看开启线程查看。Shift+H可以开启关闭线程显示
  4. jstack 进程id | grep -A 20 线程id。查看占用高的线程堆栈信息,从而看到是哪一行代码有问题。

5种io模型

  • 同步阻塞io。需要等待数据准备好(读取网络数据、文件数据等到内核空间),需要等待数据从内核空间复制到用户空间
  • 同步非阻塞io。不需要等待数据准备好,需要等待数据从内核空间复制到用户空间
  • 同步多路复用io。通过集合存储多个文件描述符,同时监听处理多个io。select poll epoll
  • 信号驱动式io。通过信号告知应用程序数据已准备好,应用程序通过系统调用将数据从内核空间复制到用户空间。
  • 异步io。两步都不需要等待,不需要阻塞等待数据复制到用户空间,在数据复制到用户空间后,通过回调,通知应用程序处理

三种网络io多路复用模型poll epoll select

这三种都是io复用机制,可以监视多个描述符的读写事件,且都是同步的,linux不存在异步网络io。(linux将所有设备都当做文件处理,都有对应文件索引既为文件描述符fd,比如磁盘,socket,进程等)

select
采用数组结构存储文件描述符,默认限制1024,通过轮询数组上的描述符状态,达到监视多个io的目的。
select存在的缺点
1单个进程文件描述符数限制最大1024,限制的目的是防止过大导致复制到内核空间性能太差。还有就是因为需要通过轮询,数量越大性能越差。
2每次调用select需要把现有fd集合存到内核空间
3 需要遍历fd集合才能知道每个描述符事件。
如果使用select支持高并发请求,一个线程能处理1024个请求,100w并发需要1k个线程,需要复制100w个fd到内核,内核轮询数组获取有数据的描述符,再将数据复制到应用程序,应用程序再轮询处理。

poll
与select类似,只是存储文件描述符的结构是链表,没有1024的限制,但是还是存在其他相同的缺点。

epoll
io操作分成3步

  1. epoll_create。创建epoll对象,创建了eventpoll结构体,包含一个红黑树rbr和双向链表rblist,红黑树存储添加到epoll的连接,双向链表放着已经有事件的连接。
  2. epoll_ctl。向epoll对象添加套接字,就是往eventpoll的红黑树添加连接,复制到内核态。添加的连接都与一个回调方法做关联,当连接上有数据时,会把事件封装成epitem结构,并添加到eventpoll的双向链表中。
  3. epoll_wait。负责定时检查eventpoll中的双向链表是否有数据,如果不为空,则把事件复制到用户态,供应用程序使用。

通过回调机制解决每次都需要轮询所有连接的问题,通过拆分事件注册和事件扫描,避免每次都要把所有的事件复制到内核态。

epoll虽然用了回调机制,但是还是需要轮询双向链表获得事件,再复制到用户态,所以不是异步io。

操作系统内存存储

参考自https://zhuanlan.zhihu.com/p/50919908

页式存储

由于不同进程占用的内存大小不一,如果直接占用部分连续空间,进程多可能会导致内存碎片的产生(就像一个盒子放很多个球,装满了会有很多缝隙,又利用不了)。
因此操作系统采用一个机制,将进程的内存空间进行拆分,分散到许多不相邻的空间中。这个方式就是页式存储
具体逻辑
将内存分成大小相同的多个存储块,并按照顺序编号。同时将进程也分成若干个与内存块大小相等的块,但是为了方便区分,称之为。(也就是实际内存拆分称为块,逻辑地址拆分后每个块称为页)。为进程分配空间时以页为单位,将若干个页放入不相邻的存储块中。通常最后一页会装不满一个内存块(比如物理内存是(3、3、3),进程内存是8,那么只能拆称3、3、2),形成不可利用的碎片,称为页内碎片因此页面大小和页面数量的制定很重要。


页表
为了找到每个页对应的存储块,系统为进程简历一个索引表,每个页对应一个块,页号->块号。页面中每一项对应关系称为页表项pte。因此页表的作用是页号到块号的地址映射(即逻辑地址->物理地址的转换),而且如果进程中部分内存还没用到,操作系统会为进程分配空闲块号,从小到大排序,记录还没分配的存储块的块号。为了快速的转换、页表是存在内存中的

页表寄存器
存储页表的内存起始地址和页面大小
逻辑地址、物理地址

  • cpu访问内存不是直接访问物理地址,而是通过虚拟地址间接访问物理内存地址。通过建立逻辑地址和物理地址的映射关系,让进程间接访问物理地址。
  • 逻辑地址通过二进制表示,包含页号+页内地址,一段表示页号,一段表示页内地址。
  • 物理地址 = 块号 * 页长 + 页内地址 +(用户基址)
    为什么区分逻辑地址和物理地址?
    制定逻辑地址让真实的物理地址由系统分配调度,避免直接由应用程序处理,导致内存碎片、冲突等。
    cpu 通过虚拟地址获取物理地址的过程
    mmu需要根据页表寄存器获得页表和页面大小。先根据虚拟地址除页面大小,得到页号,根据页表将页号转成块号。根据虚拟地址取余页面大小得到偏移量。通过该偏移量+块地址就可以获得该逻辑地址对应的物理地址。
    计算公式:
    块号*页面大小 + 页内偏移=真实物理地址。
    逻辑地址/页面大小=页号
    两次内存访问
    因为需要将逻辑地址转换成物理地址,需要访问页表,所以CPU访问数据需要访问两次内存.

页表存储
页表在页表项比较多的情况下,也会占用较多内存,因此需要对页表内存进行缩减。会通过将部分页表存储到磁盘,部分存储到内存中。还有就是通过将页表再拆分成多个页表,也就是多级页表,一级页表存储的页号存储二级页表的地址,再从二级页表找到对应的物理块号。

TLB快表。
单独的cpu寄存器。由于将逻辑地址转成物理地址,获取页框的过程需要访问一次内存,得到物理地址访问数据又要访问一次内存。为了提高逻辑地址转换物理地址的速度,又提供了TLB快表,缓存页表,提高逻辑地址转换成物理地址的速度。
页表存储位置
页表存储在pcb中,pcb为进程控制块,用于存放进程的管理和控制信息,随着进程创建时被创建。

mmu内存管理单元通过页表进行地址的转换,且不是一个一个地址转换,而是以页为单位转换。

磁盘读写原理

https://blog.csdn.net/hguisu/article/details/7408047
磁盘上凹凸不平,凸起地方是被磁化了表示为1,凹的地方表示数字0,这样磁盘就可以用二进制存储文字和图片等。

盘片
一个硬盘自上而下有多个盘片,盘片之间有空隙,且每个盘片都是平行的。盘片每分钟都以数千到上万转的速度在高速转动

盘面

  • 每个盘片有两面,一个面即为一个盘面。自上而下从0开始编号,每个编号称为盘面号,也被称为磁头号、块号

磁头

  • 用于从盘面上读取和写入数据,通过控制电路决定是读取还是写入,每个盘面都有一个磁头,盘片上会有磁粉,被写入数据的位置会磁化。
  • 磁头通过磁头臂可以移动位置,移动的方向是沿着半径方向移动,围绕盘中心点绕圈的移动要靠盘片的转动
  • 磁头臂的移动是最慢的。
  • 每个盘片的磁头在同一时刻自上而下都是重叠的,
  • 磁头的读取依靠盘片的转动进行读取。
  • 磁头一开始停留在离中心轴最接近的位置(最里面的圈),此位置为磁头停靠区。当盘片开始转动时,会有一股气流把磁头漂浮在盘面上方(盘面和磁头不接触,但是距离只有0.01μm),磁头会移动到其他区域,也就是数据区,磁头读写数据从盘面的最外圈开始读写。

磁道

  • 磁盘在格式化后,会有多个同心圆,每个圆圈被称为磁道
  • 数据的写入由外往内,外磁道写完后再往内磁道移动写入。

扇区

  • 磁盘数据的最小存储单位。
  • 磁道被划分成一段段圆弧,每个圆弧被称为扇区,每个扇区都有一个编号称为扇区号.
  • 每个扇区包含512byte的数据和一些其他信息。每个扇区作为一个单元同时读出或者写入。现在也有4k大小区扇区。
  • 同样转动速度下,外圈的扇区划过的区域比内圈长。

扇区、块、页的关系

  • 扇区是磁盘存储数据的最小单位,一般为512字节,为磁盘寻址的基本单位。
  • 块是内存的拆分,是操作系统的文件系统的最小单位,可以由系统函数mkfs指定块的大小,不一定是512字节,可以是1k、4k、8k等。块是文件系统的抽象。即一个块中包含多个扇区,块的大小是扇区大小的整数倍
  • 页是进程的拆分,一个进程的内存会拆分成一个个块区存储,这个块为了区分文件系统的块,称为,页的大小一般等于块的大小。

柱面

  • 所有盘面上的同一个磁道自上而下形成一个圆柱,被称为一个柱面。每个柱面从外往内编号,称为柱面号.
  • 数据的写入从自上而下,写完一个磁道后,会写入同一柱面的磁道。这样数据的写入就不用移动磁头臂,只需要用下一个盘面的磁头区写入。同个柱面的磁道都写完后,才往内一层磁道写数据。

磁盘访问的流程

  • 系统将逻辑地址传给磁盘,磁盘将地址翻译成物理地址。物理地址包括柱面号,盘面号(磁头号),扇区号
  • 寻道。根据盘号找到对应盘面的磁头,磁头臂根据柱面号移动磁头到对应的柱面。这个过程叫做寻道,所耗费时间叫做寻道时间。
  • 旋转。根据扇区号等待盘片旋转到当前扇区,这个等待时间为旋转时间

因此需要耗费

  1. 寻道时间:磁头移动定位到指定磁道.
  2. 旋转时间:等待指定扇区从磁头下旋转经过.
  3. 数据传输时间:数据在磁盘与内存之间的实际传输.

磁盘读写原理

  • 系统将文件存储到磁盘,数据的写入从第一盘面的第一磁道的扇区开始写入,写完之后是同一柱面的下一个磁头开始写入。即写入的顺序是从上到下,从外到内。找到地址对应的磁道、扇区后,根据当前读写任务转换电路进行读写,然后继续寻找下一个扇区,

数据预读

  • 每次读取数据都会预读一定长度的数据存到内存,因为通常读取数据,程序会继续读取下一部分数据,减少io。预读的一般是的整数倍,页的大小通常为4k,主存和磁盘以页为单位交换数据,当程序要读取的数据不在主存,就会触发缺页异常,系统会向磁盘发起读盘信号,磁盘会往后预读一页或几页数据载入内存(内核缓冲区),把用户读取的部分的数据复制到用户空间。

顺序io和随机io

  • 顺序io因为是不需要询道时间,数据在同一个磁道上,只要等待旋转时间就能读取道数据,所以顺序io可以提高io效率。
    随机io每次读取都要耗费寻道时间,所以效率低。
    mysql自增主键、kafka写入数据都利用顺序io提高了写入效率。

磁盘碎片的产生

  • 由于文件的写入从外磁道写入,再自上而下自外而内,那如果此时要改原先写入的文件,新增数据,就导致文件旁边的位置已经被别的文件写满了,这时只能采取两个方式来处理。
  1. 删除原位置的文件,在其他位置重建文件,写入原文件数据和新数据。
  2. 在别的位置继续写入数据,即一个文件的数据会处在磁盘的多个地方。
    windows就是通过第二种进行处理,然而在文件被删除后,就会留下很多空隙,造成碎片。

总结
磁道越外面读写越快,因为数据的读取总是从外磁道出发,也叫0磁道。

内存映射技术

将用户地址空间与文件建立映射关系,操作文件时直接跟操作内存一样,速度快,对内存的操作会直接反应到对应的文件(即同步到文件的过程由操作系统处理、不用阻塞等待)。

  • 读取数据,避免了io还要将数据复制到内核io缓冲区再到用户空间,直接把磁盘数据复制到用户空间(包括预读的数据)。
  • 写数据时,直接写入内存,由操作系统控制什么时候更新到磁盘。或者手动调用flush函数刷盘。

通过mmap函数可以建立内存映射。
linux的进程虚拟存储器,有一部分区域维护虚拟地址和文件的映射关系,在用户操作某个虚拟地址时,数据不存在时会触发缺页异常,基于关系表将数据直接拷贝到用户空间,重复这样的os页面调度操作。

基于内存映射的进程通信

  • 两个进程都基于同个文件调用map方法获取到buffer,基于该buffer的改动,另一个进程可以再buffer中读取到。像是内存通信。

总线

  • 数据总线 : 双向总线,用于提供cpu和寄存器、io接口等之间的数据传输,总线宽度的位数一般与处理器的位数相同。数据还有可能是状态信息、指令代码、控制信息。
  • 地址总线 : 单向总线,用于传输地址,只能由cpu往外传输,地址总线的位数决定了cpu可直接寻址的内存空间大小。寻址空间=2的n次方 ; (n表示地址线根数),
    控制总线: 双向总线,用于传输控制信号和时序信号,如读写信号、终端信号等。

tss 任务状态段 io许可位图

用于任务切换时存储各寄存器信息,且包含一个io许可位图,规定可以访问的端口。当任进程要执行一个io指令,特权集不足时,会通过进程的tss中的io许可位图检查可以访问的端口,如果符合则可执行,否则则不可执行。可以通过修改进程的tss中的io许可位图,设定进程可以访问的端口。
linux 2.4前每个进程有一个单独的tss,2.4后进程共用一个tss。

寻址空间和内存空间的区别

寻址空间指的是cpu对于内存的寻址能力,就是cpu能访问到的内存空间大小。受总线位数的大小影响,n为地址总线位数,地址空间即为2^n字节。比如地址总线为1,则可以对应两个存储单元,可以分别用0和1表示操作哪个存储单元。一个存储单元为一个字节,具有存储数据、读写数据的功能,有一个地址。

用户空间和内核空间

linux虚拟内存空间被分成用户空间和内核空间,内核是操作系统的核心,内核空间为受到保护的存储空间,应用程序能直接操作的地址空间只有用户空间。32位操作系统,有4g的寻址空间,高1g的地址空间为内核空间。

内核态 用户态

应用程序运行在内核空间就处于内核态,运行在用户空间则为用户态。进程处于内核态可以执行任何指令,可以访问任何内存地址、可以访问任何端口,执行的代码不受任何限制。
进程处于用户态则运行的代码需要收到cpu的检查,只能执行非特权指令,只能访问特定的端口,还有访问进程页表项中规定用户空间可访问的页面地址。

为什么分用户态内核态

为了防止一些危险指令被滥用,影响系统稳定性,比如清内存、设置时钟等,cpu指令被分等级,linux分为ring0和ring3指令,ring0为特权指令,只能运行在内核态。应用进程需要切换到内核态才能执行。

doc系统没有区分用户态和内核态
相当于应用程序都是运行在内核态,所以应用程序很容易导致操作系统崩溃,linux通过内核态和用户态隔离了应用程序和操作系统代码,这样即使应用程序出现问题,也不会影响整个系统的稳定性。所以通过这个机制可以提高系统的稳定性和可用性。

需要在内核态执行的情况
系统资源调用都需要在内核态执行,比如读写磁盘的数据,从网络接口读写数据,分配内存和回收内存等。

用户态和内核态怎么切换
通过系统调用,软中断,硬中断都可以从用户态切换到内核态。比如读磁盘数据时,通过一个指令进入内核态,由系统内核将数据读到内核空间中,再将数据复制到用户空间,应用程序再从用户空间读取。既进程在用户空间和内核空间都有一个堆栈,进程运行在不同空间时使用不同的堆栈。

为什么区分用户态和内核态就能提高稳定性
因为系统资源的操作都由内核代码控制,应用程序只能通过内核暴露的系统调用函数才能操作硬件资源。

处理器的三种运行状态

1 运行在用户空间,执行用户进程
2 运行在内核空间,处于进程上下文,代表某个特定的进程
3 处于内核空间,处于中断上下文,与任何进程无关,用于响应特定的中断请求。处于这种状态是为了可以快速响应中断请求。

进程上下文

进程在各种寄存器和堆栈中存储的指令和数据,上文为已执行的指令和数据,正文为正在执行的,下文为待执行的。进程在切换到内核态时,要保存进程上下文信息,以便再次执行该进程可以恢复到执行前的位置,内核执行也要依赖进程上下文获取执行信息。

中断上下文

中断处理为了提高执行速度,分成上下两部分,分别为中断触发和中断执行,中断触发即响应中断,中断执行为实际执行中断的过程,是可以被新的中断请求中断的。当被新的中断请求中断时,需要将前一个中断请求的执行信息暂存到寄存器和内存,即为中断上下文。
中断请求irq
通过往处理器发送中断请求,可以让处理器暂停当前工作,响应中断请求先处理别的工作。

用户态切换内核态性能损耗

涉及进程上下文切换。假设从a切换到b,上下文切换时需要保存a的上下文,然后将b的上下文恢复到寄存器。切换上下文时需要切换页表目录、切换内核态堆栈、切换硬件上下文、刷新tlb、执行系统调度。还有其他开销,比如cpu缓存、tlb缓存信息都用不到了,要重新去内存读取。线程上下文同样会有性能损耗,本质上线程是一种特殊的进程,只是共享内存区域。

延迟写(delayed write)

传统的UNIX实现在内核中设有缓冲区高速缓存或页面高速缓存,大多数磁盘I/O都通过缓冲进行。 当将数据写入文件时,内核通常先将该数据复制到其中一个缓冲区中,如果该缓冲区尚未写满,则 并不将其排入输出队列,而是等待其写满或者当内核需要重用该缓冲区以便存放其他磁盘块数据时, 再将该缓冲排入到输出队列,然后待其到达队首时,才进行实际的I/O操作。这种输出方式就被称为延迟写。

延迟写存在的问题
延迟写减少了磁盘读写次数,但是却降低了文件内容的更新速度,使得欲写到文件中的数据在一段时间内并没有写到磁盘上。当系统发生故障时,这种延迟可能造成文件更新内容的丢失。为了保证磁盘上实际文件系统与缓冲区高速缓存中内容的一致性

系统调用函数
UNIX系统提供了sync、fsync和fdatasync三个函数。
1)、sync函数
sync函数只是将所有修改过的块缓冲区排入写队列,然后就返回,它并不等待实际写磁盘操作结束。通常称为update的系统守护进程会周期性地(一般每隔30秒)调用sync函数。这就保证了定期冲洗内核的块缓冲区。命令sync(1)也调用sync函数。
2)、fsync函数
fsync函数只对由文件描述符filedes指定的单一文件起作用,并且等待写磁盘操作结束,然后返回。fsync可用于数据库这样的应用程序,这种应用程序需要确保将修改过的块立即写到磁盘上。
3)、fdatasync函数
fdatasync函数类似于fsync,但它只影响文件的数据部分。而除数据外,fsync还会同步更新文件的属性。
对于提供事务支持的数据库,在事务提交时,都要确保事务日志(包含该事务所有的修改操作以及一个提交记录)完全写到硬盘上,才认定事务提交成功并返回给应用层。

内存池

内存池就是申请一定数量的内存,每次需要用到内存就从池中获取申请内存,用完之后再返还。

你可能感兴趣的:(linux)