小话Linux内核

前言:
       Linux内核是一个免费和开源的单片模块化多任务类 Unix操作系统内核它最初由Linus Torvalds于 1991 年为他的基于i386的 PC 编写,并很快被采用为GNU 操作系统的内核,该操作系统被编写为Unix的免费 (libre)替代品
      要特别注意的是,由于linux内核更新很快,所以很多文件的位置、名称都可能发生变化,所以要查资料也要以版本为第一要素。

       内核的内容很宽泛,包括内核编译、内核配置、内核模块编写、内核系统调用约定、内核开发、内核启动等一系列的课题。

本机实验测试环境:

[root@aozhejin src]# cat /etc/redhat-release   
CentOS Linux release 7.9.2009 (Core)
[root@ht6 src]# uname -r  #查看当前的linux内核版本,有可能有多个内核被安装到本机
3.10.0-1160.62.1.el7.x86_64

  [root@aozhejin /sys/module/sd_mod]#cat /proc/version
  Linux version 3.10.0-1160.62.1.el7.x86_64 (mockbuild@kbuilder.bsys.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) ) #1 SMP Tue Apr 5 16:57:59 UTC 2022

  [root@aozhejin /sys/module/sd_mod]#uname -srm
  Linux 3.10.0-1160.62.1.el7.x86_64 x86_64

[root@ht6 src]# uname -r
3.10.0-1160.62.1.el7.x86_64
[root@ht6 src]# lscpu
Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                8
On-line CPU(s) list:   0-7
Thread(s) per core:    1
Core(s) per socket:    4
Socket(s):             2
NUMA node(s):          1
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 63
Model name:            Intel(R) Xeon(R) CPU E5-2660 v3 @ 2.60GHz
Stepping:              2
CPU MHz:               2593.993
BogoMIPS:              5187.98
Hypervisor vendor:     VMware
Virtualization type:   full
L1d cache:             32K
L1i cache:             32K
L2 cache:              256K
L3 cache:              25600K
NUMA node0 CPU(s):     0-7
Flags:                 fpu vme de.....

了解 Linux 版本号和内核修订

内核被编号是有原因的

1994 年,随着 Linux 内核 1.00 的发布,Linus 开始使用一种新的版本控制系统,该系统在语法中使用了三个变量:“ abc ”。这些变量(a、b 和 c)分别表示特定内核版本的主要版本、次要版本和修订号。

 1) Linux 内核 1.1.95 为例。表示第一个主要版本、第一个次要版本和第 95 次修订。
 2) 从 Linux 内核 2.4 开始,内核名称中的第四个变量表示补丁版本 
即abcd , a是主要版本号,b 是次要版本号,z 是补丁号。请注意:z 不是补丁的数量;它只是表示自上次补丁号以来修复了更多错误。
偶数次版本号表示稳定的内核版本,而奇数版本号表示开发版本
3) 在 Linux 3.0 版中,Linus 删除了版本号中的第四个变量。现在,内核版本根据语法形成:abc,其中 a、b 和 c 分别是主要版本、
次要版本和修订计数。此版本控制方案类似于 1.02.4 内核版本之间使用的方案 Linux 内核有两种类型:开发(实验)和稳定。您可以轻松区分它们,因为稳定内核是 x.even.z 而开发内核是 x.odd.z。
此时当前稳定内核为2.
2.14,当前实验内核为2.3.99-pre5。 您会注意到最后一个版本号中的 pre。实验内核中的这一约定表明稳定版本即将发布,除非您有特殊情况,否则不会向该系列添加新功能。
实验内核不稳定。

   本机版本:

[root@ht6 src]# uname -r  #查看当前的linux内核版本,有可能有多个内核被安装到本机
3.10.0-1160.62.1.el7.x86_64
3 代表内核版本
10代表主要修订
0 代表次要修订
- 之后的代表的是release版本(重新被打包,打包的是基于3.10.0内核版本)
 1160 代表补丁的编号
el7代表的是操作系统版本即Enterprise Linux 7(简称el7),也就是centos 7
x86_64 就是x86架构64位版本
按照基本的: name-version-release.architecture.rpm
请看下rpm命令约定
http://ftp.rpm.org/max-rpm/ch-rpm-file-format.html

 你以这八个选项与 uname 一起使用来输出各个字段

内核名称:-s
主机名:-n
内核版本:-r
内核版本:-v
机器硬件名称:-m
处理器:-p
硬件平台:-i
操作系统:-o

  我们可以查看yum源的镜像列表

[root@aozhejin /sys/module/sd_mod]#yum list kernel
Loaded plugins: fastestmirror, langpacks, product-id, search-disabled-repos, subscription-manager
This system is not registered with an entitlement server. You can use subscription-manager to register.
Loading mirror speeds from cached hostfile
 * base: mirrors.aliyun.com
 * epel: mirrors.bfsu.edu.cn
 * extras: mirrors.aliyun.com
 * updates: mirrors.aliyun.com
Installed Packages
kernel.x86_64                                                              3.10.0-327.el7                                                                    @anaconda
kernel.x86_64                                                              3.10.0-1160.42.2.el7                                                              @updates 
kernel.x86_64                                                              3.10.0-1160.62.1.el7                                                              @updates 
Available Packages
kernel.x86_64                                                              3.10.0-1160.88.1.el7                                                              updates

 

一、linux官网

  https://www.kernel.org/
       https://www.kernel.org/category/releases.html

二、查看linux版本

[root@ht6 src]# uname -r
3.10.0-1160.62.1.el7.x86_64
[root@ht6 src]# uname -a
 Linux ht6.node 3.10.0-1160.62.1.el7.x86_64 #1 SMP Tue Apr 5 16:57:59 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
[root@aozhejin /root]#dmesg | grep Linux

三、内核image放置目录(本机安装有多个linux内核)

[root@aozhejin /root]#ll /boot
total 141684
-rw-r--r--  1 root root   153596 Sep  7  2021 config-3.10.0-1160.42.2.el7.x86_64
-rw-r--r--  1 root root   153619 Apr  6  2022 config-3.10.0-1160.62.1.el7.x86_64
-rw-r--r--. 1 root root   126426 Nov 20  2015 config-3.10.0-327.el7.x86_64
drwxr-xr-x  3 root root       16 Sep 23  2021 efi
drwxr-xr-x. 2 root root       26 Jun  7  2017 grub
drwx------. 5 root root     4096 Apr 11  2022 grub2
-rw-r--r--. 1 root root 45389979 Jun  7  2017 initramfs-0-rescue-604749976162444b8489b13ac1fad2ed.img
-rw-------  1 root root 21230096 Apr 11  2022 initramfs-3.10.0-1160.42.2.el7.x86_64.img
-rw-------  1 root root 21230472 Apr 11  2022 initramfs-3.10.0-1160.62.1.el7.x86_64.img
-rw-------  1 root root 21193002 Sep 23  2021 initramfs-3.10.0-327.el7.x86_64.img
-rw-r--r--. 1 root root   602637 Jun  7  2017 initrd-plymouth.img
-rw-r--r--  1 root root   320757 Sep  7  2021 symvers-3.10.0-1160.42.2.el7.x86_64.gz
-rw-r--r--  1 root root   320668 Apr  6  2022 symvers-3.10.0-1160.62.1.el7.x86_64.gz
-rw-r--r--. 1 root root   252612 Nov 20  2015 symvers-3.10.0-327.el7.x86_64.gz
-rw-------  1 root root  3620596 Sep  7  2021 System.map-3.10.0-1160.42.2.el7.x86_64
-rw-------  1 root root  3621999 Apr  6  2022 System.map-3.10.0-1160.62.1.el7.x86_64
-rw-------. 1 root root  2963044 Nov 20  2015 System.map-3.10.0-327.el7.x86_64
-rwxr-xr-x. 1 root root  5156528 Jun  7  2017 vmlinuz-0-rescue-604749976162444b8489b13ac1fad2ed
-rwxr-xr-x  1 root root  6773352 Sep  7  2021 vmlinuz-3.10.0-1160.42.2.el7.x86_64
-rwxr-xr-x  1 root root  6777448 Apr  6  2022 vmlinuz-3.10.0-1160.62.1.el7.x86_64
-rwxr-xr-x. 1 root root  5156528 Nov 20  2015 vmlinuz-3.10.0-327.el7.x86_64
关注 initramfs、System.map、vmlinuz

查看系统安装的全部内核:

[root@aozhejin /sys/module/sd_mod]# grubby --info=ALL
index=0
kernel=/boot/vmlinuz-3.10.0-1160.62.1.el7.x86_64
args="ro rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet LANG=en_US.UTF-8"
root=/dev/mapper/centos-root
initrd=/boot/initramfs-3.10.0-1160.62.1.el7.x86_64.img
title=CentOS Linux (3.10.0-1160.62.1.el7.x86_64) 7 (Core)
index=1
kernel=/boot/vmlinuz-3.10.0-1160.42.2.el7.x86_64
args="ro rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet LANG=en_US.UTF-8"
root=/dev/mapper/centos-root
initrd=/boot/initramfs-3.10.0-1160.42.2.el7.x86_64.img
title=CentOS Linux (3.10.0-1160.42.2.el7.x86_64) 7 (Core)
index=2
kernel=/boot/vmlinuz-3.10.0-327.el7.x86_64
args="ro rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet LANG=en_US.UTF-8"
root=/dev/mapper/centos-root
initrd=/boot/initramfs-3.10.0-327.el7.x86_64.img
title=CentOS Linux (3.10.0-327.el7.x86_64) 7 (Core)
index=3
kernel=/boot/vmlinuz-0-rescue-604749976162444b8489b13ac1fad2ed
args="ro rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet"
root=/dev/mapper/centos-root
initrd=/boot/initramfs-0-rescue-604749976162444b8489b13ac1fad2ed.img
title=CentOS Linux (0-rescue-604749976162444b8489b13ac1fad2ed) 7 (Core)
index=4
non linux entry

linux 查看内核启动日志:

[root@aozhejin /root]#dmesg | more
[    0.000000] Initializing cgroup subsys cpuset
[    0.000000] Initializing cgroup subsys cpu
[    0.000000] Initializing cgroup subsys cpuacct
[    0.000000] Linux version 3.10.0-1160.62.1.el7.x86_64 (mockbuild@kbuilder.bsys.centos.org) 
(gcc version 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) ) #1 SMP Tue Apr 5
16:57:59 UTC 2022
[    0.000000] Command line: BOOT_IMAGE=/vmlinuz-3.10.0-1160.62.1.el7.x86_64 
root=/dev/mapper/centos-root ro rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet LA
NG=en_US.UTF-8
[    0.000000] Disabled fast string operations
[    0.000000] e820: BIOS-provided physical RAM map:
[    0.000000] BIOS-e820: [mem 0x0000000000000000-0x000000000009ebff] usable
[    0.000000] BIOS-e820: [mem 0x000000000009ec00-0x000000000009ffff] reserved
[    0.000000] BIOS-e820: [mem 0x00000000000dc000-0x00000000000fffff] reserved
[    0.000000] BIOS-e820: [mem 0x0000000000100000-0x00000000bfecffff] usable
[    0.000000] BIOS-e820: [mem 0x00000000bfed0000-0x00000000bfefefff] ACPI data
[    0.000000] BIOS-e820: [mem 0x00000000bfeff000-0x00000000bfefffff] ACPI NVS
[    0.000000] BIOS-e820: [mem 0x00000000bff00000-0x00000000bfffffff] usable
[    0.000000] BIOS-e820: [mem 0x00000000f0000000-0x00000000f7ffffff] reserved
[    0.000000] BIOS-e820: [mem 0x00000000fec00000-0x00000000fec0ffff] reserved
[    0.000000] BIOS-e820: [mem 0x00000000fee00000-0x00000000fee00fff] reserved
[    0.000000] BIOS-e820: [mem 0x00000000fffe0000-0x00000000ffffffff] reserved
[    0.000000] BIOS-e820: [mem 0x0000000100000000-0x000000043fffffff] usable
[    0.000000] NX (Execute Disable) protection: active
[    0.000000] SMBIOS 2.4 present.
.....

 

四、内核模块
            内核模块的一些相关命令(内核模块分内置模块和可加载模块)

    用途
lsmod    显示 Linux内核中已加载模块的状态
modinfo modinfo module_name  查看某个模块相信信息
modprobe modprobe -c 显示所有模块的综合配置
  modprobe --show-depends module_name 显示某个模块的依赖
  modprobe -c | grep module_name 显示特定某块的配置
  modprobe -r module_name 卸载模块
  modprobe模块名称 parameter_name=parameter_value 将参数传递给模块的基本方法是使用modprobe命令
  modinfo -F signer module_name(例如: oops.ko) 查看签名
insmod  insmod 文件名 动态加载模块
rmmod rmmod module_name 卸载模块
     
     
     


  五、内核模块加载的地址
       lsmod读取的就是这个文件来进行加工和整理输出

[root@aozhejin /root]#cat /proc/modules
veth           13458 0 -           Live 0xffffffffc0663000
xt_CHECKSUM    12549 1 -           Live 0xffffffffc065e000
iptable_mangle 12695 1 -           Live 0xffffffffc0659000
ipt_REJECT     12541 2 -           Live 0xffffffffc064f000
nf_reject_ipv4 13373 1 ipt_REJECT, Live 0xffffffffc0654000
tun            36164 1 -           Live 0xffffffffc0645000
......
objdump -dS --adjust-vma=0xffffffffc0663000 veth.ko

  /proc/modules 分析意义远大于lsmod输出的结果
1) 第1列是模块名
2) 第2列是模块占据内存大小(字节计算)
3) 第3列是模块是否被其他模块,0标识没有引用,可以被rmmod卸载. 1表示有一个实例被创建,正在被其他模块调用
   2表示,已经有2个其他内核模块在调用它,这个时候这个模块会被创建2个实例,这时当然也不能用rmmod卸载了
4)第4列 引用(依赖)其他模块,如果是多个以 ","号分开。 如果没有引用其他内核模块,则用“-”来标识
5)第5列 有三个值 Live/Loading/Unloading 标识它是否模块加载的状态
6)第6列 当前内核内存偏移量

objdump反编译 veth
     0xffffffffc0663000 就是这个模块被加载的内存地址

[root@aozhejin ~]$locate veth.ko
/usr/lib/modules/3.10.0-1160.42.2.el7.x86_64/kernel/drivers/net/veth.ko.xz
/usr/lib/modules/3.10.0-1160.62.1.el7.x86_64/kernel/drivers/net/veth.ko.xz
/usr/lib/modules/3.10.0-327.el7.x86_64/kernel/drivers/net/veth.ko
[root@aozhejin
~]$ objdump -dS --adjust-vma=0xffffffffc0663000 /usr/lib/modules/3.10.0-327.el7.x86_64/kernel/drivers/net/veth.ko | more /usr/lib/modules/3.10.0-327.el7.x86_64/kernel/drivers/net/veth.ko: file format elf64-x86-64 Disassembly of section .text: ffffffffc0663000 <veth_get_settings>: ffffffffc0663000: e8 00 00 00 00 callq ffffffffc0663005 <veth_get_settings+0x5> ffffffffc0663005: 55 push %rbp ffffffffc0663006: b8 10 27 00 00 mov $0x2710,%eax ffffffffc066300b: 31 d2 xor %edx,%edx ffffffffc066300d: 66 89 46 0c mov %ax,0xc(%rsi) ffffffffc0663011: c7 46 04 00 00 00 00 movl $0x0,0x4(%rsi) ffffffffc0663018: 31 c0 xor %eax,%eax ffffffffc066301a: 48 89 e5 mov %rsp,%rbp ffffffffc066301d: c7 46 08 00 00 00 00 movl $0x0,0x8(%rsi) ffffffffc0663024: 66 89 56 1c mov %dx,0x1c(%rsi) ffffffffc0663028: c6 46 0e 01 movb $0x1,0xe(%rsi) ffffffffc066302c: c6 46 0f 00 movb $0x0,0xf(%rsi) ffffffffc0663030: c6 46 10 00 movb $0x0,0x10(%rsi) ffffffffc0663034: c6 46 11 00 movb $0x0,0x11(%rsi) ffffffffc0663038: c6 46 12 00 movb $0x0,0x12(%rsi) ffffffffc066303c: c7 46 14 00 00 00 00 movl $0x0,0x14(%rsi) ffffffffc0663043: c7 46 18 00 00 00 00 movl $0x0,0x18(%rsi) ffffffffc066304a: 5d pop %rbp ffffffffc066304b: c3 retq ffffffffc066304c: 0f 1f 40 00 nopl 0x0(%rax)

 

六、 内核模块位置和名称
            被放置在了/lib/modules/$(uname -r)/ 目录,最好使用$(uname -r),因为当前你可能有多个内核镜像在系统里面

[root@aozhejin /root]#cat /lib/modules/$(uname -r)/modules.builtin | more
kernel/arch/x86/crypto/aes-x86_64.ko
kernel/arch/x86/crypto/sha1-ssse3.ko
kernel/arch/x86/crypto/sha256-ssse3.ko
kernel/arch/x86/events/intel/intel-rapl-perf.ko
kernel/arch/x86/events/intel/intel-uncore.ko
kernel/arch/x86/kernel/msr.ko
kernel/arch/x86/kernel/cpuid.ko
kernel/mm/zpool.ko
kernel/mm/zbud.ko
kernel/mm/zsmalloc.ko
kernel/fs/binfmt_script.ko
kernel/fs/autofs4/autofs4.ko
kernel/fs/configfs/configfs.ko


七、内核模块(可加载而未加载的)命名的子目录
  /sys/module 树由以下结构组成:
 1、在 /sys/module目录下,列出内核模块名称(包含内置和可加载的)
 2、进入每个模块目录,这里有个“parameters”目录或直接是文件,该文件可以直接配置该内核的参数
 3、根据vfs定义,/sys/...

[root@aozhejin /sys/module]#ls
8250               debug_core                    hid              kgdboc                 
ablk_helper        devlink                       hid_apple        kgdbts              
acpi               dm_log                        hid_magicmouse   libata                 
acpiphp            dm_mirror                     hid_ntrig        libcrc32c    
...
[root@aozhejin2 /sys/module]#lsmod | grep 8250

内核启动参数配置
    https://www.cnblogs.com/aozhejin/p/17150631.html

 内核当前运行占用资源情况,注意/proc是存储在ram上,每次重启都会重新生成。/proc下是进程和内核的信息输出
  1、内核的相关信息输出到/proc/下

  2、/proc/sys/kernel 下实时配置内核参数
      https://docs.kernel.org/admin-guide/sysctl/kernel.html
      https://linux.die.net/lkmpg/x40.html

 八、内核配置文件
    /lib/modules/`uname -r`/build/.config

复制代码
[root@aozhejin /]# zcat /proc/config.gz | grep CONFIG_BINFMT_ELF
gzip: /proc/config.gz: No such file or directory (错误)

[root@ht6 src]# cat /lib/modules/`uname -r`/build/.config | more (正确)
#
# Automatically generated file; DO NOT EDIT.
# Linux/x86_64 3.10.0-1160.62.1.el7.x86_64 Kernel Configuration
#
CONFIG_64BIT=y
CONFIG_X86_64=y
CONFIG_X86=y
CONFIG_INSTRUCTION_DECODER=y
CONFIG_OUTPUT_FORMAT="elf64-x86-64"
CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
.....

九、 内核运行时动态地修改内核的运行参数
    sysctl 命令
      sysctl命令被用于在内核运行时动态地修改内核的运行参数
   1)、临时写入/proc/sys/*

  [root@aozhejin2 /proc/sys/fs]#echo 5000>/proc/sys/fs/file-max
  -bash: 5000: Bad file descriptor

    正确语法语法 sysctl  -w  path.to.seting=value
   举例: 
    写入  /proc/sys/net/ipv4/ip_forward
   sysctl  -w  net.ipv4.ip_forward=1
     写入 /proc/sys/fs/file-max
   sysctl  -w  fs.file-max=60000
    写入/proc/sys/net/ipv4/ip_forward
     echo 1 > /proc/sys/net/ipv4/ip_forward
  这种情况下
  注意: /proc是一个伪文件系统,是存在ram中的,系统重启后都会丢失
永久生效
1、重启前手工修改  /etc/sysctl.conf(sysctl命令的配置文件),然后重启,这个时候 /etc/rc.d/rc.sysinit 会读取它
2、通过临时写入,执行 sysctl -p 命令,把相关配置写入 /etc/sysctl 配置生效
对其他配置感兴趣可以使用 sysctl -a > file 来查看(/proc/sys可修改项达500多项)

内核文档:

Documentation/sysctl/kernel.txt 该文档针对   /proc/sys/kernel/*

 

十、内核引导协议(boot):
  在 x86 平台上,Linux 内核使用了相当复杂的引导约定。这在一定程度上是由于历史方面的原因,以及早期希望内核本身成为可引导映像的愿望、复杂的 PC 内存模型以及由于实际消亡导致的 PC 行业预期的改变。模式 DOS 作为主流操作系统。当前,存在以下版本的 Linux/x86 引导协议

      详细请看这里 https://www.kernel.org/doc/html/v5.6/x86/boot.html

相关一些参考资料:
   https://en.wikipedia.org/wiki/Linux_kernel
  https://en.wikibooks.org/wiki/The_Linux_Kernel/Modules
   https://wiki.archlinux.org/title/Kernel_module
  https://linux-kernel-labs.github.io/refs/heads/master/labs/kernel_modules.html   
  https://linux.die.net/lkmpg/index.html
  https://tldp.org/LDP/lkmpg/2.4/lkmpg.pdf
  https://spdx.org/licenses/Linux-syscall-note.html   系统调用注解
  https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/stable-api-nonsense.rst  linux驱动接口
  https://www.sco.com/developers/devspecs/gabi41.pdf   abi接口
  https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/book1.html  linux核心规范
  https://open-std.org/JTC1/SC22/WG21/docs/papers/2020/p0124r7.html  内核内存模型
  https://web.archive.org/web/20050723031159/http://kerneltrap.org/node/1735  (Linux: The GPL And Binary Modules)
  https://www.linuxfromscratch.org/lfs/view/10.1/chapter09/udev.html
  http://www.learningaboutelectronics.com/Articles/Linux-kernel-module.php
  https://www.linuxfordevices.com/tutorials/linux/loadable-kernel-modules-linux
  https://man7.org/linux/man-pages/man5/modules-load.d.5.html
  https://www.cs.huji.ac.il/labs/parallel/linux2010/10_Kernel_modules.pdf
   http://www.cs.uni.edu/~diesburg/courses/cop4610_fall10/week06/week6.pdf
  https://www.embeddedrelated.com/showarticle/1274.php
  https://www.iitg.ac.in/asahu/cs421/books/LKM2.6.pdf
  http://lkw.readthedocs.io/en/latest/doc/03_kernel_modules.html  (有源码)
http://www.ouah.org/LKM_HACKING.html   -黑客、病毒编码人员和系统管理员的权威指南
https://community.nxp.com/t5/i-MX-Processors/Compile-kernel-module-with-static-library-a-problem/td-p/957632

http://linuxtesting.org/static-vs-dynamic  介绍动态和静态模块
https://connecttech.com/resource-center/kdb271-making-sense-linux-release-numbers-kernel-revisions/
https://unix.stackexchange.com/questions/337833/what-does-45-el7-mean-in-httpd-2-4-6-45-el7
https://tournasdimitrios1.wordpress.com/2011/02/07/passing-parameters-to-the-kernel-at-run-time-time-on-linux/

 

posted @ 2023-03-14 09:32  jinzi  阅读(21)  评论(0编辑  收藏  举报