這篇文章主要介紹“Linux模塊文件如何編譯到內(nèi)核和獨(dú)立編譯成模塊”,在日常操作中,相信很多人在Linux模塊文件如何編譯到內(nèi)核和獨(dú)立編譯成模塊問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Linux模塊文件如何編譯到內(nèi)核和獨(dú)立編譯成模塊”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!
創(chuàng)新互聯(lián)公司專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于做網(wǎng)站、成都做網(wǎng)站、雙城網(wǎng)絡(luò)推廣、微信小程序定制開發(fā)、雙城網(wǎng)絡(luò)營銷、雙城企業(yè)策劃、雙城品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營等,從售前售中售后,我們都將竭誠為您服務(wù),您的肯定,是我們最大的嘉獎;創(chuàng)新互聯(lián)公司為所有大學(xué)生創(chuàng)業(yè)者提供雙城建站搭建服務(wù),24小時服務(wù)熱線:18982081108,官方網(wǎng)址:muchs.cn
Linux內(nèi)核源代碼非常龐大,隨著版本的發(fā)展不斷增加。它使用目錄樹結(jié)構(gòu),并且使用Makefile組織配置、編譯。
初次接觸Linux內(nèi)核,好仔細(xì)閱讀頂層目錄的readme文件,它是Linux內(nèi)核的概述和編譯命令說明。readme的說明側(cè)重于X86等通用的平臺,對于某些特殊的體系結(jié)構(gòu),可能有些特殊的說明。
頂層目錄的Makefile是整個內(nèi)核配置編譯的核心文件,負(fù)責(zé)組織目錄樹中子目錄的編譯管理,還可以設(shè)置體系結(jié)構(gòu)和版本號等。
內(nèi)核源碼的頂層有許多子目錄,分別組織存放各種內(nèi)核子系統(tǒng)或者文件。具體的目錄說明如下表所示。
1.make mrproper: 清除內(nèi)核生成的配置文件與目標(biāo)文件等,一般在第一次編譯時使用
2.導(dǎo)入默認(rèn)配置信息(在內(nèi)核根目錄中)
a) make xxx_deconfig b) cp arch/arm/configs/xx_deconfig .config 生成默認(rèn)配置文件
3.配置命令
make xxxxconfig 修改配置文件 make xconfig (圖形界面 qt庫) make menuconfig (常用 libncurses庫) sudo apt-get install libncurses5-dev make config (精簡)
4.編譯內(nèi)核
make uImage ---生成內(nèi)核鏡像 /arch/arm/boot/uImage
5.編譯設(shè)備樹
make dtbs ---生成設(shè)備樹文件 /arch/arm/boot/dtb/xxxxxx.dtb
6.編譯生成模塊文件
make modules ---把配置值選成M的代碼編譯生成模塊文件。(.ko) 放在對應(yīng)的源碼目錄下。
現(xiàn)在很多基于Linux的產(chǎn)品開發(fā),通常廠家都會提供集成開發(fā)環(huán)境SDK。builroot使我們搭建環(huán)境變得更加方便,但是作為初學(xué)者我們還是要掌握如何獨(dú)立編譯內(nèi)核源碼。
必須先安裝交叉編譯工具鏈,關(guān)于交叉編譯工具鏈的安裝可以參考 《linux環(huán)境搭建-ubuntu16.04安裝》
在這里我們使用的是arm-none-linux-gnueabi-gcc。
下載地址:https://mirrors.edge.kernel.org/pub/linux/kernel/
我們下載Linux-3.14內(nèi)核(可以是更高的版本)至/home/peng目錄。
或者直接點(diǎn)擊下面鏈接 https://mirrors.edge.kernel.org/pub/linux/kernel/v3.x/linux-3.14.10.tar.xz
解開壓縮包,并進(jìn)入內(nèi)核源碼目錄,具體過程如下:
$ tar xvf linux-3.14.tar.xz $ cd linux-3.14
$ vim Makefile
找到ARCH和CROSS_COMPILE, 修改:
ARCH ?= $(SUBARCH) CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)
為
ARCH ?= arm CROSS_COMPILE ?= arm-none-linux-gnueabi-
導(dǎo)入默認(rèn)配置
$ make exynos_defconfig
這里我們假定要編譯的內(nèi)核最終在三星的板子上運(yùn)行,soc名字是exynos,三星公司其實已經(jīng)將自己的配置文件放置在 ./arch/arm/configs/exynos_defconfig
執(zhí)行這個命令,最終會在內(nèi)核根目錄下生成.config文件,
我們編譯內(nèi)核就完全依賴這個文件。該文件是exynos開發(fā)板所需要的一些內(nèi)核模塊宏定義和參數(shù)設(shè)置,這些值是廠商給的一個初始配置。實際項目開發(fā)中,需要在這個配置文件基礎(chǔ)之上再重新移植自己需要的對應(yīng)的驅(qū)動模塊。
輸入內(nèi)核配置命令,進(jìn)行內(nèi)核選項的選擇,命令如下:
$ make menuconfig
命令執(zhí)行成功以后,會看到如下圖所示的界面。其實我們在圖1.5中看到過同樣功能的界面,那個圖也是內(nèi)核選項配置界面,只不過那個界面在X-window下才能執(zhí)行。
其中:
1.子菜單--->
表示有子菜單,按下回車可以進(jìn)入子菜單。
2.中括號[] 在每一個選項前都有個括號,有的是中括號,有的是尖括號,還有的是圓括號。
[] 表示該選項只有兩種選項,中括號中要么是空,要么是“*”;
用空格鍵可以做出選擇。
3.尖括號<>
<>選擇相應(yīng)的配置時,有3種選擇,它們代表的含義分別如下。
● *:將該功能編譯進(jìn)內(nèi)核。 ● 空:不將該功能編譯進(jìn)內(nèi)核。 ● M:將該功能編譯成可以在需要時動態(tài)插入到內(nèi)核中的模塊。
4.模塊配置圓括號() 而圓括號的內(nèi)容是要你在所提供的幾個選項中選擇一項。
如果使用的是make xconfig,使用鼠標(biāo)就可以選擇對應(yīng)的選項。如果使用的是make menuconfig,則需要使用回車鍵進(jìn)行選取。
在編譯內(nèi)核的過程中,麻煩的事情就是配置這步工作了。初次接觸Linux內(nèi)核的開發(fā)者往往弄不清楚該如何選取這些選項。
實際上,在配置時,大部分選項可以使用其默認(rèn)值,只有小部分需要根據(jù)用戶不同的需要選擇。
選擇的原則是將與內(nèi)核其他部分關(guān)系較遠(yuǎn)且不經(jīng)常使用的部分功能代碼編譯成為可加載模塊,這有利于減小內(nèi)核的長度,減少內(nèi)核消耗的內(nèi)存,簡化該功能相應(yīng)的環(huán)境改變時對內(nèi)核的影響;不需要的功能就不要選;與內(nèi)核關(guān)系緊密而且經(jīng)常使用的部分功能代碼直接編譯到內(nèi)核中。
5)編譯內(nèi)核:
root@ubuntu:/home/peng/linux-3.14# make uImage
uImage
如果按照默認(rèn)的配置,沒有改動的話,編譯后系統(tǒng)會在arch/arm/boot目錄下生成一個uImage文件,這個文件就是剛剛生成的。
因為不同的板子對應(yīng)的uboot版本都不一樣,所以下載程序的uboot命令也會有所差異,關(guān)于驗證,本文暫不討論。
假定我們有以下驅(qū)動程序,要編譯成可以加載到開發(fā)板的獨(dú)立ko文件
hello.c
#include <linux/init.h> #include <linux/module.h> #include <linux/kdev_t.h> #include <linux/fs.h> #include <linux/cdev.h> //#include <io/uaccess.h> #include <linux/device.h> #include <asm/io.h> #include <asm/uaccess.h> static int major = 237; static int minor = 0; static dev_t devno; struct device *class_dev = NULL; struct class *cls; static int hello_open (struct inode *inode, struct file *filep) { printk("hello_open()\n"); return 0; } static int hello_release (struct inode *inode, struct file *filep) { printk("hello_release()\n"); return 0; } #define KMAX_LEN 32 char kbuf[KMAX_LEN+1] = "kernel"; //read(fd,buff,40); static ssize_t hello_read (struct file *filep, char __user *buf, size_t size, loff_t *pos) { int error; if(size > strlen(kbuf)) { size = strlen(kbuf); } if(copy_to_user(buf,kbuf, size)) { error = -EFAULT; return error; } return size; } //write(fd,buff,40); static ssize_t hello_write (struct file *filep, const char __user *buf, size_t size, loff_t *pos) { int error; if(size > KMAX_LEN) { size = KMAX_LEN; } memset(kbuf,0,sizeof(kbuf)); if(copy_from_user(kbuf, buf, size)) { error = -EFAULT; return error; } printk("%s\n",kbuf); return size; } static struct file_operations hello_ops = { .open = hello_open, .release = hello_release, .read = hello_read, .write = hello_write, }; static int hello_init(void) { int result; printk("hello_init \n"); result = register_chrdev( major, "hello", &hello_ops); if(result < 0) { printk("register_chrdev fail \n"); return result; } cls = class_create(THIS_MODULE, "hellocls"); if (IS_ERR(cls)) { printk(KERN_ERR "class_create() failed for cls\n"); result = PTR_ERR(cls); goto out_err_1; } devno = MKDEV(major, minor); class_dev = device_create(cls, NULL, devno, NULL, "hellodev"); if (IS_ERR(class_dev)) { result = PTR_ERR(class_dev); goto out_err_2; } return 0; out_err_2: class_destroy(cls); out_err_1: unregister_chrdev(major,"hello"); return result; } static void hello_exit(void) { printk("hello_exit \n"); device_destroy(cls, devno); class_destroy(cls); unregister_chrdev(major,"hello"); return; } module_init(hello_init); module_exit(hello_exit); MODULE_LICENSE("GPL"); //proc/devices
注意我們需要編寫Makefile如下:
ifneq ($(KERNELRELEASE),) obj-m:=hello.o else KDIR :=/home/peng/linux-3.14 PWD :=$(shell pwd) all: make -C $(KDIR) M=$(PWD) modules clean: rm -f *.ko *.o *.mod.o *.symvers *.cmd *.mod.c *.order endif
關(guān)于Makefile的詳解,大家可以參考我們之前的文章 《手把手教Linux驅(qū)動1-模塊化編程》 其中內(nèi)核路徑:
KDIR :=/home/peng/linux-3.14
必須是我們剛才編譯過的內(nèi)核源碼根目錄。
編譯時,程序可以放到其他目錄下:
用file命令查看文件屬性,是基于ARM的。該模塊文件就是與前面編譯的內(nèi)核配套的驅(qū)動模塊,如果開發(fā)板的內(nèi)核版本與上面編譯的版本號一致,那么該模塊文件就可以在開發(fā)板上insmod。
步驟:
1)拷貝文件 如果要將剛才的驅(qū)動程序直接編譯到內(nèi)核,那么我們必須把hello.c拷貝到內(nèi)核的某個目錄下。
字符設(shè)備可以考慮放到以下目錄:
linux-3.14/drivers/char
2)修改Makefile
root@ubuntu:/home/peng/linux-3.14/drivers/char# vim Makefile
修改如下:
該行內(nèi)容是根據(jù)宏CONFIG_HELLO來決定是否編譯hello.c這個文件。
3)修改Kconfig
7 HELLO 取前面步驟CONFIG_HELLO下劃線后面的字符串 8 tristate 表示該模塊最終有3個選項 空 * M 9 表示該模塊依賴的模塊,如果ARCH_EXYNOS4模塊沒有被選中,那么HELLO模塊也不會被編譯到內(nèi)核 10 幫助信息
4) 重新配置 執(zhí)行
make menuconfig
進(jìn)入配置頁面,
輸入 / 可以根據(jù)關(guān)鍵字查找模塊所在位置。
我們添加的模塊文件的位置:
根據(jù)路徑
-> Device Drivers -> Character devices
找到我們剛才的模塊配置路徑
此處是尖括號,因為我們設(shè)置的屬性是tristate
移動到Help處,可以看到前面我們填充的幫助信息
我們可以按下空格鍵設(shè)置為*,編譯到內(nèi)核中。
選擇Save,
然后再點(diǎn)擊2次Exit,就可以退出。
5)重新編譯內(nèi)核
root@ubuntu:/home/peng/linux-3.14# make uImage
這樣,我們的模塊編譯到了新生成的內(nèi)核模塊文件中。
前面一節(jié)其實最終目的是生成CONFIG_HELLO=y 這個定義信息,并把該信息保存到內(nèi)核根目錄的.config文件中。
其實我們?nèi)绻恍薷腒config,直接在.config中增加這個宏定義也是可以的。
今天內(nèi)容就到這里,還等什么?抓緊操練起來吧。
文中用到的虛擬機(jī),叫交叉編譯工具,還有源代碼,
到此,關(guān)于“Linux模塊文件如何編譯到內(nèi)核和獨(dú)立編譯成模塊”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
文章題目:Linux模塊文件如何編譯到內(nèi)核和獨(dú)立編譯成模塊
文章起源:http://muchs.cn/article2/igeoic.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供App開發(fā)、面包屑導(dǎo)航、定制網(wǎng)站、微信公眾號、企業(yè)建站、Google
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)