内核的设计有两种方式:单内核和微内核,两者各有优劣,关于两者的比较可以参见wiki.windowds和Solaris采用微内核结构.
Linux内核采用单内核结构,设计比较简单,但单内核的理念是把所有的功能集成到一块儿,所以必然会导致内核的体积变大,然而事实是Linux内核体积并不大.因为Linux在设计的时候借鉴了微内核的设计思想,将内核模块化,用到的功能模块在使用的时候再加载.然而这又导致了一个问题,万一内核中没有对应硬盘的驱动模块,那么内核将无法在硬盘上展开,为了解决这个问题设计了一个过度的产物initrd,其中rd就是ram disk的意思,用于顺利将内核展开到硬盘上,等完成任务后就退出,然后内核可以根据系统需要装载相应的模块.
在我的debian8系统上,"/lib/modules/内核版本号"这个目录下保存了所有的以.ko结尾的内核模块,共183MB,需要的时候可以加载对应的模块,而内核文件保存在/boot目录下,只有3MB大小.所以真正的内核是由"内核核心"和"内核模块"两部分组成的,核心位于/boot/vmlinuz-version,各内核模块(.ko)位于/lib/modules/version.
内核在初始化的过程中会完成下个任务:
1.设备探测
2.驱动初始化,可能会从initrd 文件中装载驱动模块,从这个角度看initrd可以看成一个临时的linux系统,这个临时系统系统中集成了比较全的硬件驱动(在我的dbeian8上 initrd.img-3.16.0-4-amd64有16MB大)可以顺利地帮内核完成对即将要展开系统的硬盘的初始化,当它的使命完成之后就退出.
3.以只读方式挂载根文件系统.
4.装载第一个用户空间进程init进程,PID为1,在不同的系统上可能略有不同,主要有upstart和systemd等.
用户空间想要和内核空间打交道可以通过/proc 和 /sys 这两个伪文件系统,所谓伪文件系统是指这两个目录下的文件都是假的,我曾经尝试用vim编辑这下面的文件,结果提示错误.所以这两个目录下的文件实际上是一些内核参数,文件本省并不存在.而且大部分文件是只读的.然而/proc/sys这个目录下的文件是可写的,但是要用echo > /proc/sys/filename的方式修改内核参数.例如,我可以修改/proc/sys/net/ipv4/ip_forward 为1,开启数据包转发功能,echo 1 > ip_forward,这种方式比较麻烦,其实有一个系统管理工具sysctl(configure kernel parameters at runtime)可以方便地修该内核参数,具体使用方法参见man手册,比如修改/proc/sys/kernel/hostname 可以用sysctl kernel.hostname=asen修改主机名,这种方式会立即生效,但是重启之后又会失效.若要永久保存则需要编辑/etc/sysctl.conf文件增加一行参数,这个文件提供了一些范例可供参考,但这种方式的缺点是重启之后可以永久生效但现在无法生效,一个办法是用sysctl -p通知内核重新读取配置文件. sysct命令后面的参数其实就是对应的/proc/sys目录下的路径和文件,sysctl -a 可以显示所有内核参数和值.
内核模块的管理的几个常见命令:
modprobe MODULE_NAME 装载某模块
modprobe -r MODULE_NAME 卸载某模块
modinfo MODULE_NAME 查看某模块的具体信息,包括模块的依赖关系
lsmod 列出当前内核上已经装载的模块
insmod /PATH/TO/ MODULE_NAME 装载某模块
rmmod MODULE_NAME 卸载某模块