一、 基础概念

内核的功能:进程管理、内存管理、网络管理、驱动程序、文件系统、安全功能

1. 内核程序的设计流派

  • 单内核设计:把所有功能集成于同一个程序,而后每一个功能在就在程序内部使用线程来实现,这就是内核线程,这种设计好处在于大家结合的更紧密,效率高,但是问题在于任何一个地方产生故障可能会影响全局,Linux是这种设计
  • 微内核设计:每一个功能都使用一个独立的子系统实现,而后在找一个中央调配协调系统,当我们用到什么功能时,就让这些子系统彼此间通信来完成任务。每一个子系统都独立运作,我们可以用一个松散框架将它们联合在一起,问题就是可能效率低,但每一个子系统出现问题不至于影响全局。不过,话虽如此,目前来看虽然微内核设计在理论上是先进的,但是由于其内部的协调机制过于复杂,使得它的任何优越性基本上没能体现,Windows,Solaris就是这种设计

2. Linux内核特点

  • 支持模块化:Linux也充分借鉴了微内核设计的思想,内部的各种功能都被做成独立的功能模块而不是子系统,子系统里面可能包括很多模块并且拥有自制机制,而内核模块就像用户空间库的概念,不过库是被应用程序调用的,而内核模块只能被内核调用,文件名称都以.ko结尾(kernel object)。通过模块化也使得Linux内核不会变得过于庞大,用到哪个模块功能就装载哪个
  • 支持模块的动态装、卸载:在线装载、卸载模块

3. Linux内核的组成部分

  • /boot/vmlinux-VERSION-release:核心文件,最核心、最基本的文件
  • /lib/modules/VERSION-release:模块文件,目录名称和内核版本号严格匹配,其中存内核模块各类型文件。不过,模块之间也有依赖关系,所以查看目录时也可以看到大量的依赖关系元数据等信息,而真正的内核文件就在子目录./kernel中存放
    /lib/modules/VERSION-release/kernel/arch:平台相关的内容
    /lib/modules/VERSION-release/kernel/crypto:内核中加密解密等安全相关的内容
    /lib/modules/VERSION-release/kernel/drivers:驱动
    /lib/modules/VERSION-release/kernel/fs:文件系统相关内容
    /lib/modules/VERSION-release/kernel/kernel:自己的一些基本核心功能
    /lib/modules/VERSION-release/kernel/lib:各种内核模块用到的库
    /lib/modules/VERSION-release/kernel/mm:内存管理相关内容
    /lib/modules/VERSION-release/kernel/net:网络相关内容
    /lib/modules/VERSION-release/kernel/sound:声音相关内
  • ramdisk:基于内存的磁盘,这个组件不是必须的,主要的功能是帮助内核驱动硬盘

二、内核运行状态信息查看

1. /proc目录

内核把内部状态信息及统计信息以及可配置参数通过伪文件系统输出到此目录,只能通过echo命令或sysctl方式修改大多数参数的值

参数类型

  • 只读参数:仅仅用于输出信息
  • 可写参数:可接受用户指定“新值”来实现对内核某功能或特定的配置,大多数可写的参数一般都在/proc/sys目录中

参数配置

因为/proc是个伪文件系统,所以不可以像编辑文本文件一样配置,应使用echo命令或sysctl命令用于设定或查看此目录中的参数

  • 配置文件:/etc/sysctl.conf
  • 设置某参数:sysctl -w parameter=VALUEsysctl命令设定参数格式比较特殊,要以/proc/sys目录为起点,并且把路径中的斜线改为.具体看下方示例
  • 重读配置文件:sysctl -p [/path/file]
  • 常用参数:
    net.ipv4.ip_forward:核心转发功能
    vm.drop_caches:清理缓存
    kernel.hostname:主机名

配置示例

修改/proc/sys/kernel/hostname的值

  • 方式一:使用sysctl命令
    ~]# sysctl -w kernel.hostname=abc.123.com
    使用sysctl命令需要以/proc/sys路径为起点,直接给定参数名称
  • 方式二:使用echo命令
    ~]# echo ‘123.abc.com’ > /proc/sys/kernel/hostname
    使用echo命令需要给定绝对路径

2. /sys 目录

sysfs伪文件系统挂载在此目录,用于让内核输出硬件的相关参数,有些参数可以修改,用于调整硬件工作特性。
udev命令通过此路径输出的信息动态为各设备创建所需的设备文件,udev是运行在用户空间的进程,它的专用工具有udevadminhotplugudev创建设备文件时,命名法则会基于事先定义好的规则文件,一般在/etc/udev/rules.d/usr/lib/udev/rules.d目录

三、 内核的编译

通过对内核模块的增删完成内核编译,自定义一个与自身需求相匹配的内核。不过,如果仅仅是对功能的增删,不能对内核源代码进行改进实现内核定制,这种带来的意义也不是特别大。所以,在没有修改源代码能力的前提下,还是不建议自行编译内核使用的

1. 编译内核的前置条件

  • 准备好开发环境
  • 获取目标主机的硬件设备相关信息
  • 了解目标主机将来需要完成的工作
  • 获取内核源代码包

2. 一次内核编译的过程

1. 准备开发环境,centos 6.9系统需要安装两个包组Development tools 和Server Platform Development
~]# yum groupinstall Development tools Server Platform Development

2. 查看目标主机的硬件设备信息
~]# lscpu
~]# lspci
~]# lsblk

3. 准备内核源码文件,可以在www.kernel.org中获取,下载后并解压至/usr/src目录
~]# tar xf linux-3.9.tar.xz -C /usr/src
~]# ln -sv /usr/src/linux-3.9/ /usr/src/linux

4. 为了便于编译成功,可以使用当前系统中的内核编译配置文件作为模板,路径为
/boot/config/config-2.6.32-696.el6.x86_64,将这个文件复制为/usr/src/linux/.config
~]# cp /boot/config-2.6.32-696.el6.x86_64 ./.config

5. 调整适用于当前内核的参数,使用make menuconfig命令进入文本窗口,完成配置后保存退出
配置参数时前边中括号的值的取值有
[ ]:N,表示不编译此功能
[*]:Y,把此功能编译进内核
[M]:M,把此功能编译成模块
~]# make menuconfig

6. 开始编译,因为编译工作会占据终端前台,所以最好启动一个虚拟屏幕完成编译
~]# yum install screen
~]# screen
~]# make
当终端断开也没关系,可以使用screen -ls查看任务,接着使用screen 加编号即可恢复
编译完成后安装
~]# make modules_install
~]# make install
重启系统验证

3. 配置内核编译参数的其他方式

  • make config:基于命令行,以遍历的方式去配置内核编译参数
  • make menuconfig:基于curses的文本窗口界面对内核参数进行编译
  • make gconfig:基于GTK开发环境的窗口配置方式
  • make xconfig:基于QT开发环境的窗口配置方式
  • oldconfig:基于现有的config文件完成编译
  • make depconfig:内核为每一种硬件平台都提供了默认配置,此选项就是基于内核对目标平台提供的默认配置进行编译
  • make allnoconfig:所有选项均回答为no
  • make allyesconfig:所有选项均回答为yes

4. 编译一部分功能

编译操作使用make命令即可完成,如果想加快速度可以使用make -J #指定同时编译的核心数。但是有时编译完成后,会发现有个功能忘记编译了,此时没必要完全从新编译,就可以使用部分编译

  • 只编译某个目录的代码进内核
    进入内核源码目录:cd /usr/src/linux
    执行编译:make some_dir/

  • 只编译特定模块
    进入内核源码目录:cd /usr/src/linux
    执行编译:make some_dir/file.ko
    编译完成后使用cp命令将file.ko复制至/lib/modules对应的目录下即可

5. 交叉编译

编译的目标平台与当前平台不相同,可查询目标平台的使用帮助make ARCH=arch_name help,然后根据帮助使用命令make ARCH=arch_name即可

6. 同目录中二次编译

同目录中如果想二次编译,一定会存在第一次编译时很多编译结果,可以使用以下方式进行源码树清理
make clean:移除所有生成的文件,仅保留config文件和自行补丁代码
make mrproper:移除所有编译生成的文件+config文件+备份文件
make distclean:移除所有,相当于刚解压源代码的状态

7. screen命令

因内核编译时间较长,当终端挂了,编译工作也就挂了,这时就可以用screen命令打开一个虚拟屏幕,在上面执行编译操作,它会剥离于当前终端的关系
ctrl + a,d:剥离当前screen与终端的关系
screen -ls:查看打开的screen
screen -r #:恢复某个screen

四、内核相关命令

1. uname命令

命令格式:uname [option]

option
-a:显示所有信息
-s:显示内核名称
-r:显示内核版本
-n:显示节点名称
-v:显示内核制作版本信息
-m:显示当前内核支持的硬件平台
-p:显示处理器类型
-i:显示硬件平台架构
-o:显示操作系统

2. lsmod命令

显示内核装载的模块,与/proc/modules文件中的一致,返回信息当中会显示模块的名称、模块的大小、被调用的次数和正被谁使用

3. modinfo

显示模块的详细信息
命令用法:modinfo [-k kernel] [mod_name | mod_file]

option
-k kernel:如果系统中有多个内核,此选项可以指定显示某个内核的模块信息
-n:只显示模块名称
-a:只显示作者
-p:只显示模块参数
-d:只显示模块描述
filename:       /lib/modules/3.10.0-1062.el7.x86_64/kernel/fs/ext4/ext4.ko.xz
license: GPL
description: Fourth Extended Filesystem
author: Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others
alias: fs-ext4
alias: ext3
alias: fs-ext3
alias: ext2
alias: fs-ext2
retpoline: Y
rhelversion: 7.7
srcversion: E8D131800079B8E4D30649E ## 源码版本
depends: mbcache,jbd2 ## 依赖到哪些模块
intree: Y
vermagic: 3.10.0-1062.el7.x86_64 SMP mod_unload modversions
signer: CentOS Linux kernel signing key
sig_key: 51:08:4E:41:88:03:02:BE:5C:B0:74:AC:0D:A3:FE:10:23:3B:7F:1C
sig_hashalgo: sha256

4. modprobe命令

装载、卸载模块
命令格式:modprobe [mod_name]

-r:卸载模块
-n:干跑模式
-q:静默模式
-C config_file:指定模块的配置文件,默认为/etc/modprobe.conf和/etc/modprobe.d/*.conf

5. depmod命令

内核模块依赖关系文件及系统信息映射文件生成工具,比如在/lib/modules/Version/modules.dep文件,它就是保存着模块中的依赖关系,但这个文件没有被真正使用,而真正使用的是这个文件的二进制版本modules.dep.bin。或者是/boot目录中,有个System.map-Version文件,用来保存内核文件的映射关系,而这些都是depmod命令生成的

6. insmod命令

装载模块的命令,但是它不会将被装载模块所依赖的模块装载,必须手动解决依赖关系,并且必须明确指定模块的绝对路径
命令格式:ismod [filename]

7. rmmod命令

卸载模块命令
命令格式:rmmod [option]