这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

内核

内核算是一个程序员的基本功,更好的理解底层技术。在处理问题时,可以挖掘到问题本质,而不只是停留在技术表面。 特别是在容器领域设计到 cgroups / namespace / unionfs 等基础技术,需要更加深入学习、掌握。

内核是操作系统的核心,其主要功能有:

  • 响应中断,执行中断服务程序
  • 管理多个进程,调度和分享处理器时间
  • 管理进程地址空间和内存管理
  • 网络和进程间通信等系统服务程序

内核的活动范围:

  • 运行于用户空间,习性用户进程
  • 运行于内核空间,处理进程上下文,代表某个特定进程的执行
  • 运行于内核空间,处理中断上下文,与进程无关,处理某个特定的中断

官网 https://kernel.org/

本系列围绕在 “进程管理”,“内存管理”,“IO栈”,“网络栈”四大脉络,总结 Linux Kernel 的一些常识知识。

Kernel 版本

Linux内核根据版本具有不同的支持级别,长期支持版本(LTS),超长期支持(SLTS)。

kernel-version

# 查询内核版本
$ uname -a
Linux xxx 5.10.16.3-microsoft-standard-WSL2 #1 SMP Fri Apr 2 22:23:49 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux  

$ uname -a
Linux xxx 5.4.0-105-generic #119-Ubuntu SMP Mon Mar 7 18:49:24 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

$ uname -a
Linux xxx 5.15.81-flatcar #1 SMP Tue Dec 6 22:42:27 -00 2022 x86_64 Intel(R) Xeon(R) CPU E5-2680 v4 @ 2.40GHz GenuineIntel GNU/Linux

# 查询系统版本
$ cat /etc/issue
Ubuntu 20.04.4 LTS \n \l

内核版本说明:

  1. 前三组数字为:主版本号 + 次版本号 + 修订版本号。
  2. SMP : 对称多处理机,表示内核支持多核、多处理器。
  3. x86_64 : 采用64位的cpu

抽象级别和层次

最底层是硬件系统,包括cpu和ram,此外硬盘和网络接口也是硬件系统的一部分。

硬件系统之上是内核,是操作系统的核心。内核是运行在内存中的软件,向cpu发送指令。内核管理硬件系统,是硬件系统和应用程序之间进行通信的接口。

进程是计算机中运行的程序,由内核统一管理,组成了最顶层,称为 用户空间

basic-component

内核和用户进程之间最主要的区别是:内核在内核模式下运行,而用户进程是在用户模式中运行。在内核模式中运行的代码可以不受限的访问cpu和内存,这种模式功能强大,因为内核进程可以让整个系统崩溃。只有内核可以访问的空间称为内核空间

1 - 修改内核参数

查看、修改 Linux 内核参数

查看、修改 Linux 内核参数

查看

方法一:

通过 /proc/sys 目录,使用 cat 命令查看对应文件的内容。
此目录是 Linux 内核启动后生成的伪目录,其目录下的 net 文件夹中存放了当前系统中生效的所有内核参数、目录树结构与参数的完整名称相关。 如 net.ipv4.tcp_tw_recycle ,对应的文件就是 /proc/sys/net/ipv4/tcp_tw_recycle,文件的内容就是参数值。 执行如下命令查看:

cat /proc/sys/net/ipv4/tcp_tw_recycle

方法二:

通过 /etc/sysctl.conf 文件进行查看,执行以下命令,查看当前系统中生效的所有参数。

sysctl -a

修改

  • 方法一:通过修改 /proc/sys 目录中对应的文件,临时修改,重启后会重置为原参数值,一般用于临时性验证。
  • 方法二:通过修改 /etc/sysctl.conf 文件进行修改,该方法修改的参数值,永久生效。
    1. 修改执行的参数值: sysctl -w kernel.domainname=“example.com”
    2. 修改配置文件: vim /etc/sysctl.conf
    3. 配置生效: sysctl -p

2 - 内存管理

内存管理

内核所管理的另一个重要资源是内存。为了提高效率,由硬件管理虚拟内存,内存是按照所谓的 内存页 方式进行管理的。 Linux 包括了管理可用内存的方式,以及物理和虚拟映射所使用的硬件机制。不过内存管理要管理的不止 4KB 缓冲区。

内核不仅管理服务器上的可用物理内存,还可以创建和管理虚拟内存。 内核通过硬盘上的存储空间来实现虚拟内存,这块区域称为 交换空间(swap space)。内核不断在交换空间和实际的物理内存之间反复交换虚拟内存中的内容。

Linux提供了对 4KB 缓冲区的抽象,如slab分配器。这种内存管理模式使用 4KB 缓冲器为基数,然后从中分配结构,并跟踪内存页使用情况, 比如哪些内存页是满的,哪些页面没有完全使用,哪些页面为空。

3 - 虚拟内存

虚拟内存

虚拟内存

做单片机的时候,程序需要烧录进芯片,这样程序才能跑起来。单片机的CPU是直接操作内存的【物理地址】。

这种情况下,在内存中想同时运行两个程序是不可能的,第二个程序在相同的位置会擦掉第一个程序的所有内容,程序会崩溃。

操作系统时如何解决这个问题的?

这里关键的问题是两个程序都引用了绝对的物理地址,这个正是我们需要避免的。

我们把进程所使用的的地址隔离起来,让操作系统为每个进程分配独立的一套【虚拟地址】,至于虚拟地址最终怎么样落到物理内存里,对进程来说是透明的。

操作系统会提供一种机制,将不同进程的虚拟地址和不同内存的物理地址映射起来。

如果程序要访问虚拟地址的时候,由操作系统进行转换成不同的物理地址,这样不同的进程运行写入不同的物理地址,就不会冲突。

  • 我们程序所使用的内存地址叫做虚拟内存地址
  • 实际存在硬件里面的空间地址叫做物理内存地址

进程持有的虚拟地址会通过 CPU 芯片中的内存管理单元(MMU)的映射关系,来转换成物理地址,然后通过物理地址访问内存。

内核通过硬盘上的存储空间来实现虚拟内存,这块区域称为 交换空间(swap space)。内核不断在交换空间和时间的物理内存之间反复交换虚拟内存中的内容。

virtual-memory

操作系统是如何管理虚拟地址和物理地址之间的关系?

主要有两种方式,分别的内存分段内存分页

内存分段

程序是由若干个逻辑分段组成的,可由代码分段、数据分段、栈段、堆段组成。 不同的段有不同的属性,所以就用分段(Segmentation)的形式把这些段分离出来。

分段的办法解决了程序不需要关心物理内存地址的问题,但是也有一些缺点:

  1. 内存碎片问题
  2. 内存交换的效率低的问题

内存分页

分段的好处是能产生连续的内存空间,但是会出现 外部内存碎片内存交换的空间太大 的问题。 要解决这些问题,就要想出能少出现内存碎片的办法。另外,当需要进行内存交换的时候,让需要交换写入或者从磁盘装载的数据少一点,这样就可以解决,也就是内存分页(Paging)。

分页是把整个虚拟和物理内存空间切成一段固定尺寸的大小,这样一个连续并且固定的内存空间,我们叫做 。在 Linux 下,每页大小为 4KB 。

虚拟地址和物理地址之间通过 页表 来映射。

页表存储在内存里,内存管理单元(MMU)就将虚拟内存地址转换成物理地址的工作。

当进程访问的虚拟地址在页表中查不到时,系统会产生一个 缺页异常,进入系统内核空间分配物理内存、更新进程页表,最后再返回用户空间,恢复进程的运行。

分页是怎么样解决分段的【外部内存碎片和内存效率低】的问题?

内存分页由于内存空间都是预先划分好的,也就不会像内存分段一样产生间隙非常小的内存。采用分页,页和页之间是紧密排列的,所以不会有外部碎片。

但是,因为内存分页之间分配的最下单位是一页,所以会出现内存浪费,所以针对 内存分页机制会有 内部内存碎片 的现象。

如果内存空间不够,操作系统会把其他正在运行的进程中[最近没有被用]的内存页释放掉,也就是暂时写在硬盘上,称为 换出(Swap Out)。一旦需要的时候,再加载进来,称为 换入**(Swap In)**。所以一次性写入磁盘的只有少数页,不会花太多时间,内存交换的效率就相对比较高。

分页会产生的页表过大问题,有了多级页表,解决空间上问题,但是这会导致CPU在寻址的过程中,需要有很多层表参加,加大了时间的开销。 根据程序的局部性原理,在CPU芯片中加入了 TLB,负责缓存最近常被访问的页表项,大大提高了地址的转换速度。