《Linux是怎样工作的》干货整理

目录

零:前言

一 系统完整性

二 OS的完整性

三 用户模式需要了解的

四 进程管理

五 进程调度器

六 内存管理

七 存储层次

八 文件系统

九 外部存储器

十 总结


零:前言

最近看了一本Linux相关的书籍,就是下面这本:

 看完后,最直接的感受就是:这是少有的技术方面的、我能在一天内看完的书。曾经听人讲三天看完高数,我估计就跟自己看这本书的感觉一样。但我这是“回锅”,跟人家“打新”还是有很大差距的。看完意犹未尽,就整理了一些知识点,算是到此一游吧。

一 系统完整性

当我们写一个Hello world程序,在shell中运行,显示最终结果的时候,并不是自己的程序完成了所有工作,而是我们将自己的程序作为一块拼图,嵌入了一个可完成运行程序的框架中。这个框架从底层到上层依次包括了如下内容:

硬件设备

内核

OS提供的库

第三方库

最后才是我们的程序

二 OS的完整性

OS管理系统硬件资源,为用户使用系统资源提供便利。OS包括了如下几个大块的功能:

用户模式与内核模式、进程及进程管理、内存及内存管理、设备驱动、外部存储、网络等。

三 用户模式需要了解的

1 系统调用。需要注意,并不存在用户进程绕过系统调用而直接切换CPU运行模式的方法。

2 可以用strace程序跟踪系统调用。

3 如果system占用系统时间较大时,说明陷入了系统调用发起过多或者系统负载过高等糟糕状态。此时,同样可以通过strace -T 选项跟踪那些系统调用占用了大部分时间。

4 系统调用的包装函数一般包含在编译工具链条中。

5 使用ldd跟踪程序依赖的库。C标准库是大部分程序依赖的基础库。GNU项目提供glibc作为C标准库使用。LLVM与CLANG使用另外的C标准库。

四 进程管理

1 通过fork系统调用创建子进程

2 通过execve创建新的进程

3 可通过readelf分析可执行文件的格式

4 关注proc下的进程相关信息

5 脚本中bash通过fork and exec创建新进程

五 进程调度器

1 一个CPU(逻辑CPU)同一时间只运行一个进程

2 多进程轮流使用CPU

3 因为上下文切换的存在,所以用户代码的执行存在被打断的可能

4 运行时间和执行时间不同。Sleep10程序运行时间可能很长,但执行时间很短,因为CPU大部分时间可能在睡眠。

5 CPU无事可干时执行空闲进程。为了节省功耗,空闲进程会使用特殊指令让逻辑CPU进入休眠状态。

6 当所有逻辑CPU都有任务可干时,增加新的进程,并不会增加吞吐量,反而会增加延迟。

7 多核运行程序时,需要考虑CPU配对情况,这会影响缓存的使用。

8 可使用ps命令的etime和time字段分析进程的运行时间和执行时间。

9 虽然谁都可以降低进程优先级,但只有root权限用户才能进行提高优先级的操作。

10 使用taskset命令可以限定进程运行的逻辑CPU。

六 内存管理

1 可使用sar -r命令来采集内存使用信息

2 简单物理地址模式内存分配存在三个问题:内存碎片化;安全隔离;难以执行多任务(可执行文件格式中包含有代码段和数据段信息以及地址,如果直接使用物理内存方式,那么地址的确认将不再变得统一)。

3 现代系统都采用了虚拟内存。进程无法直接访问真是的内存,不存在直接访问物理地址的方法。

4 进程访问未分配内存,内核缺页中断检测到非法访问,会发送SIGSEGV信号。通常收到该信号的进程会被强制结束运行。

5 可以通过 /proc/pid/maps文件查看进程的内存映射和分配情况。

6 使用虚拟地址可以解决内存碎片化问题(分页);可以解决隔离问题(进程有各自的页表);可以解决多任务的问题(地址统一,具体映射时,可以映射到不同的物理地址)。

7 内核映射的地址虽然处于用户进程大地址空间中,但用户进程无法直接访问。

8 虚拟内存的应用:

A 文件映射。可以将一个文件映射到内存中,修改文件内存内容,查看文件是否改变。        B 请求分页。分配内存成功并不代表内核已经为进程分配了物理内存,只有实际使用时,才会导致物理内存的分配。可以使用sar -B 命令观测缺页中断的发生情况。需要注意区分虚拟内存不足和物理内存不足。

C 写时复制。进程创建时采用写时复制机制。创建子进程时,会将父进程的页表复制给子进程。虽然父进程页表中存在表示写入权限的字段,但是此时,会将双方的写入权限都失效。这样,由于没有写入权限,所以在尝试写入时,会引发缺页中断。缺页中断处理中会发现需要复制,此时会为子进程分配页面并将父进程的页面内容复制到子进程中,并根据请求,修改新的页面内容。自此,父子进程页面分道扬镳。重新将父子进程页表对应项目配置为具备可写权限。需要注意,因为虚拟内存的存在,可能出现fork调用成功而进程后续执行失败的情况,此时可能是物理内存不够,缺页中断处理失败导致。

D 页交换。外部存储划分出交换分区,将进程部分暂不用(有专门的算法来选择)的内存页面换出到交换分区,以此释放部分页面从而满足新的内存分配要求。内核会记录换出页面的详细信息,以便在需要时,再换入。需要注意,长期内存不足,可能导致频繁的换入换出,从而使系统处于抖动状态。可以使用sar -W命令查看系统交换处理情况。

E 多级页表。在只使用部分虚拟内存空间的情况下,多级页表可以节省内存(减少页表本身的内存占用)。创建太多进程或者进程使用太多虚拟内存都会导致系统陷入内存不足。

F 标准大页。使用大页可以减少页表项(一项可以表示更大的内存空间),从而减少页表本身的内存占用。但是,大页可能加剧内部碎片产生的浪费。数据库和虚拟机管理器等都是需要使用大量虚拟内存的软件,标准大页能够减少这类软件的内存使用量。

七 存储层次

1 计算机采用存储层次实现性能的优化。

2 缓存一致处理有回写和直写两种方式。

3 如果软件设计不合理,导致缓存频繁刷新,也会引发系统抖动。比如伪共享就是典型的例子。

4 现代CPU存在多级缓存,这可以在/sys/devices/system/cpu/cpux/cache/index-x目录下查看

5 系统使用页面缓存来平衡外存和内存的速度差异。但是,当内存紧张,需要是否脏页时,就需要回写,此时可能会导致系统系能下降,特别是当系统上有大量文件脏页时。

6 读写文件时,可以指定direct标记,表示不需要系统辅助缓存。

7 使用sar -B命令可以查看页调换情况

8 可以通过设置脏页占比来预防产生剧烈的回写负荷。

9 超线程是逻辑CPU,与物理CPU甚至多核无关。开启超线程一般无法达到翻倍的性能提升,大部分情况下提升百分之二三十就已经不错了。

八 文件系统

1 Linux操作系统支持多种文件系统。文件系统上存在两种数据类型,数据和元数据。数据是文件本身内容数据,元数据一般是文件系统用来管理的辅助数据,比如名称、位置、大小、格式等。

2 防止用户文件占用太多空间,文件系统支持用户配额设置,支持目录配额。

3 通常使用日志或写时复制来避免文件系统的不一致情况。Ext4和xfs使用日志,btrfs使用写时复制。

4 日志区域(为保证文件系统一致性所用)是用户无法识别的元数据。

5 可以使用fsck命令来检查文件系统的不一致性,但为了可靠,推荐采用定期备份。

6 使用strings命令和dd命令可以尝试直接在块设备上更改文件内容。

7 btrfs的四大特性:多物理卷、快照、RAID及数据损坏检测与修复。

九 外部存储器

1 对磁盘的使用,尽量保证:连续,少次多量。IO调度工作就是根据这几个特性来设计的。主要工作分为:预读、排序、合并。

2 如果单次IO请求量超过数据访问的上限,在通用块层中会将访问划分为多次请求来执行。

3 内核IO调度器只有在多个进程并行读取时或者在异步IO等无须等待读取完成的IO上才能发挥作用。

4 无论是否支持IO预读和合并,随机读写的性能提升都是有限的,所以,要尽量避免随机读取少量数据。

5 对于SSD,某些情况下,IO调度器可能会导致性能下降,这种一般是IO调度运算过程占用的处理时间相对整体数据传输时间占比增加导致的。

6 最后总结一点,尽量将文件数据存放在外存的连续或者相近的区域;尽量以顺序方式访问尽可能大的数据量;尽量将对连续区域的请求汇集到一次访问请求中。

十 总结

也是懒,就只摘抄了部分文字。其实,书中有大量辅助理解的图和实验数据,会让你直观的理解到精髓。推荐一看。

猜你喜欢

转载自blog.csdn.net/wwwyue1985/article/details/128926706
今日推荐