系统管理之系统启动及内核编译


CentOS 5和6的启动流程
服务管理
Grub管理
自制Linux
启动排错
编译安装内核

系统启动流程:

 POST --> 读取BootSequence (BIOS),决定引导次序 -->读取引导设备的Bootloader(MBR grubstage1-->stage1.5/boot/filkeststem--> boot-->/boot/grub.conf/-->磁盘分区上读取 kernel(ramdisk来完成对真正根文件所在设备的加载) -->挂载rootfs(只读)到根设备上 --> 开始运行/sbin/init-->(/etc/inittab /etc/init/*.conf)-->设置默认运行级别-->运行系统初始化脚本,完成系统初始化-->关闭对应级别下需要停止的服务,启动对应级别下需要开启的服务.-->rc.local-->设置登录终端[-->图形终端]

概论

1.linux组成部分:kernel(内核)+rootfs(GUN,根文件系统)
    kernel:进程管理、内存管理、网络管理、驱动程序、文件系统、安全功能
        IPC:Inter process communication
            消息队列,semerphor,shm
            socket
    rootfs:程序和库文件glibc
        程序:二进制执行文件
        glibc:函数集合,function,调用接口
            过程调用:prpcedure,无返回值
            函数调用:function
2.kernel设计流派
    微内核:(monolithic kernel):Linux
        把所有工具集成与同一个程序
    单内核:(micro kernel): Windows, Solaris
        每种功能使用一个单独子系统实现(模块化)

3.Linux内核特点:
    支持模块化: .ko(内核对象)
        如:文件系统,硬件驱动,网络协议等
    支持内核模块的动态装载和卸载
4.linux内核组成部分:
        核心文件: /boot/vmlinuz-VERSION-release  vmlinuz的字母表示内核是压缩文件
            辅助的伪根系统:ramdisk
                启动操作系统,需要驱动,但驱动在根文件系统上,开机时挂载不了根文件系统,就需要一个第三方来辅助,生成一个虚拟的根文件系统,生成专用用户的专用驱动,来加载真正的根文件系统上的驱动.


                CentOS 5: /boot/initrd-VERSION-release.img
                CentOS6,7: /boot/initramfs-VERSION-release.img
        模块文件: /lib/modules/VERSION-release(内核版本号)
            注意:安装多版本的内核,有多个模块目录

5.模块文件目录: /lib/modules/2.6.32-431.el6.x86_64/kernel 
    arch :与平台相关的特有代码(x86 x64)
    crypto  :加密解密的组件
    drivers  :    驱动
    fs  :文件系统
    kernel  :内核追踪用到的组件
    lib  :库
    mm  :内存管理
    net  :网络管理
    sound:声音驱动

6.运行中的系统环境可分为两层:内核空间,用户空间
    用户空间:应用代码(进程或线程)
    内核空间(内核模式):内核代码(系统调用)
        任何应用程序在运行过程中,有可能需要不断发起模式转换,两种空间不断转换.转换的速率决定系统的性能.
7.建议在生产环境里面,将ctrl+alt+del里面重启的快捷键禁用

启动流程

仅适用于MBR类型架构的PC主机

1.centos6启动流程
系统管理之系统启动及内核编译

1.POST加电自检
2.加载BIOS的硬件信息,获取第一个启动设备。
3.读取第一个启动设备MBR的引导加载程序(grub)的启动信息
4.加载核心操作系统的核心信息,核心开始解压缩,并尝试驱动所有的硬件设备。
5.核型执行init程序并获取运行信息。
6.Init执行/etc/rc.d/rc.sysinit文件。
7.启动核心的外挂模块(/etc/modprobe.conf)。
8.Init执行运行的各个批处理文件(scripts).
9.Init执行/etc/rc.d/rc.local.
10.执行/bin/login程序,等待用户登录。
11.登录之后开始以Shell控制主机。
1. POST: Power-On-Self-Test,加电自检,是BIOS功能的一个主要部分。负责完成对CPU、主板、内存、硬盘子系统、显示子系统、 串并行接口、键盘、 CD-ROM光驱等硬件情况的检测。

 post(加电自检) 其实就是按开机键的那个过程,检测你的系统硬件信息 ,通过什么检测(cpu) 什么都不会干,执行事先编排好的指令和程序,cpu从哪加载指令和程序,能从硬盘拿数据吗?去内存拿数据 刚系统初始化过程中内存是空白的,没有数据,  
 这就要求系统自己完成这个的过程,通常内存有两种:ROM RAM ,计算机识别的内存和我们平时说的内存是不一样的 设备寻址时 不光识别物理4G内存条,还有一个低地址空间(BIOS的空间)在主板上有一个ROM芯片,里面嵌入了一段程序,(叫BIOS 基本输入输出系统)程序的作用就是扫描计算机的硬件, 开机过程中计算机会将他的指针指向内存低地址空间    自动在开机过程中CPU的指挥下将某个特殊的硬件的设备内容装在进内存,将BOis中的程序和指令映射进(物理地址空间)ROM 中,cpu就能读取指令,检测设备是否完整不需要任何额外指令,是硬件内置的,这个过程就是加电自检。
 bios 还要完成启动设备的次序决定,决定哪个设备先启动(USB装系统)

    ROM: BIOS, Basic Input and Output System,保存着有关计算机系统最重要的基本输入输出程序,系统信息设置、 开机加电自检程序和系统启动自举程序等。
    RAM: CMOS互补金属氧化物半导体,保存各项参数的设定按次序查找引导设备,第一个有引导程序的设备为本次启动设备

2.bootloader: 引导加载器,引导程序
    从BISO中按次序查找各引导设备,第一个有引导程序的设备即为本次启动要用到的设备.
    程序类型:
        windows: ntloader,仅是启动OS
        Linux:功能丰富,提供菜单,
            LILO: LInux LOader(缺陷:无法支持大硬盘分区)
            GRUB: GRand Unified Bootloader(统一引导加载器)
                centos 5,6: GRUB 0.X: GRUB Legacy(经典版), 各种安卓手机使用
                centos 7:   GRUB 1.X: GRUB2(跟0.X版本比,完全重写)
    功能:提供一个菜单,允许用户选择要启动系统或不同的内核版本;把用户选定的内核装载到内存中的特定空间中,解压、展开,并把系统控制权移交给内核
    MBR:Master Boot Record 
        512字节: 446byts: bootloader; 64byts: 分区表; 2byts: 55AA
            bootloader空间太小,446字符的代码只能实现最基本的功能
    GRUB:
       为向用户提供更好的开机体验,加入开机菜单,开机图片等更多功能,bootloader的小空间不能满足,grub分成三个阶段,第一阶段放在bootloader,bootloader不再直接加载内核,而是加载grub的第二阶段,第二阶段是一个虚拟操作系统,在磁盘分区内,有大的容量.相当于在启动操作系统前,启动一个虚拟操作系统(程序),不受MBR的限定,提供复杂的功能(阵列图,菜单,交互式接口),选定操作系统后,再由第二阶段加载内核文件.在第二阶段之前,还有第1.5阶段,提供文件系统驱动,方便虚拟系统的生成.

       第一阶段: primary boot loader : 1st stage, 1.5 stage
       第1.5阶段 :Partition:filesystem driver,1.5stage 文件系统驱动接口
       第二阶段 :Partition /boot/grub/ : 2nd stage,分区文件

    不支持复杂逻辑的软raid,内核分件只能放在基本磁盘分区上
   UEFI:可扩展固件接口(Extensible Firmware Interface,EFI)是 Intel 为 PC 固件的体系结构、接口和服务提出的建议标准。其主要目的是为了提供一组在 OS 加载之前(启动前)在所有平台上一致的、正确指定的启动服务,被看做是有近20多年历史的 BIOS 的继任者。
   GPT: GUID磁碟分割表(GUID Partition Table,缩写:GPT)其含义为“全局唯一标识磁盘分区表”,是一个实体硬盘的分区表的结构布局的标准。它是可扩展固件接口(EFI)标准(被Intel用于替代个人计算机的BIOS)的一部分,被用于替代BIOS系统中的一32bits来存储逻辑块地址和大小信息的主开机纪录(MBR)分区表。
3.kernel:
    有gurb中选定内核,把内核文件展开后,kernel自身初始化,然后接管系统的控制权,开始完成复杂的操作.
    自身初始化操作(按顺序操作):
        A.探测可识别到的所有硬件设备
        B.加载硬件驱动程序(有可能借助于ramdisk加载驱动)
        C.以只读方式挂载根文件系统(只读挂载,以防内核的错误操作,操作过程出错)
        D.运行用户空间的第一个应用程序: /sbin/init

     init程序的类型:
         CentOS 5之前: SysV init 
            配置文件: /etc/inittab
        CentOS 6: Upstart init (支持并发启动服务)
            配置文件: /etc/inittab(只是定义系统启动级别)
            /etc/init/*.conf(ntOS 7主要使用)
        Ce: Systemd systemd 
            配置文件: /usr/lib/systemd/system, /etc/systemd/system
    ramdisk:
        不在发行版系统光盘上事先存在,而是在装系统后,扫描硬件设备后动态生成的
         内核中的特性之一:使用缓冲和缓存来加速对磁盘上的文件访问
            ramdisk 转换成 ramfs(文件系统) 提高速度
            centos 5: initrd, 创建工具程序: mkinitrd
            CentOS 6,7initramfs,创建工具程序: mkinitrd, dracut
        系统初始化过程:
        POST --> 读取BootSequence (BIOS),决定引导次序 -->读取引导设备的Bootloader(MBR) -->磁盘分区上读取 kernel(ramdisk来完成对真正根文件所在设备的加载) -->挂载rootfs(只读)到根设备上 --> 开始运行/sbin/init( systemd

4.init程序(sbin/init)

centos5:SysV init
    运行级别:为了系-统的运行或维护等目的而设定的机制;
        0-6 :7个级别    
            0:关机 shutdowm
            1:单用户模式(root自动登录), single, 维护模式
            2: 多用户模式,启动网络功能,但不会启动NFS;维护模式
            3:多用户模式,正常模式;文本界面
            4:预留级别;,目前无特别适用目的, 可同3级别
            5:多用户模式(multi user),完全功能模式;图形界面
            6:重启
        默认级别: 3, 5
        切换级别: init #
        查看级别: runlevel ; who -r
   配置文件: /etc/inittab
        每一行定义一种action以及与之对应的process
            id:runlevel:action:process
                id:一个任务的标识符
                runlevels:在哪些级别启动此任务;#,###,也可以为空,表示所有级别
                action:在什么条件下启动此任务
                    wait: 等待切换至此任务所在的级别时运行一次
                    respawn:此任务终止时,就重新启动之
                    initdefault:设定默认运行级别; process省略
                    sysinit:设定系统初始化方式,此处一般为指定/etc/rc.drc.sysinit
                    ca::ctrlaltdel:/sbin/shutdown -t3 -r now
                    process:具体任务 ,通常是应用程序,或脚本,或二进制程序
            例:
                id:3:initdefault:  表示设定默认启动级别(centos6兼容)
                si::sysinit:/etc/rc.d/rc.sysinit 表示所有级别利用/etc/rc.d/rcsysinit设定系统初始化
                l3:3:wait:/etc/rc.d/rc 3 表示当切换到3级别时运行/etc/rc.d/rc脚本,往脚本里传递参数为3,意味着去启动或关闭/etc/rc.d/rc3.d/目录下的服务脚本所控制的服务,不同级别,数字不同.
                6:2345:respawn:/usr/sbin/mingetty tty6(定义终端1-6):表示在2345运行级别启动mingetty指令,给指令传递参数tty1,一旦该程序停止,要自动重启。mingetty会调用login程序,打开虚拟终端的程序,除了minget ty之外,还有诸如getty等
                x:5:respawn:/etc/X11/prefdm -nodaemon 表示在5运行级别启动时,打开图形化终端    
    系统初始化脚本:/etc/rc.d/rc.sysinit,完成后才会启动各种服务
        (1) 设置主机名
        (2) 设置欢迎信息
        (3) 激活udev和selinux
        (4) 挂载/etc/fstab文件中定义的文件系统
         (5) 检测根文件系统,并以读写方式重新挂载根文件系统
        (6) 设置系统时钟
        (7) 激活swap设备
        (8) 根据/etc/sysctl.conf文件设置内核参数
        (9) 激活lvm及software raid设备
        (10) 加载额外设备的驱动程序
        (11) 清理操作

     运行级别的相关服务:
       init在利用/etc/inittab配置文件,进行用户空间系统初始化时,会有关于默认运行级别的定义,当定义好默认运行级别,利于/etc/rc.d/rc.sysinit完成系统
初始化后,就会按照运行级别,来关闭、打开相应级别下的服务

    /etc/rc:规定关闭启动服务机制
         rc脚本接受一个运行级别数字为参数,/etc.rc.d/有rc+运行级别的目录,有K和S开头+运行级别+服务名的文件,每个文件链接/etc/init.d相应的程序文件.
          各种服务的控制脚本程序是存放在/etc/rc.d/init.d/目录下,然后各个对应级别下要关闭或开的程序以软连接的方式存放在/etc/rc.d/rc运行级别.d/目录下
                以K开头的表示要关闭的服务,K##*:关闭优先级,##数字越小,越是优先关闭;依赖的服务先关闭,而后关闭被依赖的;
                以S开头的表示要开启的服务,##*:启动优先级,##数字越小,越是优先启动;被依赖的服务先关闭,依赖别人的服务后启动

                一般是先关闭相关服务后,再开启相关服务

         /etc/rc.d/rc.local 该脚本为正常行级别运行后的最后一个脚本,可以将一些希望开机时自动启动,但又不合适编辑成服务脚本的一些命令或程序,写在该文件中,
单独成行,即可完成开机自动启动;正常级别下,最后启动一个服务S99local没有链接至/etc/rc.d/init.d一个服务脚本,而是指向了/etc/rc.d/rc.local脚本

    对应的文件在/etc/init/control-alt-delete.conf里,可通过/etc/inittab获知其定义信息

  /etc/rc.d/init.d/下的脚本的格式:
     这类脚本都需要在开头注释段标明:一般要接受至少start、stop、restart、status四个参数
         #!/bin/bash
          # crond    start/stop the cron daemon 标明脚本功能 ,此项可以不写 
          # chkconfig:LLL NN MM  标明该服务脚本初始状态下的运行级别,启动优先级,关闭优先级,必须要写
             LLL:自动为on级别
             NN:自动为on的优先级
             MM:自动为OFF的优先级   例:# chkconfig:2345 11 88
         # description:  描述
         功能代码段 …

 /etc/init.d/*(/etc/rc.d/init.d/*)服务脚本执行方式:
        #/etc/init.d/服务脚本 {start/restart/stop/status}
        #service SRV_SCRIPT {start/restart/stop/status}

为了统一管理服务关闭启动,设置服务脚本机制.利用chkconfig命令自动在各级别目录下创建对应的K或S的服务管理链接文件,且可以管理服务脚本的开机启动或关闭等,要想利用chkconfig进行管理,脚本必须要满足上述注释段的要求,然后将脚本放到/etc/init.d/目录下

    chkconfig命令:管控/etc/init.d/每个服务脚本在各级别下的启动或关闭状态;
         查看:chkconfig --list [服务名]
         添加:chkconfig --add 服务名
             SysV的服务脚本放置于/etc/rc.d/init.d (/etc/init.d)
         删除:chkconfig --del 服务名    
         修改执行的连接类型:
             chkconfig [--level LEVELS] name <on|off|reset>
                 --level LEVELS:指定级别,默认为234

动态管理服务  xinetd
   service命令,手动管理服务
   瞬态( Transient)服务被xinetd进程所管理进入的请求首先被xinetd代理
    配置文件: /etc/xinetd.conf、 /etc/xinetd.d/<service>
    与libwrap.so文件链接
    用chkconfig控制的服务:
        chkconfig tftp on

总结(用户空间的启动流程):/sbin/init(/etc/inittab)            
    设置默认运行级别-->运行系统初始化脚本,完成系统初始化-->关闭对应级别下需要停止的服务,启动对应级别下需要开启的服务.-->设置登录终端[-->图形终端]

  centos6:
        init程序:upstart,但依然为/sbin/init,其配置文件:/etc/init/*.conf
            为了兼容centos5,仍然有/etc/inittab,但仅仅是定义系统默认运行级别

系统管理之系统启动及内核编译

        /etc/rcs.conf:定义系统初始化脚本
        /etc/rc.conf:主配置文件,
        /etc/start-tty.conf:定义启动虚拟终端
        /etc/init-system-dbus.conf: 定义启动服务
            注意:*.confwei为upstar风格的配置文件.
        GRUB:完全一样

 centos7:
    init程序:systemd,配置文件:/usr/lib/systemd/system/*,/etc/systemd/system/*
    与centos5,6的开机启动服务相比,centos7开机时不启动任何服务,当访问某种服务时,才会启动服务,不访问的服务保持沉默状态

    完全兼容SycV脚本机制;因此,server命令依然可用,不过,建议使用systemctl命令来控制服务.
        systemctl {start|stop|restart|status} name[.service]
    设定默认系统运行级别:(不再是修改/etc/inittab,此文件指明更改方法)
        命令:systemctl set-default TARGET.target
        查看当期的运行平台: systemctl get-default
        常用的运行平台:
            # multi-user.target: analogous to runlevel 3
            # graphical.target: analogous to runlevel 5
        没有运行级别的概念,为了兼容centos5.6,设定不同的运行平台,来对应0-6的运行级别

2.详解GRUB(BOOT Loader)

grub legacy:主要运行分三个阶段
    stage1(第一阶段):安装在mbr中
    stage1.5(第1.5阶段):存放在mbr之后的扇区中,让stage1中的bootloader能识别stage2所在的分区上的文件系统(否则他是没办法加载第二阶段的)
    stage2(第2阶段):这个就是我们开机能看到提供菜单,让我们能够编辑时的加载界面的那个阶段,第二阶段是存放在磁盘分区上的,一般都在/boot/grub/目录下
    =====以上就是grub的组织格式======

    grub也有配置文件:/boot/grub.conf通常有个符号连接文件在/etc/grub.conf
    配置文件:/boot/grub/grub.conf <-- /etc/grub.conf
    因此当我们系统启动的时候如果要加载grub所在的磁盘时,会读取这个磁盘上的Mbr,从此能加载到stage1,stage1加载完以后会尝试去加载stage1.5,stage1.5阶段读到以后,从而就能够驱动stage2所在的磁盘分区;其实这个磁盘分区上不但有第二阶段,还有内核文件和ramdisk等等,都在这个分区上放置着,这就是为什么grub能够加载内核文件的原因。注意:主板bios必须能够识别硬盘。然后bios才能去加载硬盘上的boot loader,磁盘上boot loader加载完以后就能够直接识别当前主机能识别到的硬盘设备了,但是,硬盘设备能够识别,并不以为着能够识别硬盘中的文件系统,因为文件系统是额外附加的一层软件组织的文件结构。所有要想能够对接某种文件系统,必须要用到文件系统驱动。所谓的stage1.5阶段也就是给grub提供了文件系统驱动,从而grub就能够访问对应的stage2和内核所在的分区了,这通常应该是一个基本磁盘分区,毕竟stage1.5不可能做的过于复杂。所以grub的第二阶段,以及内核以及ramdisk文件通常都会放在一个基本磁盘分区
    stage2及内核等通常放置于一个基本磁盘分区(就是一般的磁盘分区,不是lvm和软raid;因为grub根本就驱动不了逻辑卷)
    功用:
        (1)提供菜单,并提供交互式接口
            e:编辑模式,用于编辑菜单
            c:命令模式,交互式接口(命令行接口)
        (2)加载用户选择的内核或操作系统
            允许用户传递参数给内核
            可隐藏菜单
        (3)    为菜单提供保护机制    
                为编辑菜单进行认证
                为启动内核或操作系统进行认证    

    如何识别硬盘设备:
        (hd#,#)第几块硬盘的第几个分区
            hd#: 磁盘编号,用数字表示;从0开始编号
            #: 分区编号,用数字表示; 从0开始编号
        (hd0,0) 第一块硬盘,第一个分区

grub的命令行接口
    help:获取帮助列表
    help KEYWORD:详细帮助信息
    find (hd#,#)/PATH/TO/SOMEFILE:

系统管理之系统启动及内核编译

    root (hd#,#) 把哪个磁盘设备设定为根设备
    kernel /PATH/TO/KERNEL_FILE: 设定本次启动时用到的内核文件;额外还可添加许多内核支持使用 cmdline参数
        例如: max_loop=100 selinux=0 init=/path/to/init
    initrd /PATH/TO/INITRAMFS_FILE: 设定为选定的内核提供额外文件的ramdisk;必须与内核版本号完全匹配,否则无法被内核装载
    boot: 引导启动选定的内核

cat /proc/cmdline 显示/boot/grub/grub.conf中内核的参数

内核参数文档:/usr/share/doc/kernel-doc-2.6.32/Documentation/kernel-parameters.txt

手动在grub命令行接口启动系统:
    grub> root (hd#,#) 指明根设备
    grub> kernel /vmlinuz-VERSION-RELEASE ro root=/dev/DEVICE(只读方式启动根文件系统)
    grub> initrd /initramfs-VERSION-RELEASE.img 指明ramdisk文件
    grub> boot  引导内核

配置文件: /boot/grub/grub.conf

系统管理之系统启动及内核编译

    default=#: 设定默认启动的菜单项;落单项(title)编号从0开始
    timeout=#:指定菜单项等待选项选择的时长(用户在规定时间内不操作,自动跳过菜单)
    splashimage=(hd#,#)/PATH/TO/XPM_FILE:菜单背景图片文件路径,支持颜色很少
    hiddenmenu:隐藏菜单
    password [--md5] STRING: 启动菜单编辑认证 STRING:加密密码串 重启生效
    title TITLE:定义菜单项“标题” , 可出现多次
        root (hd#,#): grub查找stage2及kernel文件所在设备分区;为grub“根”
        kernel /PATH/TO/VMLINUZ_FILE [PARAMETERS]:启动的内核   ,这里的根是指root指向的第一个硬盘,第一个分区(hd0,0).  
            删除rhgb quiet选项,取消开机图形界面,查看内核启动消息
        initrd /PATH/TO/INITRAMFS_FILE: 内核匹配的ramfs文件
        password [--md5] STRING: 启动选定的内核或操作系统时进行认证
        Max_loop=100 增加loop设备的数量(内核参数)

            独立分区的boot    kernel和initrd 可以写成 (hd0,0)/vimlinuz-
            非独立分区的boot kernrl      (hd0.0)/boot/vimlinuz-


grub加密:
    1.openssl passwd -1 或 指定盐: openssl passwd -salt "weds" -1
    2grub-md5-crypt命令,生成密码串,

     编辑/boot/grub/grub.conf  把生成的密码串放到password字段后 
        #password --md5 $1$8xzRy$xKj1/D5nb.9flfTfSRl5x.

系统管理之系统启动及内核编译

进入单用户模式:(可破解root密码)
    启动系统时,设置其运行级别1
    进入单用户模式:
    (1) 编辑grub菜单(选定要编辑的title,而后使用e命令);
    (2) 在选定的kernel后附加
        1, s, S或single都可以;编辑好敲回车
    (3) 在kernel所在行,键入“ b”命令
安装grub:
    (1) grub-install
        安装grub stage1和stage1_5到/dev/DISK磁盘上,并复制GRUB相关文件到 DIR/boot目录下
        grub-install --root-directory=DIR /dev/DISK
    (2) grub
        grub> root (hd#,#)
        grub> setup (hd#)

系统管理之系统启动及内核编译

3.自制linux系统

1.分区并创建文件系统
        fdisk /dev/sdb
    分两个必要的分区
        /dev/sdb1对应/boot /dev/sdb2对应根 /
        mkfs.ext4 /dev/sdb1
2.挂载boot
    mkdir /mnt/boot
    mount /dev/sdb1 /mnt/boot
3.安装grub
    grub-install --root-directory=/mnt /dev/sdb
4.. 恢复内核和initramfs文件
    cp /boot/vmlinuz-2.6.32-642.el6.x86_64 /mnt/boot/
    cp /boot/initramfs-2.6.32-642.el6.x86_64.img /mnt/boot
5.建立grub.conf文件
    Vim /mnt/boot/grub.conf
        kernel /vmlinuz-2.6.32-642.el6.x86_64 root=/dev/sda2 selinux=0 init=/bin/bash
    chroot /mnt/sysroot
6. 创建一级目录
    mkdir /mnt/sysroot
    mount /dev/sdb2 /mnt/sysroot
    mkdir –pv/mnt/sysroot/{etc,lib,lib64,bin,sbin,tmp,var,usr,sys,proc,opt,home,root,boot,dev,mnt,media}
7. 复制bash和相关库文件

4.救援模式

5.内核 Kernel

centos系统启动流程:POST-->biso-->bootloaer
加电自检后,读取bootloader中某个磁盘的MBR,kernel ,rootfs,init都是bootloader引导.

ldd命令:打印二进制程序文件的依赖库,没有对应文件的库,是真正的二进制程序入口.
    ldd /bin/ls | grep -o "lib[^[:space:]]*"

系统管理之系统启动及内核编译

内核设计体系:单内核,微内核
    linux:单内核,但充分借鉴微内核体系设计的优点:为内核引入了模块化机制
    linux的内核是宏内核架构, 把大部分功能集成在了内核上, 然后又吸取了微内核的优点, 把非必需的驱动做成模块,
    在需要的时候加载至内核中, 由于linux支持的硬件和平台众多, 通用内核通常会具有一些用不上的功能和模块,
    此时就需要工作人员对内核进行定制化编译来达到提升内核运行效率和减少其他驱动出错造成系统错误的机会.

    内核的组成部分:
        kernel:内核核心,一般为bzimage,通常位为/boot目录,一般我们看到这个文件,就说明内核文件没用了,在系统启动时已经被加载过,开机后不在被使用,放在目录里,方便我们后期管理.
        kernel object:内核对象,即内核模块,一般放置于/lib/modules/VERSION-release/.
            A.内核模块与内核核心版本一定要严格匹配;
            B.内核模块化的主要动因:为了能够支持第三方厂商的硬件设备及其驱动程序,可以引进内核模块化的方式设计,这样每一个厂商都可以把自己的设备驱动写成内核模块,当用到这个设备时,单独编译这个内核模块.针对于当前内核的源码树,编译这个模块,并装载到内核上就可以使用了;

            C.在对内核的编译中,定义某个内核的功能,分为三种选择:
                [ ]:N 编译时不启动功能,留空
                [M]:Module 编译成内核模块,用到时临时装载,只占用磁盘空间,不占用内核内存空间
                [*]:Y 直接编译进内核核心,只要内核在,功能就在,不用装载.
            D.内核:动态装载和卸载
                ramdisk:辅助性文件,并非必须,这取决于内核是否能直接驱动rootfs所在的设 备;能直接驱动,ramdisk就不需要;不能驱动,就需要借助ramdisk封装驱动,不仅包括设备的驱动程序,也可以包括设备上的格式化所提供的逻辑设备,比如说lVM,文件系统;如果都编译成模块的话,都可以加载到内核中.
                借助于ramdisk,能加载的驱动,包括为:
                    目标设备驱动,例如:ISCSI设备的驱动
                    逻辑设备驱动,例如:LVM设备的驱动
                    文件系统,例如:XFS文件系统
                ramdksk:是一个简装版的根文件系统;不能作为一个操作系统使用,因为运行在内存中,缺少长久性,所以操作系统必须在持久性存储设备上,这也是做根切换的原因.提供设备驱动,仅仅是为了能够让内核找到真正的根文件系统.
        内核信息查看:
            uname命令:
               -a, --all 全部显示
               -s, --kernel-name 内核名称
               -n, --nodename  节点名称(主机名)    
               -r, --kernel-release  内核发行号
               -v, --kernel-version  内核编译版本号
               -m, --machine   硬件架构类型
               -p, --processor   cpu类型
               -i, --hardware-platform  硬件平台名称
               -o, --operating-system   操作系统类型

系统管理之系统启动及内核编译

        模块信息查看:
             lsmod命令:显示当前内核已加载的模块名,模块大小,被引用次数,被什么模块所引用
                 抽取/proc/modules的信息,lsmod抽取内核自己的输出接口的信息,以人性化的方式输出.
             modinfo命令:显示指定模块文件的详细信息
                    无论模块是否被装载,都可以用modinfo查看,modinfo就是通过获取/lib/modules目录下与当前内核版本同名的目录下的模块原数据文件,加以显示的.模块原数据文件类似于rpm包的元数据数据库,可以支持查询操作,需要专门的命令.每个文件都是经过hash格式编码,文件里面的都是键值对,从中查找数据的性能是O1(恒定)的,衡量一个算法的标准,O1,On,Olocaln.. 

                    选项:
                        -F:只显示指定字段的信息
                        -a:
                        -n:显示文件路径,相当于 -F filename,
                        -k:默认显示当前内核信息,要想显示其他内核的相关模块,使用-k选项指明kernel,和模块名

系统管理之系统启动及内核编译

         模块信息管理:
             modprobe命令:模块动态装载和卸载
                modpobe [-r] mod_name
                模块动态装卸载也可以基于文件实现,-c指明配置文件,默认是/etc/modprobe.d/*.conf文件
                选项:
                    装载模块: modprobe 模块名          被依赖的模块也会被装载
                    卸载模块: modprobe- r 模块名    正在使用的和默认装载的模块千万不要卸载,会影响系统使用

系统管理之系统启动及内核编译

             depmod命令:生成模块依赖关系
                内核模块依赖关系文件及系统信息映射文件的生成工具
                大多数命令选项,不使用;只有在新增模块时,这个模块依赖于其他模块,不得不手动改写模块文件.自己手动执行drpmod命令
                在对另外一个的内核文件生成依赖关系,并且保存文件也不放在/boot目录下,才有必要使用-b,-F,-E 选项指明内核文件,和内核模块
             模块装载和卸载的另一组命令:
                insmod命令:
                    insmod [filename][module options...]
                            filename:模块文件的文件路径,配合modinfo -n 查看模块文件路径

系统管理之系统启动及内核编译

                rmmod命令:
                    rmmod [module_name(模块名)]

系统管理之系统启动及内核编译

        ramdisk文件的管理:
            不是直接生成的,而是由命令管理的
            (1)mkinitrd命令: centos5 但6,7也有连接
                为当前使用中的内核重新制作ramdisk文件
                文件名:
                    centos5:initrd-2.6.32-504.30.3.el6.x86_64kdump.img
                    centos6,7:initramfs-2.6.32-504.30.3.el6.x86_64.img 
                命令格式:
                    mkinitrd [OPTION...] [<initrd-image>] <kernel-version>
                        --with=<module>:除了默认的模块之外需要装载至initramfs中的模块,重新制作ramdisk的重要原因,添加新的模块.
                        --preload=<module>:initramfs所提供的模块需要预先装载的模块;

                    示例: mkinitrd /boot/initramfs-$(uname -r).img $(uname -r)
            (2)dracut命令 centos 6,7
                    较为底层的生成ramdisk文件的工具
                    #dracut  [OPTION...] [<initrd-image>] <kernel-version>
                    示例:dracut /boot/initramfs-$(uname -r).img $(uname -r)

        内核信息输出的伪文件系统:
            /proc/:内核状态和统计信息的输出接口.可以通过各种文件系统直接管理.同时,还提供一个配置接口,/proc/sys;
                参数:
                    只读:信息输出;/proc下以数字命名的目录,只是用来输出某进程的相关信息./例如:/proc/#/*
                    可写:可接受用户指定一个"新值"来实现对内核某功能或特性的配置;写权限只有管理员拥有./proc/sys/
                            专门用来修改用于支持修改其值的参数,从而能够让我们实现配置内核参数的
                    伪文件系统的参数与/proc/sys/目录下的每个文件有映射关系,都相对与/proc/sys/目录而言,每个参数对应着我们所看到的/proc/sys/目录下的每个文件, 文件路径中的斜杠分隔符替换成点号,就成为参数名;
                        示例:net/ipv4/ip_forward相当于net.ipv4.ip_forward

                修改方式:    
                    (1)sysclt命令
                        专用于查看或设定/proc/sys/目录下参数的值
                        命令使用格式:
                            sysclt [options] [variable[=value]]
                                查看:
                                    #sysclt -a 查看全部信息
                                    #sysclt variable 指定参数名称 variable为文件目录的简装路径,以点分隔
                                修改其值:
                                    #sysclt -w variable=value

系统管理之系统启动及内核编译

                    (2)文件系统命令(cat,echo)
                        伪文件系统,不能使用文本编辑器去直接编辑,而应该使用重定向的方式覆盖原值
                        查看:
                            #cat /proc/sys/PATH/TO/SOME_KERNEL_FILE    
                        设定:使用覆盖重定向修改内核参数
                            echo "node1" > /proc/sys/kernel/hostname

系统管理之系统启动及内核编译

                        注意:上述两种方式的设定仅当前内核有效,内核或系统重启,配置失效
                    (3)配置文件
                        有可能是两种文件,
                        centos 5,6: /etc/sysctl.conf 
                        centos7:    /etc/sysctl.d/*.conf 分隔成多段配置
                        修改配置文件,不会立即生效,下次启动系统
                        立即有效:重读此配置文件,通知让sysctl命令重读此文件,并根据此文件的设定,来修改内核参数相关值即可
                            sysctl -p [/PATH/TO/CONFLG_FILE] 从指定文件中加载内核参数的相关设定,默认读取/etc/sysctl.conf,可指定其他文件,但最好在/etc/sysctl.d/目录下.
                内核参数:
                    1.net.ipv4.ip_forward,核心路由转发功能
                    2./proc/sys/vm/drop_caches:回收内存
                        0:
                        1:
                        2:
                    3./proc/sys/kernel.hostname:主机名
                    4./proc/sys/net/ipv4/icmp_exho_ignore_all 忽略别人ping自己,自己可以ping 别人
         /sys/目录:
                挂载的是sysfs:输出内核识别出的各硬件设备的相关属性信息,也有内核对硬件特性的可设定参数;对此些参数的修改,即可定制硬件设备工作特性;
                    [root@Wencx ~]# ls /sys
                    block  bus  class  dev  devices  firmware  fs  hypervisor  kernel  module  power
                    块设备,总线,
                    不同目录,通过不同视角对各设备划分的类别;根据总线划分,根据类别划分等等,另外也会根据某些特殊内容做些不同类的输出,或者说很多文件,很多设备所输出的位置不止一个目录,但是在多个目录下指向的同一个文件或设备.

                对一个linux主机来讲,每一个硬件设备被访问就要有设备文件,设备文件在/dev/目录下,内核怎么知道不同用户会有哪些硬件设备呢?事先不得而知.那应该准备怎样的设备文件来让内核识别呢?不知道的情况下,只能全部列出所有的设备文件,linux内核2.4以后在/dev/目录下有两万多个设备文件,无法预测用户用到哪些设备,所以把用户但凡用到的全创建出来,那么有两个问题?一.用户使用的很少,大多数文件浪费,虽不占用磁盘空间,但文件数量过大,二,没办法通过设备文件判断某个设备的存在./sys/目录在linux2.6内核引入后,使得我们能够按需创建设备文件,意思是说,每一次当内核系统完成自身初始化的时候,它会自动探测识别出每一个硬件设备信息,而后在把设备信息在系统启动完后,在内核初始化完后,在根文件系统挂载后,在重新探测输出到/sys/目录下,有多少硬件都在/sys/目录下显示.但是有些设备没有设备文件,就会临时读取/sys/目录下的设备信息,给它按需创建设备文件.对/dev/目录来说至关重要.

                udev:通过读取/sys/目录下的硬件设备信息按需为各硬件设备创建设备文件.是用户空间程序,不能直接跟硬件打交道,/sys/目录的存在才让udev读取硬件设备信息.专用命令:devadmin,hotplug;

                当根文件挂载完成后,系统初始化已经结束,系统就不会输出硬件信息./sys/目录的存在就会强制内核重新输出一遍内核信息,把内核中的各硬件设备信息输出至/sys/目录下,而这时候udev就会通过读取/sys/目录下的硬件设备信息按需为各硬件设备创建设备文件.

                /dev/目录下许多文件是Udev创建的,还有一些是内核创建的,比如说内核还要识别/sda硬盘,如果不能识别sda硬盘,标识为一个设备的话,怎么挂载设备?为了让设备访问正常,内核自动通过devtmpfs(设备临时文件系统),为每个内核必须用到的设备创建一个设备文件,这些设备文件可以在根文件系统挂载以后,从内核直接移到/dev/目录下,但不是完全移动,剩下的拷到udev,

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

                /etc/udev/rules.d/70-persistent-net.rules文件,更改网卡配置文件的定义,并更改

内核编译

复习:
    内核组成:kernel,kernel object,ramdisk
        kernel:uname
        kernel object:lsmod,modinfo,modprobe,rmmod,depmod
        ramdisk:mkinitrd,dracut
    系统启动流程:
        post-->bootsequence(BISO)-->bootloader MBR(grub)-->kernel(ramdisk)-->rootfs(swith_root)-->/sbin/init(/etc/inittab,/etc/init/*.conf,/usr/lib/system/)-->设定默认运行级别-->系统初始化-->关闭或启动服务-->/etc/rc.local/-->启动终端(图形终端)

    grub:
        1st stage:mbr
        1.5 stage:MBR之后的扇区
        2st stage:磁盘分区上/boot/grub/
    加密:grub编辑功能验证,内核验证

编译概论:

    程序包的编译安装
        ./configure,make ,make install
    内核编译的前提
        开发环境(开发工具,开发库),头文件:/usr/include
    为什么编译呢
        开源:拿到自由程序的源代码,能够自由获取,自由学习,自由修改,自由创建衍生版,自由分发,更多拿到源代码程序是应用,就有了发行版
        发行版:按照自已的理解,以"通用(要能够在某种平台上被绝大所数用户的平台所兼容)"的目标,把各种开源的源代码拿过来,组织成一个完备的操作系统.不同发行版,有不同的收录包.

        当前内核版本低,内核有重大bug,重新定义内核功能.

    前提:
        (1)准备好开发环境 C语言
        (2)获取目标主机上的硬件设备的相关信息.编译内核时要选择驱动,驱动的选择正确与否,决定编译是否成功,编译过程根据硬件平台和选择功能不同,编译时间从20分钟到二个小时不等.内核代码数非常大
        (3)获取目标主机系统功能的相关信息,例如要启动的文件系统
        (4)获取内核源代码包 www.kernel.org
编译过程:
    (1)准备开发环境:
        centos6:
            包组:Development Tools,Server Platform Development
        entos7:
            包组:Development Tools,Server Platform Development,
        注意:必须安装ncurses程序包,通过下面命令查看
            [root@wen-6 ~]# yum list all *ncurses*
    (2)获取硬件信息
        CPU:cpu型号
            #cat /proc/cpuinfo
            #x86info -a (需要安装程序x86info)
            #lscpu
        PCI设备:显卡,网卡,鼠标,键盘
            lspci

系统管理之系统启动及内核编译

            lsusb

系统管理之系统启动及内核编译
lsblk 块设备
系统管理之系统启动及内核编译

       了解全部硬件设备信息(跟win资源观路器类似,通过hal硬件抽象层映射的)
           hal-device    (可能需要额外安装)    
             rpm -q /usr/bin/hal-device 查看安装情况,centos6默认安装 
    (3)获取内核源代码包    
        从kernel.org官方站点下载同主线最新的内核模块, 笔者用的archlinux , 内核版本为4.7.2 下载了最新版本的4.7.3版本的内核源代码进行编译和安装. 编译之前组安装下开发工具(development tools)

系统管理之系统启动及内核编译

        wget https://cdn.kernel.org/pub/linux/kernel/v3.x/linux-3.12.63.tar.xz  从官网下载内核源码包
        tar xvf linux-3.18.41* -C /usr/src  解压源码包至/usr/src
        cd /usr/src     进入/usr/src目录
        ln -sv linux    -3.18.41 linux  (使用链接方式,以防版本更新,链接方便,发支持回滚)  创建源码包链接
        ls /usr/src/linux (内核源码树)
            arch:运行平台 (cpu运行在市面上大部分平台上)
            block:块设备相关内核级代码
            crypto:加密库
            Documentation:帮助文档(最佳学习内核的资料)
            drivers:驱动(按类)
            firmware:固件设备驱动
            fs:文件系统
            include:头文件
            init:init程序
            ipc:进程间通信机制
            kernel:内核核心
            lib:库文件
            mm:内存管理
            net:网络协议栈
            samples:使用示例
            scripts:用到的脚本
            security:安全机制 
            sound:声音设备
            tools:内核自带工具
            usr:
            virt:虚拟化(内核级)

系统管理之系统启动及内核编译

    (4) 配置内核选项(选择其中一种,也可以多种方式联合)必须在/usr/src/linux目录下
            配置内核选项的工具(方式,一共7种)  make help 查看方式
                 支持“更新”模式进行配置:   在已有的.config文件的基础上进行更新操作
                    (a) make config:基于命令行以遍历的方式去配置内核中可配置的每个选项
                    (b) make menuconfig:基于curses的文本窗口界面(最容易理解)
                            必须安装: yum -y install ncurses-devel
                            使用方式:通过键盘进行选择,选项后面有箭头代表有子选项,回车进入,每个选项选*代表编译进内核,M代表编译成模块,不选表示不编译不启用此功能,选择到exit键可以退出.
![](http://i.imgur.com/8rOIleO.png)                            

                    (c) make gconfig:基于GTK (GNOME)环境窗口界面 必须有桌面环境("桌面平台开发"包组)和相应的开发环境
                    (d) make xconfig:基于QT(KDE)环境的窗口界面 必须有桌面环境(KDE)和相应的开发环境
                支持“全新配置”模式进行配置   原有配置全部覆盖
                    (a) make defconfig:基于内核为目标平台提供的“默认”配置为模板进行配置
                    (b) make allyesconfig: 所有选项均回答为“yes“ 用于内核测试
                    (c) make allnoconfig: 所有选项均回答为"no“   用于内核测试
    (5)编译: 
        (1)多线程编译:make [-j #]  编译内核,可使用-j指定编译线程数量,cpu必须多核心,不指定的话,默认只在一个核心上编译.编译顺序按照/usr/sur/linux目录下的文件顺序 
        (2)编译内核的一部分功能:
            (a) 只编译某子目录中的相关代码:
                # cd /usr/src/linux  切换到源码树下
                # make net/wirelese/
            (b) 只编译一个特定的模块:
                # cd /usr/src/linux
                # make net/wirelese/chan.c
                注意:单独编译模块,只能手动复制到定义特定目录的相应目录下,编译好的模块在/lib/modules/内核版本号/kernel/的相关目录下.不能使用make install命令自动复制
                例如:只为e1000编译驱动:
                    #make drivers/net/ethernet/intel/e1000/e1000.ko
        (3)交叉编译:
            如何交叉编译内核:
                目标平台与当前编译操作所在的平台不同;
                # make ARCH=arch_name
                    make ARCH=
            要获取特定目标平台的使用帮助
                # make ARCH=arch_name help
                # make ARCH=arm help
        (4)如何在执行过编辑操作的内核源码树上做重新编译
            需要事先清理操作:
                # make clean:清理大多数编译生成的文件,但会保留config文件和外部模块的编译链接等
                # make mrproper: 清理所有编译生成的文件、 config及某些备份文件
                # make distclean: mrproper、 patches以及编辑器备份文件
            然后在重复以上编译操作,重新编译
      (6)安装内核模块
        make modules_install
    (7)安装内核
        make install
    (8)重启系统,选择新内核即可
        root



    编译内核的过程描述
        (1)准备好开发环境 C语言(建议在非最小化系统下进行,否则开发环境安装出错)
        (2)获取目标主机上的硬件设备的相关信息.编译内核时要选择驱动,驱动的选择正确与否,决定编译是否成功,        编译过程根据硬件平台和选择功能不同,编译时间从20分钟到二个小时不等.内核代码数非常大
        (3)获取目标主机系统功能的相关信息,例如要启动的文件系统
        (4)获取内核源代码包 www.kernel.org
        (5)准备.config 文本配置文件
        (5)make menuconfig 配置内核选项(其中一种做法)
        (6)make [-j #]    编译内核,可使用-j指定编译线程数量,cpu必须多核心,不指定的话,默认只在一个核心上编译.编译顺序按照/usr/sur/linux目录下的文件顺序 
        (7)make modules_install 安装内核模块
        (8)make install 安装内核
        (9)reboot

        注意:如果是远程连接主机编译内核,建议在screen下操作配置内核选项过程
            打开screen:screen
            拆除screen:Crtl+a,d
            列出screen:screen -ls
            连接至screen:screen -r screen_id
            关闭screen:exit
          第一次编译,为了编译成功,可以仿照当前系统的内核选项,来进行设定要编译的内核.要复制一个模板,在/boot/config****.x86下, redhet放在这目录下,可供我们参照.但有些发行版的内核模板是/proc/config.gz.可自动输出.复制这个文件,到内核源码目录下,改名成 .config.打开文件都是内核选项.

    操作示例:
        (1)准备开发环境
            安装必要包组 yum groupinstall

系统管理之系统启动及内核编译

            安装ncurses服务

系统管理之系统启动及内核编译

        (2)获取目标主机的硬件设备信息

系统管理之系统启动及内核编译

        (3)获取内核源码包
            [root@wen-6 src]# wget https://cdn.kernel.org/pub/linux/kernel/v3.x/linux-3.12.63.tar.xz
            [root@wen-6 src]tar xf linux-3.10.67.tar.xz -C /usr/src
            [root@wen-6 src] cd /usr/src
            [root@wen-6 src]ln -sv linux-3.10.67 linux
        (4)准备内核配置模板.config文件(有能力自己配置内核选项,可忽略此步)
            cd /usr/src/linux
            cp /boot/config-$(uname -r) ./.config

系统管理之系统启动及内核编译

        (5)配置内核选项
            make menuconfig

系统管理之系统启动及内核编译
系统管理之系统启动及内核编译

        (6)编译内核( make -j 2)

系统管理之系统启动及内核编译

        (7)安装内核模块
            make modules_install

系统管理之系统启动及内核编译

        (8)安装内核
            make install

系统管理之系统启动及内核编译

        (9)查看内核文件

系统管理之系统启动及内核编译

        (10)重启系统,选择最新内核进入系统
            reboot

系统管理之系统启动及内核编译
系统管理之系统启动及内核编译
系统管理之系统启动及内核编译

原创文章,作者:wencx,如若转载,请注明出处:http://www.178linux.com/46271

(0)
wencxwencx
上一篇 2016-09-13
下一篇 2016-09-13

相关推荐

  • 马哥教育网络22期+第四周作业博客

    1、复制/etc/skel目录为/home/tuser1,要求/home/tuser1及其内部文件的属组和其它用户均没有任何访问权限。    [root@centos-rpi3 skel]# cp -r /etc/skel /home/tuser1 && chmod -R g-rwx,o-rwx /home/tuser1 …

    Linux干货 2016-09-08
  • ContOS 7 安装

    在虚拟机中安装ContOS 7,自定义4个分区
    虚拟机使用ISO镜像文件安装,网络使用桥接模式,内存大小设置为1224MB(安装桌面比较大)

    2018-03-13
  • NFS(Network File System)介绍与应用(双httpd + php-fpm + nfs + mysql 搭建discuz论坛)

    NFS相关介绍 一、NFS简介     1. NFS(Network File System): NFS是一个文件共享协议, 也是是在类Unix系统中在内核中实现的文件系统。      2. 起源: 最早是由SUN公司研发,非常古老,只是实现文件共享,安全控制方面比较简…

    Linux干货 2015-07-21
  • 8.1作业习题

    1,创建testuser uid 1234,主组:bin,辅助组:root,ftp,shell:/bin/csh home:/testdir/testuser useradd -u 1234 -g bin -G root,ftp -s /bin/csh -d /testdir/testuser testuser 2.修改testuser uid:4321,主…

    Linux干货 2016-08-04
  • X-Y Problem

    X-Y Problem 对于X-Y Problem的意思如下: 1)有人想解决问题X2)他觉得Y可能是解决X问题的方法3)但是他不知道Y应该怎么做4)于是他去问别人Y应该怎么做? 简而言之,没有去问怎么解决问题X,而是去问解决方案Y应该怎么去实现和操作。于是乎: 1)热心的人们帮助并告诉这个人Y应该怎么搞,但是大家都觉得Y这个方案有点怪异。2)在经过大量地讨…

    Linux干货 2016-08-15
  • Nginx配置进阶

    目录 ngx_http_rewrite_module模块 ngx_http_gzip_module模块 ngx_http_fastcgi_module模块 ngx_http_ssl_module模块 ngx_http_referer_module模块 ngx_http_rewrite_module模块 将用户某一次请求的URI当中的字符串是不是能够被我们给出…

    Linux干货 2016-11-05