Linux内核升级

显示全文:

Linux内核的简介:

linux操作系统是一个用来和硬件打交道同时为用户程序提供一个有限服务集的低级支撑软件。内核提供了底层硬件的驱动,以及提供各种系统所需的核心功能,包括防火墙机制,是否支持LVM或Quota等文件系统等。

为什么要进行linux内核的升级?

大部分情况下,我们可以不对内核进行太大改变,直接使用现有的内核,因为它已经可以提供给我们基本的功能,但现在的硬件升级速度太快了,如果核心太老,而机器又换了新的硬件,那么这个核心肯定是无法支持,当然我们也可以将新硬件的驱动做成模块化安装,现实情况也是这么做的。但我们不可能把内核所有支持的功能都编译进内核来支持所有硬件运行工作。我们可以通过编译内核,针对linux的用途加载不同的功能,让linux跑的更稳定,更流畅,这也是我们要编译核心的最主要原因。

内核的两个模块:

核心  :/boot/vmlinuz-version
内核模块: /lib/modules/version/

内核设计的两种风格:

单内核:linux(采用微内核的设计思想,引用模块化设计)。

微内核:在微内核中,大部分内核都作为单独的进程在特权状态下运行,他们通过消息传递进行通讯。
linux下装载模块的命令:
insmod
modprobe
linux下查看当前系统的内核版本
[root@www boot]# uname -r
2.6.32-431.el6.x86_64
主 次 修正  次修正号

次版本号为偶数表示稳定版,
修正:修正bug
次修正:添加新特性。

用户空间的访问,监控内核的方式:
/proc, /sys
伪文件系统。(是内核参数)
/proc/sys:此目录中的文件很多是可读写的。修改文件内容来修改内核运行特性。
例如:

[root@localhost vm]# pwd
/proc/sys/vm
[root@localhost vm]# ls -l
total 0
-rw-r--r-- 1 root root 0 Sep 13 12:08 block_dump
--w------- 1 root root 0 Sep 13 12:08 compact_memory
-rw-r--r-- 1 root root 0 Sep 13 12:08 dirty_background_bytes
-rw-r--r-- 1 root root 0 Sep 13 12:08 dirty_background_ratio
-rw-r--r-- 1 root root 0 Sep 13 12:08 dirty_bytes
-rw-r--r-- 1 root root 0 Sep 13 12:08 dirty_expire_centisecs
-rw-r--r-- 1 root root 0 Sep 13 12:08 dirty_ratio
-rw-r--r-- 1 root root 0 Sep 13 12:08 dirty_writeback_centisecs
-rw-r--r-- 1 root root 0 Sep 13 12:08 drop_caches
-rw-r--r-- 1 root root 0 Sep 13 12:08 extfrag_threshold
-rw-r--r-- 1 root root 0 Sep 13 12:08 hugepages_treat_as_movable
-rw-r--r-- 1 root root 0 Sep 13 12:08 hugetlb_shm_group
-rw-r--r-- 1 root root 0 Sep 13 12:08 laptop_mode
-rw-r--r-- 1 root root 0 Sep 13 12:08 legacy_va_layout
-rw-r--r-- 1 root root 0 Sep 13 12:08 lowmem_reserve_ratio
-rw-r--r-- 1 root root 0 Sep 13 12:08 max_map_count
-rw-r--r-- 1 root root 0 Sep 13 12:08 memory_failure_early_kill
-rw-r--r-- 1 root root 0 Sep 13 12:08 memory_failure_recovery
-rw-r--r-- 1 root root 0 Sep 13 12:08 min_free_kbytes
-rw-r--r-- 1 root root 0 Sep 13 12:08 min_slab_ratio
-rw-r--r-- 1 root root 0 Sep 13 12:08 min_unmapped_ratio

这些都是内核参数,作为管理员,可以进行内核参数的修改。
/sys/某些文件可写。
例如:通过修改内核参数/proc/sys/vm/drop_caches为,可以清空buffer。

drop_cache

注意
设定内核参数值的方法不能用vim而用echo重定向:

#echo   VALUE  >  /proc /sys/TO/SOMEFILE

例如: 我们想修改hostname主机名

方法一:直接用echo修改内核的参数。

[root@localhost kernel]# pwd
/proc/sys/kernel
[root@localhost kernel]# cat hostname 
localhost.localdomain
[root@localhost kernel]# hostname 
localhost.localdomain
[root@localhost kernel]# echo leo > hostname
[root@localhost kernel]# hostname
leo

方法二:使用sysctl控制

#sysctl   -w  kernel.hostname="localhost.localdomain"

使用"."指定路径。文件必须是在/proc/sys目录下的子目录里。
[root@localhost kernel]# hostname 
leo
[root@localhost kernel]# sysctl -w kernel.hostname=localhost.localdomain
kernel.hostname = localhost.localdomain
[root@localhost kernel]# hostname
localhost.localdomain

但是这两种方法都是立即生效的,但是不能永久生效

想永久生效的话:唯一的办法是修改/etc/sysctl.conf(但不能立即生效)内核参数根据/etc/sysctl.conf这个文件设置内核参数的值。
写法:

sysctl   -w  kernel.hostname="localhost.localdomain"

例如:
两块网卡,是否允许在两块网卡之间传递包。

[root@localhost ~]# cat /proc/sys/net/ipv4/ip_forward 
0 

1代表传递,0代表不传递。

通过修改/etc/sysctl.conf 这个文件,将0改为1,即可永久生效,但是不会立即生效、

[root@localhost ~]# head /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

# Controls source route verification
net.ipv4.conf.default.rp_filter = 1

或者,我们可以通过命令

#sysctl  -p  

让内核重读这个文件,实现立即生效。

[root@localhost ~]# 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


#sysctl  -a  :显示所有的内核参数和其值。

常用的三个参数:hostnameip_forward/proc/sys/vm/drop_caches

内核模块管理:

lsmod:列出当前内核装载的模块。

[root@localhost kernel]# lsmod 
Module                  Size  Used by
ipv6                  321747  266 
nls_utf8                1421  1 
dm_mirror              14048  0 
dm_region_hash         10730  1 dm_mirror
dm_log                  9696  2 dm_mirror,dm_region_hash
snd_ens1371            20593  0 
snd_rawmidi            22734  1 snd_ens1371
snd_ac97_codec        124339  1 snd_ens1371
ac97_bus                1442  1 snd_ac97_codec
snd_seq                55532  0 
snd_seq_device          6522  2 snd_rawmidi,snd_seq
snd_pcm                85629  2 snd_ens1371,snd_ac97_codec
snd_timer              21904  2 snd_seq,snd_pcm
snd                    68480  7 snd_ens1371,snd_rawmidi,snd_ac97_codec,snd_seq,snd_seq_device,
snd_pcm,snd_timersoundcore               7668  1 snd
snd_page_alloc          8428  1 snd_pcm
e1000                 145057  0 
floppy                 63253  0 
vmw_balloon             6781  0 
microcode             111822  0 
pcspkr                  1958  0 
i2c_piix4              10998  0 
i2c_core               30023  1 i2c_piix4
shpchp                 27791  0 
sg                     29692  0 
dm_mod                 74380  2 dm_mirror,dm_log
ext4                  364623  1 
mbcache                 7254  1 ext4
jbd2                   80484  1 ext4
sd_mod                 35179  3 
crc_t10dif              1531  1 sd_mod
sr_mod                 15213  1 
cdrom                  39482  1 sr_mod
mptspi                 16113  2 
mptscsih               34977  1 mptspi
mptbase                93281  2 mptspi,mptscsih
scsi_transport_spi     24957  1 mptspi
pata_acpi               3691  0 
ata_generic             3891  0 
ata_piix               23068  1 


modprobe  MOD_NAME:模块装载。
modprobe  -r  MOD_NAME :卸载模块。
modinfo  MOD_NAME:查看模块的具体信息
另两个命令:但这里必须指定模块路径。
insmod  /path/to/module_file:装载模块(必须指定模块的路径)。
rmmod    MOD_NAME:卸载模块(移除)
depmod  /path/to/modiles_dir   生成模块依赖。。。(需要指定路径)
内核模块必须和驱动程序完全相同。

内核中的功能除了核心功能之外,在编译时,大多数功能都要有三种选择:

  • 1,不使用此功能
  • 2,编译成内核模块 modprobe装载
  • 3,编译进内核

##如何手动编译内核:

目前内核版本是:
uname

挂载系统镜像光驱到/mnt目录,创建一个rpm仓库,编辑yum的配置文件:

  • 1), cd /etc/yum.repos.d目录下,创建一个.repo的文件。内容如下:
[root@localhost ~]# cat /etc/yum.repos.d/Base.repo 
[base]
name=Server
baseurl=file:///mnt
enabled=1
gpgcheck=0
  • 2),编辑/etc/fstab,使得系统光驱开机自动挂载,搭建一个本地的yum仓库。
[root@localhost ~]# cat /etc/fstab 

#
#/etc/fstab
#Created by anaconda on Sat Sep 12 10:59:40 2015
#
#Accessible filesystems, by reference, are maintained under '/dev/disk'
#See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
UUID=8ebb2c3a-320d-40fb-8d57-062be9556d46 /                       ext4    defaults        1 1
UUID=6499e7e6-a462-4b30-b195-1bca6ee04eaa swap                    swap    defaults        0 0
tmpfs                   /dev/shm                tmpfs   defaults        0 0
devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
sysfs                   /sys                    sysfs   defaults        0 0
proc                    /proc                   proc    defaults        0 0
**/dev/cdrom               /mnt            iso9660 defaults        0 0**

只需要添加最后一行即可。

  • 3),安装需要用到的开发库:
yum groupinstall "Development Tools" "Development Libraries" -y

可以通过命令 #yum grouplist 查看当前系统哪些库装了,哪些没安装,依据自己实际情况而定。

  • 4),将下载的内核解压到/usr/src这个目录下。
    下载内核链接:www.kernel.org
#tar -xvf linux-2.6.38.2.tar.xz -C /usr/src/

创建一个软连接,当前我们使用的内核或正在编译的内核一般链接为linux

#ln -sv linux-2.6.38.2 linux
`linux' -> `linux-2.6.38.2'

查看linux目录下的文件:
ls

可以看到有很多的子目录:
例如:

arch:架构有关。
crypto:加密解密
drivers:驱动
fs:文件系统,里面包括ntfs,默认没有安装这个模块,我们可以安装。这样双系统就可以共享文件。
virt:虚拟化功能
ipc:进程间通信
firmware:固件
Documentation:文档。

如何手动编译内核呢:

  • 1),make gconfig : Gnome桌面环境使用(需要安装图形开发库)GNOME Software Development
    make kconfig:KDE桌面环境使用;需要安装图形开发库)
    需要安装桌面,用的不是特别多,用的更多是下面哪种方法。

  • 2),使用menuconfig这个命令之前要先将开发库安装好。

#yum -y install ncurses-devel
#make  menuconfig 

打开文本菜单(需要在内核所在的目录输入该命令)。勾选内核属性。我们可以将当前系统的内核配置文件拷备过去,然后在当前系统内核配置文件的基础上做修改。

  • 3),make编译。
    k1

可以看到选择的界面,注意—->表示底下有很多子条目。敲回车即可打开子条目。
[*]:表示做进内核中
[M]:表示做成模块
[ ]:表示不启用此功能。

在General setup的子目录下,有个叫做local version的选项,就是本地版本号
例如:
[root@www boot]# uname -r
2.6.32-431.el6.x86_64
这里的431就是本地版本号,我们可以自己定义。
在local version那个选项那里回车即可输入自己编译的版本号。
k1
连敲两下esc可以退到上一层目录。

在出现的界面中我们可以选择文件系统的选项,可以将NTFS这个功能做成模块。这样如果电脑装了双系统,linux系统也可以访问windows的NTFS文件系统下的文件。

k2

然后选好自己想要安装的内核功能,然后保存配置文件。

k3

点击yes退出,就会在内核编译的目录下生成一个隐藏配置文件.config,

config

我们当前运行的系统也存在一个内核的配置文件,在/boot目录下,

config2

我们自己定义的config可能在编译的过程中发生错误而导致编译不成功。为了减小这种错误,我们可以将目前系统的内核配置文件复制过去,然后再在当前配置文件的基础上进行修改,这样出现问题的几率就会小很多。
例如:
我们新下载的一个内核,进行编译的时候,先将目前内核的配置文件复制到内核文件所在目录下命名为.config,然后执行make menuconfig这个命令,根据自己的需求进行修改。这样出现问题的可能性会降小。

对内核进行一些调整:

k4

选中项定义了处理器的类型和特点,我们可以进行选择,去掉一些不常用的功能。
centos和redhat默认的cpu类型都是选择的Generic-x86-64,我们可以依据自己的实际情况选择,例如我自己的笔记本是core i5的就可以将处理器选择为core2的。

k5
同时我们可以去掉一些内核的驱动,一些很老,没必要使用的驱动。
k6
例如网卡驱动:

几个比较古老已经淘汰了的东西:
k7

上面的PCMCIA,ATM,FDDI都已经淘汰,用不到,可以去掉了。

  • 4),make安装:

make 进行编译内核。可能会经历很长时间。

可以使用

#make  -j4   

同时使用4核来进行编译加快速度,具体根据自己的机器核心数来指定-j后的number。

make编译安装之后会生成vmlinux,System.map ,modules.builtin等文件。

#make  modules_install  -j4  先进行模块安装,再安装。

make1

#make   install  -j4  安装。

make2

至此,编译系统编译安装完成。

如果之前的编译不好用,可以进行编译清理。
二次编译时清理:(清理前,如果有需要,请备份配置文件.config)
make clean:清理此前编译好的二进制模块。
make mrproper:清理此前编译的内容,使用之前,最好先备份配置文件.config)。

内核编译完成之后,会在 /usr/src/linux/arch/x86/boot目录下生成一个bzImage,这是linux内核的映像文件。
bz

内核编译完成后我们可以通过修改/boot/grub/grub.conf这个grub的配置文件进行内核选择,从新的内核启动。
[root@localhost ~]# cat /boot/grub/grub.conf

#grub.conf generated by anaconda
#
#Note that you do not have to rerun grub after making changes to this file
#NOTICE:  You do not have a /boot partition.  This means that
#          all kernel and initrd paths are relative to /, eg.
#          root (hd0,1)
#          kernel /boot/vmlinuz-version ro root=/dev/sda2
#          initrd /boot/initrd-[generic-]version.img
#boot=/dev/sda
default=0
timeout=5
splashimage=(hd0,1)/boot/grub/splash.xpm.gz
hiddenmenu
title CentOS (2.6.38.2-1.el6)
    root (hd0,1)
    kernel /boot/vmlinuz-2.6.38.2-1.el6 ro root=UUID=8ebb2c3a-320d-40fb-8d57-062be9556d46 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 /boot/initramfs-2.6.38.2-1.el6.img
title CentOS 6 (2.6.32-504.el6.x86_64)
    root (hd0,1)
    kernel /boot/vmlinuz-2.6.32-504.el6.x86_64 ro root=UUID=8ebb2c3a-320d-40fb-8d57-062be9556d46 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 /boot/initramfs-2.6.32-504.el6.x86_64.img

如图,只需要将default=1改为default=0即可,即从第一个内核vmlinuz-2.6.38.2-1.el6启动。

解释下各参数的含义:
default=0:设定默认启动的title的编号,从0开始
timeout=5 :等待用户选择超时时长,单位为s
splashimage=(hd0,0)/grub/splash.xpm.gz:grub的背景图片
hiddenmenu:隐藏菜单。
title Red Hat Enterprise Linux (2.6.32-358.el6.i686) 内核标题或操作系统标题。字符串,可以自由修改。
root (hd0,1)#内核文件所在的设备。(对grub而言,所有类型硬盘一律为hd;格式为(hd#,N) hd#表示第#个磁盘。最后的0则表示对应的磁盘分区。
kernel /vmlinuz-2.6.32-358.el6.i686 ro #grub的访问路径所以是在根下。
root=UUID=1e0664cd-aaf4-4064-96b5-3090c26f37a0 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-358.el6.i686.img #ramdisk的文件路径。

重启系统后,查看内核是否完成升级

[root@localhost ~]# uname -r
2.6.38.2-1.el6

可以看到内核已经从2.6.32升级到2.6.38了。

可能遇到的问题:

使用vmware进行编译内核的时候,执行到make install时候会提示如下错误,意思是vmware_balloon这个模块找不到,原因是这个模块名字已经发生了改变为vmw_balloon.ko。做个软连接即可。
错误提示:
err

找不到 vmware_balloon 模块,原因有两个:
首先,确认你的 .config 文件里面有 CONFIG_VMWARE_BALLOON=m 这一行,或者你可以用 make menuconfig 进去内核编译菜单,选中 Device Drivers -> MISC devices -> VMware Balloon Driver 为 M 或者 *
其次,而这个模块在后面的版本中,已经更名为 vmw_balloon,所以 可以用下面的命令来解决:
cd /lib/modules/3.x.xx/kernel/drivers/misc #将版本号改成你自己的
ln -s vmw_balloon.ko vmware_balloon.ko #建立软连接

解决方法:

ln

成功编译:

make2