为Deepin Linux编译内核

Deepin Linux是Linux中的新锐力量,独创的桌面环境、应用生态与设计时的种种匠心,使得它拥有非常酷炫的体验,成为越来越多电脑爱好者的首选。

不过,基于Linux的操作系统,并不像Windows一样能完美解决驱动问题。在Windows中,只需找到对应的官方驱动安装即可;但是Linux却是将设备驱动程序都集成在内核中,以及作为内核模块加载,这一切都是在编译内核时就已一锤定音。如此机制,使得Deepin发行版的一套编译好的内核并不能完美适用于所有设备。

笔者就在Linux的驱动上吃了苦头。面前这台备用笔记本是ThinkPad X200,X系列的老旗舰,在运行Deepin的时候,显卡驱动就出现了问题,表现为每次关盖后重新打开,或者是待机后重新唤醒,移动鼠标就会在鼠标指针下方区域出现画面撕裂、闪屏的情况,即便使用“深度显卡驱动管理工具”更换驱动也是如此。后来我就决定,自己为X200量身编译一个内核。


获取内核源码

在Linux内核官网(https://www.kernel.org/)上,就可以下载到若干个版本的内核源码。从官网可知,内核源码有若干个版本,分别包括主线版(mainline)、稳定版(stable)、长期支持版(longterm)。这几个版本的区别如下:

  • 主线版是Linux开发者活跃的地方,最新的内核功能主要在这里诞生;
  • 稳定版是可供用户直接使用的版本;
  • 长期支持版则主要是给设备制造商、发行版开发者使用的版本,相对更稳定,且能长期得到技术支持。

对于PC上的Linux,一般选择稳定版,和版本大于等于4.x的长期支持版。我选择的是4.19.1的稳定版,它出现在最醒目的位置。

为Deepin Linux编译内核_第1张图片
Kernel.org的主页面

内核源码使用tar.xz格式压缩。我将内核源码包放置在~/kernel目录下,然后使用以下命令解压缩:

tar -Jxvf linux-4.19.1.tar.xz

安装依赖

内核的编译需要用到若干个软件。在Deepin中,使用apt可一次性安装好:

# 编译工具
sudo apt install gcc make
# 语法解析器生成工具
sudo apt install bison flex
# OpenSSL库
sudo apt install libssl-dev
# ncurses库
sudo apt install libncurses-dev

配置内核准备

加载默认的配置文件

配置内核的第一步,就是先加载默认的配置文件以供修改。在内核解压目录linux-4.19中,运行:

make defconfig

默认的配置文件就会被写入内核配置文件.config中。这里的.config位于内核源码根目录,内核编译过程用到的就是它。

执行结果如下:

anclark@anclark-PC:~/kernel/linux-4.19$ make defconfig
  HOSTCC  scripts/kconfig/conf.o
  YACC    scripts/kconfig/zconf.tab.c
  LEX     scripts/kconfig/zconf.lex.c
  HOSTCC  scripts/kconfig/zconf.tab.o
  HOSTLD  scripts/kconfig/conf
*** Default configuration is based on 'x86_64_defconfig'
#
# configuration written to .config
#

打开menuconfig

接下来的工作就是配置内核了。Linux为我们提供了menuconfig这个配置工具,它基于ncurses与wxDialog开发,可以在其中以图形化菜单的方式配置各种内核选项。

运行以下命令,即可自动编译并启动menuconfig:

make menuconfig

稍等片刻,终端中就会出现如下画面:

为Deepin Linux编译内核_第2张图片
menuconfig的主界面

menuconfig的操作方法简单直观,在界面上部就已经列出了,改变选项值除了按“Y/N/M”三个键之外,还可用空格。可以键入问号(即Shift+问号键)来查看帮助,键入斜杠(/)来检索设置项。

值得注意的是,一些组件在编译时可以选择将其编译到内核中(显示为[*]<*>)或是编译为模块(显示为[M])。编译到内核中就成为了内核的一部分;而编译成为模块则会被安装到指定的目录中,使用modprobe等工具加载。

配置内核

启用设备支持

要想让内核比较完美地支持目标设备,还需对内核进行一番设置。Linux官方虽然提供了针对PC的通用配置文件,但该配置文件仅仅是一个开始,要面向各种各样复杂的具体平台,内核的发布者不可能兼顾所有的设备。因此,仅仅使用默认的配置文件是不够的。

启用无线网络支持

考虑到不同的设备使用不同的无线网卡,默认配置文件并没有启用无线网卡的设备驱动。为此还需手动开启。

首先使用lspci命令,列出所有安装在PCI总线上的设备,查看网卡型号:

anclark@anclark-PC:~/kernel/linux-4.19$ lspci
00:00.0 Host bridge: Intel Corporation Mobile 4 Series Chipset Memory Controller Hub (rev 07)
00:02.0 VGA compatible controller: Intel Corporation Mobile 4 Series Chipset Integrated Graphics Controller (rev 07)
00:02.1 Display controller: Intel Corporation Mobile 4 Series Chipset Integrated Graphics Controller (rev 07)
00:03.0 Communication controller: Intel Corporation Mobile 4 Series Chipset MEI Controller (rev 07)
00:03.3 Serial controller: Intel Corporation Mobile 4 Series Chipset AMT SOL Redirection (rev 07)
00:19.0 Ethernet controller: Intel Corporation 82567LM Gigabit Network Connection (rev 03)
00:1a.0 USB controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #4 (rev 03)
00:1a.1 USB controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #5 (rev 03)
00:1a.2 USB controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #6 (rev 03)
00:1a.7 USB controller: Intel Corporation 82801I (ICH9 Family) USB2 EHCI Controller #2 (rev 03)
00:1b.0 Audio device: Intel Corporation 82801I (ICH9 Family) HD Audio Controller (rev 03)
00:1c.0 PCI bridge: Intel Corporation 82801I (ICH9 Family) PCI Express Port 1 (rev 03)
00:1c.1 PCI bridge: Intel Corporation 82801I (ICH9 Family) PCI Express Port 2 (rev 03)
00:1c.2 PCI bridge: Intel Corporation 82801I (ICH9 Family) PCI Express Port 3 (rev 03)
00:1c.3 PCI bridge: Intel Corporation 82801I (ICH9 Family) PCI Express Port 4 (rev 03)
00:1d.0 USB controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #1 (rev 03)
00:1d.1 USB controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #2 (rev 03)
00:1d.2 USB controller: Intel Corporation 82801I (ICH9 Family) USB UHCI Controller #3 (rev 03)
00:1d.7 USB controller: Intel Corporation 82801I (ICH9 Family) USB2 EHCI Controller #1 (rev 03)
00:1e.0 PCI bridge: Intel Corporation 82801 Mobile PCI Bridge (rev 93)
00:1f.0 ISA bridge: Intel Corporation ICH9M-E LPC Interface Controller (rev 03)
00:1f.2 SATA controller: Intel Corporation 82801IBM/IEM (ICH9M/ICH9M-E) 4 port SATA Controller [AHCI mode] (rev 03)
00:1f.3 SMBus: Intel Corporation 82801I (ICH9 Family) SMBus Controller (rev 03)
03:00.0 Network controller: Intel Corporation PRO/Wireless 5100 AGN [Shiloh] Network Connection
04:00.0 Memory controller: Intel Corporation Turbo Memory Controller (rev 11)

在列出的设备中,无线网卡对应的是03:00.0 Network controller: Intel Corporation PRO/Wireless 5100 AGN [Shiloh] Network Connection,从中不难得知,我X200无线网卡的型号是Intel 5100AGN。

然后在menuconfig中,依次进入以下选项:

  • Device Drivers
    • Network device support
      • Wireless LAN

其中提供了很多设备的驱动选项。先找到自己无线网卡的品牌,然后找到无线网卡型号所对应的项目,按空格键选择“M”编译为模块。当然,如果确定驱动程序没有问题,也可以选择“*”编译为内核的一部分,不过这样就不能使用modprobe工具手工装载卸载以便调试了。

以笔者的Intel 5100AGN为例。首先找到Intel所对应的项目,如下图所示。特别的是,笔者的5100AGN对应的驱动项目是iwlwifi,即列表中的Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlwifi)这一点从该项的帮助信息中可以知悉——遇到无法确认的项目,不妨查看它的帮助信息,以了解它支持什么型号。

为Deepin Linux编译内核_第3张图片
无线网卡驱动列表中的Intel相关选项,高亮的那一项是笔者无线网卡需要用到的
为Deepin Linux编译内核_第4张图片
“iwlwifi”项目所对应的网卡型号。看来英特尔把这些新推出的网卡型号都整合成一个驱动了。

同时,英特尔无线网卡的工作还需要固件(firmware)的支持,因此下面的两项关于固件的项目也选择上。

注意事项

  • 在笔者的X200上,如果此处英特尔无线网卡的驱动型号同时选择多个,会有不能加载固件的情况出现,不能加载固件就意味着不能启动无线网卡。即便将固件下载站中正确的固件放置到指定位置(/lib/firmware/),也无法启动网卡。因此,只能选择iwlwifi
  • 笔者的5100AGN无线网卡不支持把驱动编译到内核中(上述选项选择“*”就是将指定的驱动编译为内核的一部分),而只能编译为模块。否则,同样会出现找不到固件的问题。

启用蓝牙支持

kernel.org上的内核源码,面向的是千千万万台配置不同的设备,所以除了WLAN,蓝牙也并没有默认启用,还需手动启用。具体可参见我写的另一篇教程《为Deepin Linux启用蓝牙支持》

启用声卡支持

同样默认地,默认配置文件并未启用声卡支持,因此用编译出来的内核启动系统,是没有声音的。Linux内核使用ALSA作为音频框架,声卡驱动作为编解码器(codec)被加载,需要我们手动把声卡的codec选项打开,才可在Deepin中听到声音。

在menuconfig中,依次进入以下选项:

  • Device Drivers
    • Sound card support
      • Advanced Linux Sound Architecture
为Deepin Linux编译内核_第5张图片
声卡驱动选项

其中又包括若干个关于声卡驱动的子菜单,包括Generic sound devices(标准音频设备)、PCI sound devices(PCI音频设备)、HD-Audio、USB sound devices(USB音频设备)和PCMCIA sound devices。现在新的笔记本和台式机声卡基本上都使用HD Audio控制器,包括笔者的X200,因此选择HD-Audio。

为Deepin Linux编译内核_第6张图片
HD-Audio 的相关选项,其中包括了各个品牌的声卡编解码器

特别的是,在Linux中,HD Audio音频的实现由芯片组厂商(如Intel、AMD、NVIDIA)负责,因此使用lspci是看不到声卡品牌和型号的。不过不用担心,在HD-Audio这一列表中,一个品牌的所有HDA声卡都遵循同一套API标准,所以可以以一个选项覆盖所有型号。而就品牌而言,现在的笔记本多使用Realtek(瑞昱)和Conexant(科胜讯,已被Synaptics收购)的声卡,所以选择它们对应的两项即可。另外,如果笔记本附带HDMI或DisplayPort接口,则还要选上Build HDMI/DisplayPort HD-audio codec support,以从这两种视频输出接口中输出音频信号。

至于编译模式,最好将它们编译成内核的一部分,因为相较于无线网卡,声卡的折腾要容易不少,电脑声卡出问题的概率会低得多。

启用用户态文件系统支持

包括Deepin在内的发行版,为了方便用户使用,以及照顾双系统用户的需求,都支持Windows和Mac的文件系统,如NTFS、exFAT、HFS+。通常对于这些文件系统的支持,多基于FUSE(Filesystem In UserSpacE,用户态文件系统),配合访问这些文件系统的驱动层,如ntfs-3g。

值得注意的是,默认情况下,用户态文件系统并没有在默认配置文件中启用,必须要手动打开该功能才行。打开的方法很简单,该选项位于menuconfig主页面的“File systems”中,项目名为FUSE (Filesystem in Userspace) support,如下图所示:

为Deepin Linux编译内核_第7张图片
FUSE选项在“File systems”二级菜单中的位置

务必把它编译成内核的一部分,而不是模块,以实现Linux对FUSE的无缝支持,这对系统体验的提升是不可或缺的。

保存内核配置

内核配置默认保存在内核源码根目录的.config文件中,内核编译过程会使用它,因此menuconfig默认也会将修改好的配置文件保存在那里。按左右方向键,在底部的按钮中选择“Save”,选择内核配置文件的保存位置(默认为.config),回车。若要退出,选择“Exit”即可。

为Deepin Linux编译内核_第8张图片
保存内核配置的提示界面

笔者建议将好不容易编辑好的内核配置导出,以便下次使用。直接把内核源码根目录的.config复制到别处。下次若要使用,直接将导出的配置文件覆盖内核源码根目录的.config文件即可。

编译内核

配置工作完成后,我们就可以着手开始编译内核了,同时编译完成后的内核与模块可以直接安装到系统中,下次启动就可以直接使用我们新的内核。

开始编译

首先确保内核已经配置好——源码根目录有.config文件,然后运行以下命令,开始编译:

make

如果想提高一下编译效率,可以加上-j参数,多开编译进程:

make -j8

稍等一段时间,等待编译完成。完成时,make会输出以下信息:

Kernel: arch/x86/bzImage is ready (#2)

安装内核模块

内核编译好之后,可以直接运行make install进行安装。但是经我实测,直接安装容易出错,出错的地方主要位于在内核模块的安装上。因此,最好先安装内核模块。

安装内核模块,只需要一个命令:

sudo make modules_install

运行该命令会调用depmod工具——配置内核模块的工具。不同版本内核的模块必须分别存放在内核对应的目录中,depmod工具可以自动创建新的内核所对应的模块目录,然后将模块安装到其中。

安装内核

安装内核到系统中,只需要一个命令:

sudo make install

该命令会自动调用内核源码中的安装工具,将内核复制到系统中,在Grub菜单项中加入新内核所对应的启动选项,并备份旧版本内核。安装成功后,下次启动就会自动使用我们编译好的新内核了,同时还可以在启动菜单的“高级启动选项(Advanced boot options)”中选择旧版本的内核启动。

安装头文件

如果你需要做Linux相关的开发,也可以将内核头文件安装到系统中。只需使用一个命令:

sudo make headers_install

编译清理

编译后,如果对内核源码进行了一些修改,或是同一个内核源码用来给多个设备进行编译,一般都需要进行一番清理。

清理的命令有两个:

make clean
make distclean

它们的区别在于,make clean只会清理编译输出的文件,如*.o(目标代码)、*.cmd(编译命令记录)等,而保留当前内核的配置文件,便于重新编译;而make distclean的清理则比较彻底,会将内核配置文件、内核配置程序的可执行文件等(如menuconfig的可执行文件)一并清除。

注意事项:
在Deepin中,由于我们在安装内核的过程中使用了sudo,这会使得内核源码目录中的一些文件只有使用Root权限才能被修改。因此清理和编译的命令也需要sudo,否则会因权限不足而中止。

测试新的内核

内核安装完成后,重启电脑就会默认使用新内核启动。为了保证内核无故障运行,我需要对内核进行一番测试。以下是我在我的X200上进行测试的过程。但在实际操作中,由于无前人的经验,我只能摸着石头过河,发现一个问题,解决一个问题。以下是我对整个测试过程的总结。

显示:检查关盖花屏问题是否解决

很简单,关闭盖子重新打开,移动鼠标,以及休眠后唤醒,移动鼠标。可以发现,花屏问题完美解决,原先闪屏撕裂的状况不再出现,终于可以愉快地吃上Deepin了。

无线网卡:检查连接性

老款的ThinkPad有一个很贴心的设计——灯条,这是我当时选择它的原因。灯条上电源、硬盘、网卡、蓝牙工作的状态一应俱全,方便而直观,贴心程度至今难以被后来者超越。尤其是无线网卡,会在启动后亮起,并在有网络流量时闪烁。

无线网卡未加载时,Deepin系统的状态栏中并不会出现无线网络的图标,同时X200的无线网卡灯不会亮起。这使我非常纳闷,毕竟测试的时候我曾经尝试同时启用过多个型号的驱动。

后来我尝试分析内核日志,使用dmesg | grep iwl获取Intel无线网卡相关的日志信息,结果发现了下面的错误提示:

Direct firmware load for iwlwifi-5000-5.ucode failed with error -2
Direct firmware load for iwlwifi-5000-4.ucode failed with error -2
Direct firmware load for iwlwifi-5000-3.ucode failed with error -2
Direct firmware load for iwlwifi-5000-2.ucode failed with error -2
Direct firmware load for iwlwifi-5000-1.ucode failed with error -2
No suitable firmware found!

后来,我尝试在Intel固件发布页面中下载了与我无线网卡对应的上述固件文件,放置于/lib/firmware中,结果重启后还是会提示上述的错误。

于是,我回到menuconfig中,得知对应我设备的Intel驱动选项其实是iwlwifi,而不是列表中其他的那些型号。果然,取消勾选其他型号,只保留iwlwifi,重新编译并安装内核,问题解决,久违的无线网卡指示灯终于欢快地亮起了。

测试声卡

测试声卡的过程相对要顺利一些,也更简单。起初电脑放不出声音,在Deepin设置中的“声音”→“高级设置”中设备列表是空的。然后在内核中打开声卡驱动相关的选项,重新编译之后,声音播放就正常了。

Chrome打开网易云音乐,随便放首歌,是最直观的测试方法。

测试文件系统

笔者将X200原装的硬盘拆下来改为移动硬盘,并给笔记本换上固态,把原装硬盘格式化为exFAT。在启用FUSE之前,插上原装硬盘,Deepin虽然能识别出来,却无法挂载,显示为空。后来启用FUSE后,果然能正常识别并自动挂载了,任务栏上也出现了安全弹出的图标。

测试USB

笔者的另一台新的惠普笔记本,在Ubuntu 16.04上曾使用4.18版本的stable内核源码,结果USB无法使用。有鉴于此,我在X200上还需对USB功能单独测试。使用lsusb命令检查USB设备连接,果然有输出;然后插入鼠标、键盘、移动硬盘等USB设备,果然正常识别出来了。由此说明,4.19内核在X200上的USB功能不存在问题。

总结

和Windows不同,玩Linux的意义在于折腾。驱动问题上,Windows的解决是最为到位和全面的,只需下载驱动安装文件安装即可,并且厂商也会优先支持Windows;而Linux上必须好好折腾一番,就像我这样不停地编辑配置编译内核,才能用上顺手好用的系统。Linux虽说麻烦一些,可是折腾之后设备跑起来的成就感,却是难以比拟的。

与此同时,笔者也意识到,很多问题的解决,还是要靠自己。对于Deepin官方内核在X200上显示的Bug,笔者曾在Deepin论坛和反馈平台中反馈,但几乎没人有有效的回复,终究还是靠我自己解决。而且我稍微检索了一下百度,结果没找到任何前人的经验,找到的只是问题最基本的排查方法而已。要是等着别人为我想办法,那难度可堪比登天了。自己动手,丰衣足食,正是硬道理!

你可能感兴趣的:(为Deepin Linux编译内核)