Linux內核編譯與管理

我們說的Linux其實指的就是 內核(kernel)而已。這個內核控制你主機的所有硬件并提供系統(tǒng)所有的功能,所以它非常重要。我們開機的時候就是利用開機管理程序加載這個內核文件來檢查硬件,在內核加載適當的驅動程序后,系統(tǒng)才能夠順利運行。

現今的系統(tǒng)由于強調在線升級機制,因此非常不建議自定義內核編譯!但是,如果你想將你的Linux安裝到USB移動設備,將你的PC安裝自己的Linux,想讓你的Linux可以驅動你的PC,內核編譯就是相當重要的一個任務。

編譯前的任務:認識內核與取得內核源代碼

內核(kernel)是整個操作系統(tǒng)的最底層,它負責了整個硬件的驅動,以及提供各種系統(tǒng)所需的核心功能。包括防火墻機制、是否支援LVM或Quota等文件系統(tǒng)。如果你的內核不認識某個最新的硬件,那么該硬件也就無法被驅動,當然也就無法使用該硬件。

什么是內核(kernel)?

Kernel

電腦真正在工作的東西其實是 “硬件”,例如數值運算要使用到CPU、儲存資料要用到硬盤、圖形顯示要用到顯卡、音頻需要聲卡、連接Internet需要網卡等等。那么如何控制這些硬件呢?那就是內核的工作了。

你想讓計算機進行的工作,都必須要內核支持才行,這個標準不論是LInux還是Windows都一樣。

其實內核就是系統(tǒng)上面的一個文件而已,這個文件包含了驅動主機各項硬件的檢測程序與驅動模塊。在開機流程分析中,這個文件被讀入主存儲器的時機,當系統(tǒng)讀完BIOS并加載MBR內的引導裝載程序后,就能夠加載內核到內存當中。然后內核開始檢測硬件,掛載根目錄并取得內核模塊來驅動所有的硬件,之后調用 systemd就能依序啟動所有系統(tǒng)所需的服務了。

這個內核文件通常被放置在 /boot/vmlinuz-xxx,不過也不見得,因為一臺主機上可以擁有多個內核文件,而開機的時候僅能選擇一個來加載而已。我們甚至可以在一個distribution上面放置多個核心,然后以這些核心來做成多重開機。

內核模塊(Kernel module)用途

既然內核文件都已經包含了硬件檢測與驅動模塊,那么什么是內核模塊?

如果我的內核比較舊,但是我換了新的硬件,這個內核肯定無法識別,而重新編譯內核是很麻煩的。為了這個緣故,Linux就開始使用所謂的模塊化設置了。即是將一些不常用的類似驅動程序的內容獨立出內核,編譯成模塊,然后,內核可以在系統(tǒng)正常運行的過程中加載這個模塊到內核的支持。如此一來,我在不需要更改內核的前提下,只要編譯出適當的內核模塊,在加載它,Linux就可以使用這個硬件了。模塊組放置于 /lib/modules/$(uname -r)/kernel/中。

自制內核-內核編譯

內核文件是通過 源碼(source code)編譯而成的。因為內核是直接被讀入主存儲器中,所以要將它編譯成為系統(tǒng)可認識的文件才行,也就是說,我們要取得內核的源碼,然后進行編譯。

關于驅動程序:是廠商的責任還是內核的責任

在驅動程序的開發(fā)這個工作上來說,應該是屬于硬件發(fā)展廠商的問題。主要是Linux上面的使用人員實在是少于Windows人員。

更新內核的目的

除了BIOS(或UEFI)之外,內核是操作系統(tǒng)中最早被加載到主存儲器的,它包含了所有可以讓硬件和軟件工作的信息。所以,如果沒有搞定核心,系統(tǒng)肯定會有小問題。

內核編譯的重點在于 “你的Linux做什么?”,如果沒有必要的工作,就不用加在內核當中,這樣才能讓你的Linux跑的更快更穩(wěn)健。這也是為什么我們需要編譯內核的最主要原因。

Linux內核特色與默認內核對終端用戶的角色

Linux內核有幾個主要的特色,除了Kernel可以隨時、 隨各人喜好而改動之外,版本改動次數太頻繁也是一個特點。所以,除非你有特殊需求,否則一次編譯成功就可以啦!不需要隨時保持最新的內核版本,而且也沒有必要(便以一次內核要很久。)

對于一般的使用者,由于系統(tǒng)已經將內核編譯的相當得相當適合普通用戶使用了,因此一般入門的用戶基本上不太需要編譯內核。

內核編譯的可能目的

當然是有需要才回來編譯內核啦!

編譯內核的時機可以歸納為以下幾類:

新功能的需求

我需要新的功能,而這個功能只在新的內核里面才有,為了獲得這個功能,只好重新編譯我的內核;

原本的內核太過于臃腫

如果你對系統(tǒng)穩(wěn)定性很要求,對于內核多編譯了很多莫名其妙的功能不太喜歡的時候,那么就可以重新編譯內核來取消該功能;

與硬件搭配的穩(wěn)定性

內核也可能沒有正確的驅動新的硬件,此時就得重新編譯核心來讓系統(tǒng)取得正確的模塊才好;

其他需求(如嵌入式系統(tǒng))

你需要特殊的環(huán)境需求時,就得自行設計你的內核;

如果為了增加性能來編譯內核的話,基本上,效益不大。然而,如果是針對“系統(tǒng)穩(wěn)定性”來考量的話,那么就有充分的理由來支持你重新編譯內核。

如果系統(tǒng)已經運行很久了,而且也沒有什么問題,加上我又不想增加冷門的硬件設備,那么建議就不需要重新編譯內核。因為重新編譯內核的主要目的是“想讓系統(tǒng)變得更加穩(wěn)定”。

由于內核的主要工作是控制硬件,所以編譯之前,請先了解硬件設備和主機未來的功能。內核當然是越簡單越好啦!

內核的版本

uname -r

內核版本

目前CentOS7使用的3.10.x版本為長期維護版本,不過理論上我們也可以升級到后續(xù)的主線版本上。

內核源代碼的取得方式

基本上,依據我們的distributions去挑選的內核源碼主要有:

原本distribution提供的內核源代碼文件

全部的CentOS原始SRPM,http://vault.centos.org/;

CentOS 7.1的SRPM,http://vault.centos.org/7.1.1503/;

原本的distribution放出的源碼中,包含有他們設定好的默認值,我們也就可以輕易的了解到當初他們是如何選擇與內核有關的各項設定項目的參數值,就可以利用這些可以配合我們Linux系統(tǒng)的默認參數加以修改。

取得最新的穩(wěn)定版內核源代碼

Linux的內核目前是由其發(fā)明者 Linus Torvalds所屬團隊在負責維護,其網站上可以找到最新的Kernel信息。

內核官網:https://www.kernel.org/;

保留原本設置:利用patch升級內核源代碼

其實每一次內核發(fā)布時,除了發(fā)布完整的內核壓縮文件以外,也會發(fā)布該版本與前一版本的差異性補?。╬atch)文件,每個內核的patch僅僅是針對前一版本的內核來分析而已;

所以,如果想要從3.10.85升級到3.10.88的話,那么就得要下載 “patch-3.10.86,patch-3.10.87,patch-3.10.88”等文件,然后 依序一個一個的進行patch動作,這個很重要!

同樣,如果是某個硬件或非官方機構所發(fā)布的patch文件時,你也必須要了解該patch文件所適用的內核版本,然后才能進行patch動作;

在進行完patch動作之后,你可以直接檢查一下原本的設置值,如果沒有問題,就可以直接進行編譯。至于patch文件的下載,同樣是在Kernel的相同目錄下,尋找文件嗎是patch開頭的就是了。

內核源代碼的解壓縮、安裝、觀察

不論是從CentOS官網下載的SRPM還是從Linux Kernel官網下載的tarball內核源代碼,最終都會有一個tarball的內核源代碼。

Linux Kernel Archive

內核源代碼的解壓縮與放置目錄

#### Kernel:linux-3.10.107.tar.xz

cd /usr/src/kernels/

wget https://cdn.kernel.org/pub/linux/kernel/v3.x/linux-3.10.107.tar.xz

tar -Jxvf linux-3.10.107.tar.xz -C /usr/src/kernels/

內核源代碼下的此目錄

arch:與硬件平臺有關的選項,大部分指的是CPU的類別,例如 x86,x86_64,Xen虛擬支持等;

block:與區(qū)塊設備較相關的設置數據,區(qū)塊數據通常指的是大量存儲媒體,還包括ext3等文件系統(tǒng)的支持是否允許等;

crypto:內核所支持的加密技術,如 md5或des等;

Documention:與內核有關的幫助文檔;

drivers:一些硬件的驅動程序,如顯卡、網卡、PCI相關硬件;

firmware:一些舊式硬件的微指令(固件)數據;

fs:內核所支持的filesystems,如vfat、nfs等;

include:一些可讓其他程序調用的頭(header)定義數據;

init:一些內核初始化的定義功能,包括掛載與init程序的調用等;

ipc:定義Linux操作系統(tǒng)內各程序的通信;

kernel:定義內核的程序、內核狀態(tài)、線程、程序的調度(schedule)、程序的信號(signal)等;

lib:一些函數庫;

mm:與內存單元有關的各種信息,包括swap與虛擬內存等;

net:與網絡有關的各項協(xié)議信息,還有防火墻(net/ipv4/netfilter/*)等;

security:包括SELinux等安全性設置;

sound:與音效有關的各項模塊;

virt:與虛擬化及其有關的信息,目前內核支持的是KVM(Kernel base Virtual Machine)


內核編譯的前處理和內核功能選擇

內核的目的在管理硬件與提供系統(tǒng)內核功能,因此你必須要先找到系統(tǒng)硬件,并且規(guī)劃主機的未來任務,這樣才能夠編譯出適合這部主機的內核。所以,真?zhèn)€內核編譯的重要工作就是在 “挑選我們想要的功能”。

硬件環(huán)境查看與內核功能要求

一部主機硬件環(huán)境

CPU:Intel(R) Core(TM) i5-4590 CPU @ 3.30GHz; ? ?#lscpu,/proc/cpuinfo

主板芯片組:Gigabyte B85M-D2V ;? ? #dmidecode | grep "Base Board Information"

顯卡:Intel Corporation Xeon E3-1200 v3/4th Gen Core Processor Integrated Graphics Controller (rev 06),集成顯卡; ? ?# lspci | vga

內存:8G; ? ?# /proc/meminfo

硬盤:1TB; ? ?# fidsk -l

網卡:Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (rev 0c); ? ?# lspci | grep Ethernet

至于這臺主機的需求,則根據你來定了。

保持干凈的源代碼:make mrproper

了解了硬件相關的信息后,我們還得要處理一下內核源代碼下面的殘留文件才行??梢酝ㄟ^一下命令在此目錄下處理這些“編譯過程的目標文件(*.o)以及設置文件”

make mrproper ? ?

# 這個動作會將以前進行過的內核功能選擇文件也刪除掉,所以幾乎只有第一次執(zhí)行內核編譯前才執(zhí)行這個動作,其他時候刪除前一次編譯殘留文件,只需要使用如下命令。

make clean

# make clean僅會刪除類似目標文件之類的編譯過程產生的中間文件,而不會刪除設置文件。

開始挑選內核功能:make XXconfig

在 /boot/ 目錄下存在一個名為config-xxx的文件,它就是內核的功能列表文件。

/boot/

我們下面要進行的動作,就是制作出該文件。而后續(xù)所要進行的編譯動作就是通過這個文件來處理的。內核功能的挑選,最后會在 /usr/src/kernel/linux-3.10.107/ 下產生一個 .config 的隱藏文件,這個文件就是 /boot/config-xxxx 的文件。如何建立該文件?

make menuconfig;

## 文字模式下可以顯示類似圖形界面的方式來挑選內核功能選單!

make oldconfig;

## 通過使用已經存在的 ./.config 文件內容,使用該文件內的設置值為默認值,只將新版本內核中的新功能選項列出讓用戶選擇,可以簡化內核功能的挑選過程!對于作為升級內核源代碼后的功能挑選來說,是非常好的一個選項。

make xconfig

## 通過以Qt為圖形界面基礎功能的圖形化界面顯示,需要具有X-Window的支持。如KDE就是通過Qt來設計的X-Window。

make gconfig;

## 通過以Gtk為圖形接口基礎功能的圖形化界面顯示,需要X-Window的支持。如GNOME就是通過Gtk來設計的X-Window。

make config;

## 最老式的功能挑選方法,每個選項都以條件式的一條一條的列出讓你選擇,設置錯誤的話只能夠再次選擇,很不人性化。

大致功能選擇有上述方法,更多使用說明請參照 README文件。推薦使用 make menuconfig,雖然圖形界面的選擇很不錯,但是是需要圖形界面的支持的。如果是升級內核源代碼并且需要重新編譯,那么使用 make oldconfig 比較合適!

make menuconfig;

## 可能需要 yum install ncurses-devel庫,生成 .config文件。

## make mrproper會將 .config 刪除的哦!

在/usr/src/linux-3.10.107/下
3.10.107 Kernel Configuration 選擇

若為 [ * ] < * > 則表示編譯進內核;

若為 [ M ] 則表示編譯成模塊;

如果在不知道該選項為何時,且有模塊可以選,那么就直接選擇為模塊。

關于整個內核功能的選擇上面,可以這樣思考:

“肯定” 內核一定要的功能,直接編譯進內核內;

可能在將來會用到的功能,那么盡量編譯成為模塊;

不知道那個東西要干嘛的,看幫助也看不懂的話,那么就保留默認值,或者是將它編譯成模塊。

總之,盡量保證內核小而美,剩下的功能就編譯成模塊,尤其是需要考慮到將來擴展性。

內核功能細項選擇

看不懂的選項,務必要使用Help查閱。下面列舉幾個比較重要的選項。

Kernel configuration 細項

General setup

與Linux最相關的程序互動、內核版本說明、是否使用開發(fā)中程序代碼等信息都在這里設置。這里的選項主要都是針對內核與程序之間的相關性來設計的,基本上,保留默認值就可以了。不要隨便取消底下的任何一個項目,因為可能會造成某些程序無法被同時執(zhí)行??梢砸罁﨟elp的建議來選擇新功能的啟動與否。

General setup默認值
鳥哥的

loadable module + block layer

要讓內核能夠支援動態(tài)的內核模塊,那么Enable loadable module support就得設置成開啟。block layer則默認是啟動的。

loadable module默認值
鳥哥的


block layer默認值
鳥哥的

CPU的類型與功能選擇

Processor type and feature,挑選你主機的實際CPU形式。KVM和Xen虛擬化服務。

Processor type and features 默認值
鳥哥的

電源管理功能

Power management and ACPI(Advanced Configuration and Power Interface) options 系統(tǒng)的電源管理機制。但電源管理機制還需要搭配主板和CPU的相關省電功能,才能夠實際達到省電的效率啦!

Power 默認設置
鳥哥的

一些總線(bus)的選項

Bus options(PCI etc.)選項與總線有關!最為常見的 PCI 與 PCI-Express的支持。里面的 PCI-E一定要選,不然可能無法識別到某些PCI-E設備。

Bus options 默認值
鳥哥的

編譯成可執(zhí)行文件的格式

Executable file formats / Emulations 是給Linux內核運行可執(zhí)行文件之用的數據,通常是與編譯行為有關。?

Executable file 默認值
鳥哥的

內核的網絡功能

Networking support選項相當重要,它包含了防火墻相關的項目!由于防火墻是在啟動網絡之后再設置即可,所以絕大部分的內容都可以被編譯成模塊,而且也建議編譯成模塊。有用到的時候再載入內核即可。

Networking support 默認值
鳥哥的

各項設備的驅動程序

Device Driver是所有硬件設備的驅動程序庫!這里面的選項與主機的硬件有絕對的關系。

這里面的選項很重要,內核發(fā)布時的默認值比較符合一般狀態(tài)的。你可以根據你的主板和相關硬件來進行編譯,不過要記得還有“擴展性”的考慮。

Device Drivers 默認值
鳥哥的
鳥哥的

Firmware(固件) Drivers

基本上保留默認設置值就可以了。

文件系統(tǒng)的支持

File system,如果不支持某個文件系統(tǒng),那么Linux Kernel就無法識別,當然也就無法使用!如Quota,NTFS等文件系統(tǒng)。

這部分很麻煩,因為涉及內核是否能夠支持某些文件系統(tǒng),以及操作系統(tǒng)支持的 partition table項目。在進行選擇時,務必要小心!尤其使我們常常用到的網絡操作系統(tǒng)(NFS/Samba等),都要選擇,否則是無法被識別的。

File system 默認值
鳥哥的

內核駭客、信息安全、密碼應用

Kernel hacking 與內核開發(fā)者比較相關的部分,這部分建議保留默認之即可;

Security options 屬于信息安全方面的設置,包括SELinux這個具體權限強化模塊也在這里編入內核。這部分只要記得SELinux作為默認值,且要將 NSA SELinux編進內核即可,其他保留默認值;

Cryptographic API 是密碼應用程序接口工具選項,以前的默認加密機制為MD5,近些年則該用了 SHA 機制,只要保留默認值就好了。

Kernel hacking默認值
Security options默認值
Cryptographic API默認值

虛擬化與函數庫

Virtualization,我們可以通過虛擬化技術在一部主機上同時啟動多個操作系統(tǒng)來運行,Linux內核已經主動的納入了虛擬化功能。而Linux認可的虛擬化使用的機制為 KVM(Kernel base Virtual Machine)。至于常用的內核函數庫也可以全部編譯為模塊。

Virtualization 默認值
鳥哥的

Library routines 保留默認的設置值就可以。

Library routines 默認值

在這些都設置完畢后,點擊 Save ,在出現的窗口中確認文件名為 .config,按下 OK,這樣剛剛的設置便被記錄下來了。接下來就可以準備進行編譯的行為啰!原來的 .config 文件會被更名為 .config.old。

無論如何,請記得隨時查看 Help那個選項來看一看內容,反正Kernel重新編譯的幾率不大!花一點時間重新編譯一次,然后將該編譯完成的參數文件儲存下來,未來可以直接將該文件拿來讀取!所以花一點時間安裝一次就好,這是相當值得的。


內核的編譯與安裝

將最復雜的內核功能選擇完畢后,接下來就是進行這些內核、內核模塊的編譯了。編譯完成后,就需要使用新內核。如何使用新內核呢?就得要考慮 grub 了。

編譯內核與內核模塊

可以使用 “ make help” 查詢所有可用的編譯參數。

make help
make help
make help

make vmlinux ? ?#未經壓縮的內核

make modules ? ?#僅內核模塊

make bzImage ? ?#經壓縮過的內核(默認),大寫的 i

make all? ? #進行上述三個動作,Build all targets marked with [*]?

我們常見的 /boot/ 下的內核文件,都是壓縮過的內核文件。因此,上訴動作中比較常用的是 modules 和 bzImage 這兩個。bzImage可以制作出壓縮過的內核,也就是一般我們拿來進行系統(tǒng)開機的信息。

/boot/

基本上我們會進行的動作是:

make -j 4 clean ? ?#先清除臨時文件

make -j 4 bzImage ? ?#先編譯內核

make -j 4 modules ? ?#再編譯模塊

## make -j 4 clean bzImage modules ? ?#連續(xù)動作

## -j [N], --jobs[=N] ? ? ? 同時允許 N 個任務;無參數表明允許無限個任務

## 為啥是 -j 4,因為我的主機有四個CPU核心,這幾個核心可以同時進行編譯行為,這樣在編譯時會比較快。如果CPU核心數有多個,那這里就寫成可用CPU數量。

編譯動作花費的時間依據你選擇的選項以及主機硬件的性能而不相同!

最后制作出來的資料是被放置在 /usr/src/kernels/linux-3.10.107/ 目錄下,還沒有被放到系統(tǒng)的相關路徑中哦!

在上面的編譯過程中,如果有發(fā)生任何錯誤的話,很可能是由于內核項目的選擇不夠好,可能就需要重新 make menuconfig 再次檢查一下你的相關設置。如果還是無法成功的話,那么或許要將原本的內核數據內的 .config 文件復制到內核源文件目錄下,然后加以修改,應該就可以順利編譯出內核。

最后,執(zhí)行完 make bzImage 命令后,最終結果應該會像這樣:

make bzImage

并且可以發(fā)現你的內核已經編譯好而且放置于 /usr/src/kernels/linux-3.10.107/arch/x86/boot/bzImage 里面,這就是我們的內核文件。最重要的就是它,我們等一下就會安裝這個文件!然后就是編譯模塊的部分。make modules 進行完畢后,就等著安裝了。

內核的編譯(make bzImage)和模塊的編譯(make modules)

實際安裝模塊

安裝模塊前有個地方要特別強調。我們知道模塊是放置到 /lib/modules/$(uname -r)/ 目錄下,那如果同一個版本(如3.10.107)的模塊被反復編譯安裝,會不會產生沖突呢?新版內核第一次編譯不會有這個問題!

重新編譯一次,那么這兩個版本一模一樣時,模塊放置的目錄也一樣,此時就會產生沖突了!有兩個解決方法:

方法1:先將舊的模塊目錄更名,然后才安裝內核模塊到目標目錄中去;

方法2:在 make menuconfig 時,將General setup內的Local version修改成新的名稱;

建議使用方法2,這樣,模塊放置的目錄名稱就不會相同,這樣也就能略過上述的目錄同名問題。

使用 make 命令安裝模塊到正確的目標目錄:

make modules_install

剛剛安裝的內核模塊

最終會在 /lib/modules/ 下建立起你這個內核的相關模塊哦!接下來就是要準備內核的安裝了。這個又與 grub2 有關。

開始安裝新內核與多重內核菜單(grub)

現在我們知道內核文件放置于 /usr/src/kernels/linux-3.10.107/arch/x86/boot/bzImage,但是其實系統(tǒng)內核理論上都是在 /boot/ 下,并且為 vmlinuz 開頭的文件名。此外,我們也知道一部主機是可以做成多重開機系統(tǒng)的!

所以,我們可以同時保留舊版的內核,并且新增新版的內核在我們的主機上面。

此外,與 grub1 不一樣,grub2 建議我們不要直接修改配置文件,而是通過讓系統(tǒng)自動檢測來處理grub.cfg 這個配置文件的內容。所以,在處理內核文件時,可能就得要知道內核文件的命名規(guī)則比較好!

grub2.cfg

移動內核到 /boot 且保留舊內核文件

保留舊內核最大的好處就是可以確保系統(tǒng)能夠順利開機。新內核編譯成功不代表就完全適用于目前的主機,可能有某些選項忘記選擇了,可能導致新內核無法順利驅動整個主機系統(tǒng),更糟糕的是可能主機無法成功開機。

內核文件通常以 vmlinuz 為開頭,后面跟上內核版本的文件格式。

復制新內核文件到 /boot/ 下并改名 vmlinuz-3.10.107,保留舊內核文件

cp ?/usr/src/kernels/linux-3.10.107/arch/x86/boot/bzImage ?/boot/vmlinuz-3.10.107


備份 .config 設置文件并改名 config-3.10.107

cp ?/usr/src/kernels/linux-3.10.107/.config ?/boot/config-3.10.107


給新內核文件添加 X 權限

chmod ?a+x ?/boot/vmlinuz-3.10.107


備份其他文件

cp? /usr/src/kernels/linux-3.10.107/System.map ?/boot/System.map-3.10.107

gzip -c? /usr/src/kernels/linux-3.10.107/Module.symvers ?> /boot/symvers-3.10.107



建立相對應的 Initial Ram Disk(initrd)

由于SATA磁盤支持的功能并沒有直接編譯到內核去,所以要使用 initramfs 來加載才行!

使用如下方法來建立 initramfs,記得要搭配正確的內核版本!

dracut ?-v ?/boot/initramfs-3.10.107.img ?3.10.107

## mkinitrd ?-v? /boot/initramfs-3.10.107.img? 3.10.107

## Usage: /sbin/dracut ?[ option ] ... [<initramfs> [<kernel-version>] ]

## -v ?Increase verbosity level



編輯開機選項(grub)

前面的文件大致上都擺放妥當之后,同時得根據你的內核版本來處理文件名。

使用 grub2-mkconfig 來處理你的 grub2 開機選項設置即可!

grub2-mkconfig ?-o ?/boot/grub2/grub.cfg

## -o, --output=文件? ? ? output generated config to FILE [default=stdout]

grub2-mkconfig

默認較新版本的內核會放在最前面成為默認的的開機選項,第一個被發(fā)現的內核要為你剛剛編譯好的內核文件才對!



重新以新內核開機、測試、修改

上述動作都成功后,接下來就是重新開機并選擇新內核來啟動系統(tǒng)啦!

uname -a ? ? #檢測內核



額外(單一)內核模塊的編譯

我們現在知道內核所支持的功能當中,有直接編譯到內核內部的,有使用外掛模塊的。外掛模塊可以想象成就是驅動程序。內核模塊依據不同的版本,被分別放置到 /lib/modules/$(uname -r)/kernel/ 下,硬件的驅動則是放置于 /lib/modules/$(uname -r)/kernel/drivers/ 下。

如果我想要忘記編譯某個驅動程序,或者是想要使用新的驅動程序,那該怎么辦?

編譯前注意事項

如果想要自行使用硬件開發(fā)商提供的模塊來進行編譯時,就需要使用到內核所提供的源文件當中的,所謂的 頭文件(header include file)來取得驅動模塊所需的一些函數庫或頭的定義。

也就是說,如果想要自行編譯內核模塊時,就得要擁有內核源代碼。

內核源代碼放置于 /usr/src/ 下。在2.6版本后,內核使用有趣的方法來設計它的源碼放置目錄。那就是以 /lib/modules/$(uname -r)/bulid 以及 /lib/modules/$(uname -r)/source 這兩個連接文件來指向正確的內核源碼防止目錄。

由于內核模塊的編譯其實與內核原本的源碼有點關系,因此如果你需要重新編譯模塊時,除了 make,gcc 等主要編譯工具外,還需要 kerner-devel 這個軟件。

單一模塊編譯

假設兩種情況:

1,如果我的默認內核忘記加入某個功能,而且該功能可以編譯成為模塊,不過,默認內核卻沒有將該項功能編譯成模塊,使得我們沒法使用,這怎么辦;

2,如果Linux的內核源碼并沒有某個硬件的驅動程序(module),但硬件廠商提供給Linux使用的驅動程序源碼,那我又該如何將該項功能編進內核模塊呢?

反正他們都需要內核提供的include表頭文件與函數庫。

硬件開發(fā)商提供的額外模塊

如果硬件廠商有提供驅動程序的話,直接下載源碼,重新編譯,將它放置到內核模塊該放置的地方后就能夠使用了!

看一下鳥哥的一個例子:

需要提醒一點,當自行編譯模塊時,若內核有更新(如利用自動更新的線上機制)時,則必須要重新編譯該模塊一次,重復上面的步驟才行!因為這個模塊僅針對目前的內核來編譯。

利用舊的內核源碼進行編譯

重新編譯模塊的話,先要進入源碼目錄, 執(zhí)行 make menuconfig,然后將 NTFS(栗子)的選項設定為模塊(M),之后執(zhí)行:

make fs/ntfs/

那么NTFS的模塊(ntfs.ko)就會自動被編譯出來了,然后將該模塊復制到 /lib/modules/3.10.107/kernel/fs/ntfs/ 目錄下,在執(zhí)行 depmod -a 就行了!

內核模塊的管理

內核和內核模塊是分不開的,至于驅動程序模塊在編譯的時候,更與內核的源碼分不開。因此,必須先了解到: 內核、內核模塊、驅動程序模塊、內核源碼與頭文件的相關性,然后才有辦法了解到為何編譯驅動程序的時候老是需要找到內核的源碼才能夠順利編譯!然后才會知道,為何內核更新之后,自己之前所編譯的模塊會失效。

此外,與內核模塊有關的,還有那個常被使用的 modprobe 命令,以及開機的時候會讀取到的模塊定義文件 /etc/modprobe.conf 。 這些資料也必須要了解才行。


重點回顧

內核就是系統(tǒng)上面的一個文件而已,這個文件包含了驅動主機各項硬件的檢測程序與驅動模塊;

內核模塊放置于 /lib/modules/$(uname -r)/kernel/;

驅動程序開發(fā)是屬于硬件廠商的問題;

由于系統(tǒng)已經將內核編譯的相當適合一般使用者,因此一般使用者基本不需要關系編譯內核;

編譯內核的一般目的:新功能的需求、原內核太過于臃腫,與硬件搭配的穩(wěn)定性以及其他需求;

編譯內核前,最好先了解主機硬件和主機用途,這樣才便于選擇內核功能;

編譯前若想保持內核源碼的干凈,可使用 make mrproper 來清除臨時文件等;

選擇內核功能與模塊可用make配合:menuconfig、odlconfig、xconfig、gconfig等;

內核功能選擇完畢后,一般編譯過程為: make bzImage,make modules;

模塊編譯成功后安裝:make modules_install;

內核的安裝過程中,需要移動 bzImage文件,建立 initramfs 文件,重建 grub.cfg等;

我們可以自行有硬件開發(fā)商官網下載驅動來自星編譯內核模塊;


內核編譯的步驟:

1,下載內核源碼;

2,解壓到 /usr/src/kernels/ 下;

3,make mrproper ;

4,make menuconfig 挑選功能;

5,make clean 清除過去的臨時文件;

6,make bzImage、make modules 編譯內核和模塊;

7,make modules_install 安裝內核模塊;

8,復制內核文件到 /boot/ 下;

9,建立 initramfs 文件;

10,grub2-mkconfig 修改/boot/grub2/grub.cfg 文件;


移除自行編譯的內核:

rm -rf /lib/modules/3.10.107

rm /boot/vmlinuz-3.10.107? /boot/initramfs-3.10.107.img

grub2-mkconfig -o /boot/grub2/grub.cfg


下面這種方法無法刪除自行編譯的內核,可以刪除升級后多余的內核:

uname -r? ? #查看內核版本

rpm -qa | grep kernel

yum remove kernel-3.x.xx

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容