一、linux内核剖析
1、“内核”指的是一个提供硬件抽象层、磁盘及文件系统控制、多任务等核心功能的系统软件,是整个操作系统的最底层。linux内核的功能有:进程管理、文件系统、硬件驱动、内存管理、安全功能(SELinux)、网络子系统
2、内核设计流派
①单内核体系:单内核是个很大的进程,它的内部又能够被分为若干模块。但是在运行的时候,它是作为一个整体的大进程;其模块间的通信是通过直接调用其他模块中的函数实现的,而不是消息传递。如linux
Linux内核:核心 + 外围模块
核心:/boot/vmlinux-VERSION-release
模块:/lib/modules/VERSION-release
*.ko: kernel object
ramdisk:/boot/initramfs-VERSION-release.img(在内核启动过程中装载根文件系统时有用)
②微内核体系:在微内核中,大部分内核都作为单独的进程在特权状态下运行,他们通过消息传递进行通信。在典型情况下,每个概念模块都有一个进程。如Windows,Solaric
3、linux内核具有模块化的特性,应此在编译核心时,无须将全部功能都放于内核本体,可将这些功能编译成一个个单独的模块,需要时再分别载入
编译进内核本体 [*]
编译成内核模块 [M]
不选择使用 [ ]
4、内核模块管理
lsmod:显示内核已装载模块
modprobe -l:显示可用模块
动态装卸载模块:
装载:modprobe MOD_NAME 或 insmod /path/to/module_file
卸载:modprobe -r MOD_NAME 或 rmmod MOD_NAME
查看某模块详细信息:
modinfo MOD_NAME
模块之间也可能有依赖关系,装载某模块需要先装载其依赖的模块
depmod:分析可加载模块的依赖关系,生成modules.dep文件和映射文件,这两个文件位于/lib/modules/VERSION-release目录下
[root@node2 ~]# lsmod Module Size Used by autofs4 26513 3 8021q 25349 0 garp 7152 1 8021q stp 2218 1 garp #stp被garp使用,即garp依赖stp llc 5546 2 garp,stp ipt_REJECT 2351 2 nf_conntrack_ipv4 9506 2 nf_defrag_ipv4 1483 1 nf_conntrack_ipv4 iptable_filter 2793 1 ip_tables 17831 1 iptable_filter ip6t_REJECT 4628 2 nf_conntrack_ipv6 8748 2 nf_defrag_ipv6 11182 1 nf_conntrack_ipv6 xt_state 1492 4 nf_conntrack 79758 3 nf_conntrack_ipv4,nf_conntrack_ipv6,xt_state ip6table_filter 2889 1 ip6_tables 18732 1 ip6table_filter ipv6 317340 153 ip6t_REJECT,nf_conntrack_ipv6,nf_defrag_ipv6 microcode 112685 0 ppdev 8537 0 vmware_balloon 7199 0 snd_ens1371 21587 0 ... [root@node2 ~]# modprobe -r snd_ens1371 [root@node2 ~]# lsmod | grep 'snd_ens' [root@node2 ~]# modprobe snd_ens1371 [root@node2 ~]# lsmod | grep 'snd_ens' snd_ens1371 21587 0 snd_rawmidi 23017 1 snd_ens1371 snd_ac97_codec 124967 1 snd_ens1371 snd_pcm 87409 2 snd_ens1371,snd_ac97_codec snd 70569 7 snd_ens1371,snd_rawmidi,snd_ac97_codec,snd_pcm,snd_seq,snd_seq_device,snd_timer [root@node2 ~]# modinfo ppdev filename: /lib/modules/2.6.32-431.el6.x86_64/kernel/drivers/char/ppdev.ko alias: char-major-99-* license: GPL srcversion: 72666B19847D704839BC900 depends: parport vermagic: 2.6.32-431.el6.x86_64 SMP mod_unload modversions [root@node2 ~]# rmmod ppdev [root@node2 ~]# lsmod | grep 'ppdev' [root@node2 ~]# insmod /lib/modules/2.6.32-431.el6.x86_64/kernel/drivers/char/ppdev.ko [root@node2 ~]# lsmod | grep 'ppdev' ppdev 8537 0 parport 36209 2 ppdev,parport_pc [root@node2 ~]# ls /lib/modules/2.6.32-431.el6.x86_64/ build modules.alias modules.ccwmap modules.drm modules.isapnpmap modules.ofmap modules.seriomap modules.usbmap vdso extra modules.alias.bin modules.dep modules.ieee1394map modules.modesetting modules.order modules.symbols source weak-updates kernel modules.block modules.dep.bin modules.inputmap modules.networking modules.pcimap modules.symbols.bin updates [root@node2 ~]# ls /lib/modules/2.6.32-431.el6.x86_64/kernel arch crypto drivers fs kernel lib mm net sound
5、查看内核版本
uname:打印当前系统相关信息(内核版本号、硬件架构、主机名称和操作系统类型等)
用法:uname [option]
常用选项:
-a:显示全部信息
-m:显示机器名
-r:显示内核版本
-i:显示硬件架构
-n:显示在网络上的主机名
-s:显示内核名
不加任何选项当于uname -s
[root@node2 boot]# uname Linux [root@node2 boot]# uname -r 2.6.32-431.el6.x86_64 [root@node2 boot]# uname -i x86_64
二、内核参数配置
1、linux系统上有两个伪文件系统:/proc和/sys。
/proc存储的是当前内核运行状态映射的一系列特殊文件,用户可通过这些文件查看硬件和进程的信息,还可更改某些文件来改变内核运行状态。
只读文件:输出统计信息
读写文件:设定内核工作特性,一般位于/proc/sys目录下,不允许使用文本编辑器进行编写,而只能使用重定向的方式或使用专用的工具,例如 echo 1 > /proc/sys/vm/drop_cathes
几个常用参数:
kernel.hostname
vm.drop.caches:释放缓存
net.ipv4.icmp_echo_ignore_all:可屏蔽别人ping你的主机
net.ipv4.ip_forward:决定主机是否可路由
[root@node2 ~]# ls /proc 1 1266 1352 1493 16 1778 2116 28 33 4 50 8 buddyinfo dma ioports kpagecount mounts schedstat sysrq-trigger vmstat 10 1272 1393 15 17 18 2150 29 34 40 51 85 bus driver ipmi kpageflags mpt scsi sysvipc zoneinfo 11 1285 1399 1506 171 19 22 297 35 41 52 9 cgroups execdomains irq loadavg mtd self timer_list 1173 13 14 1508 172 2 23 298 36 42 54 914 cmdline fb kallsyms locks mtrr slabinfo timer_stats 1198 1316 1420 1510 1727 20 24 3 37 43 55 915 cpuinfo filesystems kcore mdstat net softirqs tty 12 1317 1440 1512 173 2032 25 30 38 44 6 954 crypto fs keys meminfo pagetypeinfo stat uptime 1241 1342 1470 1514 176 2036 26 31 383 45 7 acpi devices interrupts key-users misc partitions swaps version 1256 1351 1481 1516 177 21 27 32 39 5 763 asound diskstats iomem kmsg modules sched_debug sys vmallocinfo [root@node2 ~]# ls /proc/sys abi crypto debug dev fs kernel net vm [root@node2 ~]# ls /proc/sys/net core ipv4 ipv6 netfilter nf_conntrack_max unix
2、修改内核参数的方法:
①echo "XXX" > /proc/sys/
②sysctl -w VARAIABLE=VALUE
sysctl -a:显示sysctl可控制的所有参数
sysctl VARAIABLE:查看指定参数
sysctl -p:重读配置文件并生效之
sysctl的配置文件:/etc/sysctl.conf,在此配置文件中修改内核参数不会立即生效,但会永久有效
[root@node2 ~]# cd /proc/sys [root@node2 sys]# cat net/ipv4/ip_forward 0 [root@node2 sys]# echo 1 > net/ipv4/ip_forward #开启ip报文转发功能 [root@node2 sys]# cat net/ipv4/ip_forward 1 [root@node2 sys]# sysctl -w !$=0 #关闭ip报文转发 sysctl -w net/ipv4/ip_forward=0 net.ipv4.ip_forward = 0 [root@node2 sys]# sysctl -a #显示所有sysctl可控的参数并显示其当前值 kernel.sched_child_runs_first = 0 kernel.sched_min_granularity_ns = 2000000 kernel.sched_latency_ns = 10000000 kernel.sched_wakeup_granularity_ns = 2000000 kernel.sched_tunable_scaling = 1 ... ... net.ipv6.mld_max_msf = 64 net.nf_conntrack_max = 31636 net.unix.max_dgram_qlen = 10 abi.vsyscall32 = 1 crypto.fips_enabled = 0 [root@node2 sys]# vim /etc/sysctl.conf # Kernel sysctl configuration file for Red Hat Linux # # For binary values, 0 is disabled, 1 is enabled. See sysctl(8) and # sysctl.conf(5) for more details. # Controls IP packet forwarding net.ipv4.ip_forward = 1 #为安全起见,默认为0,此处将其改为1 # Controls source route verification net.ipv4.conf.default.rp_filter = 1 # Do not accept source routing net.ipv4.conf.default.accept_source_route = 0 # Controls the System Request debugging functionality of the kernel kernel.sysrq = 0 # Controls whether core dumps will append the PID to the core filename. # Useful for debugging multi-threaded applications. kernel.core_uses_pid = 1 # Controls the use of TCP syncookies net.ipv4.tcp_syncookies = 1 ... [root@node2 sys]# sysctl -a | grep 'net.ipv4.ip_forward' net.ipv4.ip_forward = 0 [root@node2 sys]# sysctl -p #重读配置文件 net.ipv4.ip_forward = 1 net.ipv4.conf.default.rp_filter = 1 net.ipv4.conf.default.accept_source_route = 0 kernel.sysrq = 0 kernel.core_uses_pid = 1 net.ipv4.tcp_syncookies = 1 error: "net.bridge.bridge-nf-call-ip6tables" is an unknown key error: "net.bridge.bridge-nf-call-iptables" is an unknown key error: "net.bridge.bridge-nf-call-arptables" is an unknown key kernel.msgmnb = 65536 kernel.msgmax = 65536 kernel.shmmax = 68719476736 kernel.shmall = 4294967296 [root@node2 sys]# sysctl net.ipv4.ip_forward #可看到,重读配置文件后,对参数的修改已生效 net.ipv4.ip_forward = 1
3、/sys:跟/proc一样是个伪文件系统,存放着由内核的驱动程序所探测到的硬件设备相关信息
Linux 2.4-:/dev所有设备文件都是事先预置;
Linux 2.6+:/dev下所有设备文件能够按需创建;用户空间的某应用程序可根据/sys中信息来为每个设备按需创建设备文件
udev:用户空间的程序,用于创建所需要的设备文件,udevadmin
udev创建设备文件是根据udev规则进行,规则文件在/etc/udev/rules.d/下(我们可通过修改规则文件改变设备文件名,一个典型的例子就是 给克隆的虚拟机修改网卡名称,具体过程见下方示例)
hotplug(热插拔):该程序会即时监控/sys目录,一旦发现有设备增减,即通知udev增减相应的设备文件
当然,我们也可使用mknod命令手动创建设备文件
※示例:给克隆的虚拟机修改网卡名称
克隆的虚拟机会自动生成一个与原主机物理地址不同的新网卡,且将其命名为eth1,为了管理的方便,一般将其改为eth0。克隆虚拟机的过程这里不作赘述,以下为在克隆机上所做的操作:
①修改udev中关于网络设备的规则文件
vim /etc/udev/rules.d/70-persistent-net.rules
②修改接口配置文件
vim /etc/sysconfig/network-scripts/ifcfg-eth0
③重新装载网卡驱动模块
modprobe -r e1000
modprobe e1000
④修改其它一些参数,例如将主机名改为node2
# vim /etc/sysconfig/network
HOSTNAME=node2
# hostname node2
三、内核编译安装
1、为什么要编译内核?
可以使用新内核的功能
按需定制,可精简内核
对于较新的硬件,有些老内核没有相应的驱动
2、linux内核官网:https://www.kernel.org
3、前提:查看本地硬件信息,以便选择要编译的驱动
①查看CPU信息
cat /proc/cpuinfo
x86info (yum install x86info)
lscpu
②查看PCI:
lspci [-v]
③查看USB:
lsusb
④查看块设备:
lsblk
常用选项:
-f:显示文件系统信息
-m:显示权限信息
[root@node2 ~]# lscpu Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Little Endian CPU(s): 2 On-line CPU(s) list: 0,1 Thread(s) per core: 1 Core(s) per socket: 2 Socket(s): 1 NUMA node(s): 1 Vendor ID: GenuineIntel CPU family: 6 Model: 69 Stepping: 1 CPU MHz: 2593.996 BogoMIPS: 5187.99 Hypervisor vendor: VMware Virtualization type: full L1d cache: 32K L1i cache: 32K L2 cache: 256K L3 cache: 4096K NUMA node0 CPU(s): 0,1 [root@node2 ~]# lspci 00:00.0 Host bridge: Intel Corporation 440BX/ZX/DX - 82443BX/ZX/DX Host bridge (rev 01) 00:01.0 PCI bridge: Intel Corporation 440BX/ZX/DX - 82443BX/ZX/DX AGP bridge (rev 01) 00:07.0 ISA bridge: Intel Corporation 82371AB/EB/MB PIIX4 ISA (rev 08) 00:07.1 IDE interface: Intel Corporation 82371AB/EB/MB PIIX4 IDE (rev 01) 00:07.3 Bridge: Intel Corporation 82371AB/EB/MB PIIX4 ACPI (rev 08) 00:07.7 System peripheral: VMware Virtual Machine Communication Interface (rev 10) 00:0f.0 VGA compatible controller: VMware SVGA II Adapter 00:10.0 SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01) 00:11.0 PCI bridge: VMware PCI bridge (rev 02) 00:15.0 PCI bridge: VMware PCI Express Root Port (rev 01) 00:15.1 PCI bridge: VMware PCI Express Root Port (rev 01) ... 02:00.0 USB controller: VMware USB1.1 UHCI Controller 02:01.0 Ethernet controller: Intel Corporation 82545EM Gigabit Ethernet Controller (Copper) (rev 01) 02:02.0 Multimedia audio controller: Ensoniq ES1371 [AudioPCI-97] (rev 02) 02:03.0 USB controller: VMware USB2 EHCI Controller
4、编译内核的步骤
①安装好开发环境
Development Tools, Server Platform Development, ncurses-devel(提供字符终端处理符,包括面板和菜单)
②获取源代码,展开到指定目录下
tar xf linux-3.10.10.tar.xz -C /usr/src
cd /usr/src/linux
③配置内核,可使用的命令有:
make config:遍历选择编译内核功能
make allyesconfig:启用全部功能
make allnoconfig
make menuconfig:会启动一个文本界面以方便配置内核
make gconfig(依赖GNome桌面环境及GNome的图形开发环境,gtk2)
make kconfig(依赖KDE桌面环境及KDE的图形开发环境,qt)
配置完成后会在linux目录下生成一个名为 .config 的隐藏文件;另外linux有提供一个/boot/config-VERSION作为模板
④编译
make [-j #] 例如 # make -j 2 表示启动两个线程执行编译,这样可加快编译速度
[make bzimage:仅编译核心]
编译完成后会在arch/boot/目录下生成一个新的内核映像文件bzImage
⑤安装内核模块
make modules_install 安装位置:/lib/modules/VERSION/
⑥安装内核
make install
生成的内核文件为:/boot/vmlinuz-VERSION,并且会自动在grub.conf中自动添加一行新title
■二次编译前的清理操作:
make clean:清理编译的文件,但保留配置文件
make mrproper:移除所有编译生成的文件、配置文件和备份文件
make disclean:完全清理
■将编译生成的文件保存至别处:
方法一:
make O=/path/to/somewhere
方法二:
madir /path/to/somewhere
cd /path/to/somewhere
./configure --ksource /usr/src/linux
■如何只编译内核的部分代码:
①只编译某子目录中的
cd /usr/src/linux
make [SUBDIR=]path/to/dir/(相对路径)
例如:
make SUBDIR=arch/
make drivers/net/
②只编译部分模块
make M=path/to/dir 例如 make M=drivers/net/
③只编译一个模块
make path/to/dir/MOD_NAME.ko
例如 make drivers/net/ethernet/intel/e1000/e1000.ko
■交叉编译(cross-compling):编译程序所在的宿主机平台与其目标运行平台不是同一类平台
make ARCH=arch
获取某arch的可用的默认配置:
make ARCH=arch help 例如:make ARCH=arm acs5k_defconfig
※示例:
[root@node2 ~]# tar xf linux-3.10.10.tar.xz -C /usr/src [root@node2 ~]# cd /usr/src [root@node2 src]# ls debug kernels linux-3.10.10 [root@node2 src]# mv linux-3.10.10 linux [root@node2 src]# cd linux [root@node2 linux]# ls arch COPYING crypto drivers fs init Kbuild kernel MAINTAINERS mm README samples security tools virt block CREDITS Documentation firmware include ipc Kconfig lib Makefile net REPORTING-BUGS scripts sound usr [root@node2 linux]# ls arch alpha arm avr32 c6x frv hexagon Kconfig m68k microblaze mn10300 parisc s390 sh tile unicore32 xtensa arc arm64 blackfin cris h8300 ia64 m32r metag mips openrisc powerpc score sparc um x86 [root@node2 linux]# yum grouplist | grep 'Development' Additional Development Desktop Platform Development Development tools Server Platform Development [root@node2 linux]# rpm -q ncurses-devel package ncurses-devel is not installed [root@node2 linux]# yum -y install ncurses-devel ... [root@node2 linux]# make menuconfig
执行make menuconfig命令后,会出现如下文本界面:
按 Space键 将某功能编译进内核本体[*]、编译成内核模块[M]或取消选定
点击 EXIT 或 连敲两下ESC键 返回
scripts/kconfig/mconf Kconfig # # using defaults found in /boot/config-2.6.32-431.el6.x86_64 # /boot/config-2.6.32-431.el6.x86_64:497:warning: symbol value 'm' invalid for X86_INTEL_PSTATE /boot/config-2.6.32-431.el6.x86_64:565:warning: symbol value 'm' invalid for PCCARD_NONSTATIC /boot/config-2.6.32-431.el6.x86_64:2730:warning: symbol value 'm' invalid for MFD_WM8400 /boot/config-2.6.32-431.el6.x86_64:2731:warning: symbol value 'm' invalid for MFD_WM831X /boot/config-2.6.32-431.el6.x86_64:2732:warning: symbol value 'm' invalid for MFD_WM8350 /boot/config-2.6.32-431.el6.x86_64:2745:warning: symbol value 'm' invalid for MFD_WM8350_I2C /boot/config-2.6.32-431.el6.x86_64:2747:warning: symbol value 'm' invalid for AB3100_CORE configuration written to .config *** End of the configuration. *** Execute 'make' to start the build or try 'make help'. [root@node2 linux]# ls -a #可以看到已生成一个.config文件 . arch .config CREDITS Documentation firmware .gitignore init Kbuild kernel .mailmap Makefile net REPORTING-BUGS scripts sound usr .. block COPYING crypto drivers fs include ipc Kconfig lib MAINTAINERS mm README samples security tools virt [root@node2 linux]# vim .config #这个.config是文本文件,可直接编辑 # # Automatically generated file; DO NOT EDIT. # Linux/x86 3.10.10 Kernel Configuration # CONFIG_64BIT=y CONFIG_X86_64=y CONFIG_X86=y CONFIG_INSTRUCTION_DECODER=y CONFIG_OUTPUT_FORMAT="elf64-x86-64" CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig" CONFIG_LOCKDEP_SUPPORT=y ... [root@node2 linux]# cp /boot/config-2.6.32-431.el6.x86_64 .config cp: overwrite `.config'? y #采用默认配置编译的内核未必可用,通常妥当的做法是以/boot目录下提供的config文件为模板,再做些适当的修改 [root@node2 linux]# make menuconfig ... [root@node2 linux]# screen #内核编译时间较长,保险起见,通常启动一个新屏幕,在新屏幕中执行make -j 2开始编译。按ctrl+a,d将该屏幕隐藏 [detached] [root@node2 linux]# screen -ls There is a screen on: 5601.pts-3.node2 (Detached) 1 Socket in /var/run/screen/S-root. [root@node2 linux]# screen -r [screen is terminating] 编译完成后退出sreen [root@node2 linux]# ls arch/x86_64/boot #编译完成后会生成一个内核映像文件bzImage bzImage [root@node2 linux]# make modules_install #安装内核 ... INSTALL /lib/firmware/edgeport/down3.bin INSTALL /lib/firmware/whiteheat_loader.fw INSTALL /lib/firmware/whiteheat.fw INSTALL /lib/firmware/keyspan_pda/keyspan_pda.fw INSTALL /lib/firmware/keyspan_pda/xircom_pgs.fw DEPMOD 3.10.10 [root@node2 linux]# ls /lib/modules 2.6.32-431.el6.x86_64 3.10.10 build kernel source [root@node2 linux]# make install #安装内核 sh /usr/src/linux/arch/x86/boot/install.sh 3.10.10 arch/x86/boot/bzImage \ System.map "/boot" ERROR: modinfo: could not find module vmware_balloon #提示找不到vmware_balloon模块,其实这个没多大影响 [root@node2 linux]# ls /boot #可以看到boot目录下已生成新版的内核和initramfs了 config-2.6.32-431.el6.x86_64 initramfs-2.6.32-431.el6.x86_64.img symvers-2.6.32-431.el6.x86_64.gz System.map-3.10.10 vmlinuz-2.6.32-431.el6.x86_64 efi initramfs-3.10.10.img vmlinuz-3.10.10 grub lost+found System.map-2.6.32-431.el6.x86_64 [root@node2 linux]# cat /etc/grub.conf # grub.conf generated by anaconda # # Note that you do not have to rerun grub after making changes to this file # NOTICE: You have a /boot partition. This means that # all kernel and initrd paths are relative to /boot/, eg. # root (hd0,0) # kernel /vmlinuz-version ro root=/dev/sda2 # initrd /initrd-[generic-]version.img #boot=/dev/sda default=1 timeout=5 splashimage=(hd0,0)/grub/splash.xpm.gz hiddenmenu title CentOS (3.10.10) #grub.conf中也自动添加了一行新title root (hd0,0) kernel /vmlinuz-3.10.10 ro root=UUID=aa0330af-3681-428c-98e2-ccf2e6f0f686 rd_NO_LUKS rd_NO_LVM LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet initrd /initramfs-3.10.10.img title CentOS (2.6.32-431.el6.x86_64) root (hd0,0) kernel /vmlinuz-2.6.32-431.el6.x86_64 ro root=UUID=aa0330af-3681-428c-98e2-ccf2e6f0f686 rd_NO_LUKS rd_NO_LVM LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet initrd /initramfs-2.6.32-431.el6.x86_64.img