编译内核

了解内核;内核设计体系:单内核,微内核

    linux:单内核设计,但充分借鉴了微内核体系的设计优点;为内核引入了模块化机制;

内核的组成部分一般有三种;

    kernel:内核核心,一般为bzimage (bzip2格式所压缩的内核映像文件),这个文件通常位于/boot/目录下,名称为vmlinuz-VERSION-release;

    kernel object:内核对象,即内核模块,一般放置与/lib/modules/VERSION-release/ 

        注意:内核模块与内核核心版本一定要严格匹配;

编译的时候的内核模块的选择

    [ ]:N :这表示不编译此功能

    [M]:Module:这表示编译为内核模块,编译成内核模块的用处在于,用到时在临时装载,不用时可以不装载,最多只是占用磁盘空间,而不占用内核内存空间

    [*]:Y:这表示直接编译进内核核心;要编译进内核核心的功能必须是最核心的,近乎所有人都用到的功能;但是编译成模块有一个缺陷,因为他支持动态装载和卸载,因此我们一般只能够在用到此模块时还要临时把其转载进来才能用,这中间就产生了一个时间差。如果是要是在内核核心直接提供的话,上来就可以用了。就没有这个时间差了。但是这个时间差几乎可以忽略不计。

    注意:不是所有功能都可以编译成模块的,有些功能要么选择编译进核心,要么不选择,而不支持模块化编译。内核:内核模块支持动态装载和卸载


ramdisk:辅助性文件,并非必须,这取决与内核是否能直接驱动rootfs(根文件系统)所在的设备;

    借助与ramdisk能加载的内容包括;

        目标设备驱动,例如SCSI设备的驱动;

        逻辑设备驱动,例如LVM设备的驱动;

        文件系统,例如xfs文件系统;

    ramdisk是一个简装版的根文件系统;因此内核一旦用到了ramdisk在内存中;那这个时候他起始已经有根了,这个根是位于内存中的根,这个时候如果内核不做根切换动作的话,那这个系统其实就已经启动完成了。但是这样的缺陷就是数据无处存放,万一断电了,数据操作系统和修改的操作系统全部都没了,为了避免这样的尴尬,我们还是应该把操作系统放在一个持久性存储设备上,这就是为什么多数情况下要做根切换的原因,所以说ramdisk仅仅是为了让内核能够找到真正的根文件系统。

注意:在操作系统启动完成以后起始内核就已经加载完成了,我们能看到的内核文件与我们这次启动已经没有关系了,无论怎么修改,其都没有办法生效了。除非重启,不过对于内核4.0版本以后据说可以打补丁,不用重启可以直接让其生效。


内核信息获取:uname命令:显示系统的信息

选项;

    -r:内核的(releace)发行号

    -n:显示当前主机名

    -v:内核的版本号(编译版本)

    -a:显示所有信息

内核模块信息获取和管理:

    lsmod命令:列出模块;显示内容来自于/proc/modules

        有三个字段:模块名称;模块大小;被引用次数以及被什么模块所引用

    modinfo命令:显示单个模块文件的相关信息

        -F field:仅显示指定字段的信息

        -n:显示文件路径

    文件:/boot/vmilnuz-VERSION-release

modprobe命令:从内核中动态装载模块或从内核中卸载模块

    使用格式:modprobe [-r] module_name

    动态装载模块modprobe module_name

    动态卸载模块modprobe -r module_name

    注意:对正在使用中的内存模块,千万不要去随意卸载

    depmod命令:对模块生成依赖关系(内核模块依赖关系文件的生成工具)

模块装载和卸载的另一组命令:

    insmod命令:插入模块

    insmod [filename] [module options]

    filename:模块文件的文件的路径;

    rmmod命令:删除模块

    rmmod [module_name]


ramdisk文件的管理:

(1)mkinit命令

    为当前使用中的内核重新制作ramdisk文件

    # mkinitrd [option…] [<initrd-image>]<kernel-version>

        –with=<module>:除了默认模块之外需要装载至initramfs中的模块,

        –preload=<module>:initramfs所提供的模块需要预先装载的模块;

        示例:]# mkinitrd /boot/initramfs-$(uname -r).img $(uname -r)

(2) dracut命令;较为底层的,用于生成ramdisk文件的命令

    # dracut [option…] [<image> [<kernel version>]]

    示例:]# dracut /boot/initramfs-$(uname -r).img $(uname -r)


内核信息输出的伪文件系统:

    /proc:内核状态及统计信息的输出接口;同时,还提供一个配置接口,这个配置接口是/proc/sys;

    有两种参数:只读和可写

        只读:只用于信息输出;例如/proc/#/*

        可写:作用是可接受用户指定一个“新值”来实现对内核某功能或特性的配置:/proc/sys/

    /proc/sys:

    net/ipv4/ip_forward 相当于 net.ipv4.ip_forward

    那么既然可写,怎么写呢?因为所谓的系统调优操作主要就是改这两个目录,一个是/proc/sys/,一个是/sys/下的很多参数

修改其值的方式有两种;

(1)sysctl命令;专用与查看或设定/proc/sys目录下参数的值

    sysctl [option] [variable[=value]]

    查看:

    # sysctl -a 

    # sysctl variable

    # cat /proc/sys/PATH/TO/SOME_KERNEL_FILE

    修改其值:

    # sysctl -w variable=value

(2)文件系统命令(cat,echo)

    查看:

    # cat /proc/sys/PATH/TO/SOME_KERNEL_FILE

    设定:

    # echo "VALUE" > /proc/sys/PATH/TO/SOME_KERNEL_FILE

    注意:上述两种方式的设定仅当前运行内核有效;

(3)配置文件:/etc/sysctl.conf,/etc.sysctl.d/*.conf

    立即生效的方式:sysctl -p [/PATH/TO/CONFIG_FILE]


内核参数:

net.ipv4.ip_forward:核心转发

vm.drop_caches:回收内存所用的内核参数

kernel.hostname:主机名

net.ipv4.icmp_echo_ignpre_all:忽略所有发往本主机的ping操作

/sys目录:

sysfs:主要用于输出内核识别出的各硬件设备的相关属性信息,也有内核对硬件特性的可设置参数;对此些参数的修改,即可定制硬件设备的工作特性

udev:通过读取/sys目录下的硬件设备信息按需为各硬件设备创建文件;udev是用户空间程序;专用工具(用来创建设备文件):devadmin,hotplug;

udev为设备创建设备文件时,会读取其事先定义好的规则文件,一般在/etc/udev/rules.d/目录下,以及/usr/lib/udev.rules.d/目录下;


如何编译内核:

程序包的编译安装三个步骤:

./configure,make,makeinstall

前提:开发环境(开发工具,开发库),头文件:/usr/include

开源:源代码–>可执行格式

发行版的主要作用:以“通用”的目标;避免让用户去手动编译

前提

(1)准备好开发环境;

(2)获取目标主机上硬件设备的相关信息;为什么要获取硬件设备的相关信息呢?我们编译内核的时候要选择驱动的,如果我们有一个驱动没有选好,编译完了会发现启动不了 ,结果就是得重新启动老版本内核改了内核配置重新编译,而一次编译根据硬件平台所选定的功能不同从二十分钟到两个小时不等,内核代码数是非常大的。

(3)获取到目标主机系统功能的相关信息,例如要启用文件系统;

(4)获取内核源代码包:www.kernel.org

如何准备开发环境:

    centos6:

    包组:

        Development Tools

        Server Platform Development

    centos7:

    包组:

        Development Tools

        Server Platform Development

        注意:确保包组中有安装*ncurses-devel*这个包

获取目标主机上硬件设备的相关信息;

    CPU:

        ~]# cat /proc/info

        ~]# lscpi

        ~]# x86info -a

    PCI设备:

        ~]# lspci

        -v

        -vv

        ~]# lsusb

        -v

        -vv

        ~]# lsblk

了解全部硬件设备信息:

    ~]# hal -device


内核编译过程:

步骤:

获取源代码

~]# tar xf linux-3.10.67.tar.xz -C /usr/src

~]# cd /usr/src

~]# ln linux-3.10.67 linux

~]# cd linux

~]# make menuconfig 配置内核选项

~]# make [-j #(表示多线程同时编译)]:编译内核,可使用-j指定编译线程数量

~]# make modules_install 安装内核模块

~]# make install 安装内核核心

重启系统,选择使用新内核

如果是远程连接执行编译的话建议将下面这几个选项运行在screen命令:

screen命令:

打开screen:~]# screen

拆除screen: Ctrl+a,d

列出screen: ~]# screen -ls

连接至screen: ~]# screen -R SCREEN_ID

关闭screen: ~]# exit

过程详细说明

(1)配置内核选项

  支持“更新”模式进行配置:在已有的.config文件的基础之上进行“修改”配置;

        (a)make cofig:基于命令行以遍历的方式去配置内核中可配置的每个选项

        (b)make menuconfig:基于cureses的文本配置窗口

        (c)make gconfig:基于GTK开发环境的窗口界面;“桌面平台开发”

        (d)make xongfig:基于QT开发环境的窗口界面;

  支持“全新配置”模式进行配置

        (a)make defconfig:基于内核为目标平台提供的“默认”配置为模版进行配置;

        (b)make allnoconfig:所有选项均为“no”

(2)编译

        (a)多线程编译:make [-j #]

        (b)编译内核中的一部分代码;

        (i)只编译某子目录中的相关代码

            # cd /usr/src/linux

            # make path/to/dir

        (ii)只编译一个特定的模块

            # cd /usr/src/linux

            # make path/to/dir/file.ko

        (c)如何交叉编译:

            目标平台与当前编译操作所在的平台不同;

            # make ARCH=arch_name

            如果要获取特点目标平台的使用帮助:

            # make ARCH=arch_name help

(3)如何在执行过编译操作的内核源码树上做重新编译:

    事先清理操作:

        # make clean:清理编译生成的绝大多数文件,但会保留config,及编译外部模块所需要的文件;

        # make mrproper:清理编译生成的所有文件,包括配置生成的config文件及某些备份文件;

        # make distclean:相当于mrproper,额外清理各patches以及编辑器备份文件



示例

安装开发包组

blob.png

获取内核源代码

blob.png

blob.png

blob.png


原创文章,作者:M20-1马星,如若转载,请注明出处:/46190

联系我们

400-080-6560

在线咨询:点击这里给我发消息

邮件:1823388528@qq.com

工作时间:周一至周五,9:30-18:30,节假日同时也值班

友情链接:万达开户  万达招商  万达招商  guoqibee.com  万达娱乐主管QQ  万达娱乐注册  万达开户  万达娱乐平台  万达娱乐注册