Linux内核简单知识点
一、 基础概念
内核的功能:进程管理、内存管理、网络管理、驱动程序、文件系统、安全功能
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=VALUE
,sysctl
命令设定参数格式比较特殊,要以/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
是运行在用户空间的进程,它的专用工具有udevadmin
、hotplug
。udev
创建设备文件时,命名法则会基于事先定义好的规则文件,一般在/etc/udev/rules.d
及/usr/lib/udev/rules.d
目录
三、 内核的编译
通过对内核模块的增删完成内核编译,自定义一个与自身需求相匹配的内核。不过,如果仅仅是对功能的增删,不能对内核源代码进行改进实现内核定制,这种带来的意义也不是特别大。所以,在没有修改源代码能力的前提下,还是不建议自行编译内核使用的
1. 编译内核的前置条件
- 准备好开发环境
- 获取目标主机的硬件设备相关信息
- 了解目标主机将来需要完成的工作
- 获取内核源代码包
2. 一次内核编译的过程
|
3. 配置内核编译参数的其他方式
make config
:基于命令行,以遍历的方式去配置内核编译参数make menuconfig
:基于curses的文本窗口界面对内核参数进行编译make gconfig
:基于GTK开发环境的窗口配置方式make xconfig
:基于QT开发环境的窗口配置方式oldconfig
:基于现有的config文件完成编译make depconfig
:内核为每一种硬件平台都提供了默认配置,此选项就是基于内核对目标平台提供的默认配置进行编译make allnoconfig
:所有选项均回答为nomake 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]
|
2. lsmod命令
显示内核装载的模块,与/proc/modules
文件中的一致,返回信息当中会显示模块的名称、模块的大小、被调用的次数和正被谁使用
3. modinfo
显示模块的详细信息
命令用法:modinfo [-k kernel] [mod_name | mod_file]
|
|
4. modprobe命令
装载、卸载模块
命令格式:modprobe [mod_name]
|
5. depmod命令
内核模块依赖关系文件及系统信息映射文件生成工具,比如在/lib/modules/Version/modules.dep
文件,它就是保存着模块中的依赖关系,但这个文件没有被真正使用,而真正使用的是这个文件的二进制版本modules.dep.bin
。或者是/boot
目录中,有个System.map-Version
文件,用来保存内核文件的映射关系,而这些都是depmod
命令生成的
6. insmod命令
装载模块的命令,但是它不会将被装载模块所依赖的模块装载,必须手动解决依赖关系,并且必须明确指定模块的绝对路径
命令格式:ismod [filename]
7. rmmod命令
卸载模块命令
命令格式:rmmod [option]