這篇文章將為大家詳細(xì)講解有關(guān)Linux內(nèi)核編譯與開(kāi)發(fā)的示例分析,小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛(ài)。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶,將通過(guò)不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:國(guó)際域名空間、網(wǎng)站空間、營(yíng)銷軟件、網(wǎng)站建設(shè)、海鹽網(wǎng)站維護(hù)、網(wǎng)站推廣。
一.Linux內(nèi)核簡(jiǎn)介
linux kernel map:
linux 系統(tǒng)體系結(jié)構(gòu):
linux kernel體系結(jié)構(gòu):
arm有7種工作模式,x86也實(shí)現(xiàn)了4個(gè)不同級(jí)別RING0-RING3,RING0級(jí)別***,
這樣linux用戶代碼運(yùn)行在RING3下,內(nèi)核運(yùn)行在RING0,這樣系統(tǒng)本身就得到了
充分的保護(hù)
用戶空間(用戶模式)轉(zhuǎn)到內(nèi)核空間(系統(tǒng)模式)方法:
系統(tǒng)調(diào)用
硬件中斷
linux kernel 體系結(jié)構(gòu):
虛擬文件系統(tǒng)VFS:
VFS(虛擬文件系統(tǒng))隱藏各種文件系統(tǒng)的具體細(xì)節(jié),為文件操作提供統(tǒng)一的接口
二.Linux內(nèi)核源代碼
linux內(nèi)核下載www.kernel.org
目錄結(jié)構(gòu):
解壓linux kernel tar后目錄
arch:根據(jù)cpu體系結(jié)構(gòu)不同而分的代碼
block:部分塊設(shè)備驅(qū)動(dòng)程序
crypto:加密,壓縮,CRC校驗(yàn)算法
documentation:內(nèi)核文檔
drivers:設(shè)備驅(qū)動(dòng)程序
fs(虛擬文件系統(tǒng)vfs):文件系統(tǒng)
include:內(nèi)核所需的頭文件,(與平臺(tái)無(wú)關(guān)的頭文件在include/linux中)
lib:庫(kù)文件代碼(與平臺(tái)相關(guān)的)
mm:實(shí)現(xiàn)內(nèi)存管理,與硬件體系結(jié)構(gòu)無(wú)關(guān)的(與硬件體系結(jié)構(gòu)相關(guān)的在arch中)
net:網(wǎng)絡(luò)協(xié)議的代碼
samples:一些內(nèi)核編程的范例
scripts:配置內(nèi)核的腳本
security:SElinux的模塊
sound:音頻設(shè)備的驅(qū)動(dòng)程序
usr:cpio命令實(shí)現(xiàn),用于制作根文件系統(tǒng)的命令(文件系統(tǒng)與內(nèi)核放到一塊的命令)
virt:內(nèi)核虛擬機(jī)
linux DOC 編譯生成:
linux源根目錄/Documentation/00-INDEX:目錄索引
linux源根目錄/Documentation/HOWTO:指南
生成linux內(nèi)核幫助文檔:在linux源根目錄(Documentation) 執(zhí)行make htmldocs
ubuntu16下需要執(zhí)行sudo apt-get install xmlto安裝插件才可生成doc文檔
后面開(kāi)發(fā)中經(jīng)常要改的是arch,drivers中的代碼
三.Linux內(nèi)核配置與編譯
清理文件(在linux源碼根目錄):
make clean:只清理所有產(chǎn)生的文件
make mrproper:清理所有產(chǎn)生的文件與config配置文件
make distclean:清理所有產(chǎn)生的文件與config配置文件,并且編輯過(guò)的與補(bǔ)丁文件
配置(收集硬件信息如cpu型號(hào),網(wǎng)卡等...):
make config:基于文本模式的交互配置
make menuconfig:基于文本模式的菜單模式(推薦使用)
make oldconfig:使用已有的.config,但會(huì)詢問(wèn)新增的配置項(xiàng)
make xconfig:圖形化的配置(需要安裝圖形化系統(tǒng))
配置方法:
1)使用make menuconfig操作方法:
1>按y:編譯>連接>鏡像文件
2>按m:編譯
3>按n:什么都不做
4>按"空格鍵":y,n輪換
配置完并保存后會(huì)在linux源碼根目錄下生成一個(gè).config文件
注意:在ubuntu11上要執(zhí)行apt-get install libncurses5-dev來(lái)安裝支持包
2)利用已有的配置文件模板(.config)
1>linux源碼根目錄/arch/
2>利用當(dāng)前運(yùn)行已有的文件(要用ls /boot/ -a查看)把/boot/config-2.6.18-53.e15拷貝并改名為.config至linux源碼根目錄下執(zhí)行以上操作就可以用make menuconfig在拷貝
.config文件上面修改文件了
編譯內(nèi)核:
1)make zImage
2)make bzImage
區(qū)別:在X86平臺(tái)上,zimage只能用于小于512k的內(nèi)核
獲取詳細(xì)編譯信息:make zimage V=1 或 make bzimage V=1
編譯好的內(nèi)核在:arch/
注意:在把.config配置文件cp到根目錄編譯內(nèi)核前,必須進(jìn)入make menuconfig并保存退出(否則生不了效)
編譯并安裝模塊:
1)編譯內(nèi)核模塊:make modules
2)安裝內(nèi)核模塊:make modules_install INSTALL_MOD_PATH=/lib/modules
更換本機(jī)器內(nèi)核:將編譯好的內(nèi)核模塊從內(nèi)核源碼目錄copy至/lib/modules下
制作init ramdisk():輸入執(zhí)行命令mkinitrd initrd-2.6.39(任意) 2.6.39(可通過(guò)查詢/lib/modules下的目錄得到)
注意:
mkinitrd命令為redhat里面的,ubuntu的命令為:mkinitramfs -k /lib/modules/模塊安裝位置 -o initrd-2.6.39(任意) 2.6.39(可通過(guò)查詢/lib/modules下的目錄得到)
如果ubuntu里面沒(méi)有mkinitramfs命令可以用apt-get install initrd-tools進(jìn)行安裝
安裝內(nèi)核模塊:
1)手動(dòng)
1>cp linux根目錄/arch/x86/boot/bzImage /boot/mylinux-2.6.39
2>cp linux根目錄/initrd-2.6.39 /boot/initrd-2.6.39
***修改/etc/grub.conf或/etc/lilo.conf文件
2)自動(dòng)
1>make install:這個(gè)命令會(huì)自動(dòng)完成上面的操作(查看當(dāng)前內(nèi)核版本:uname -r)
-----------------------------------------------------------------------------
四.linux內(nèi)核模塊開(kāi)發(fā)
描述:
linux內(nèi)核組件非常龐大,內(nèi)核ximage并不包含某組件,而是在該組件需要被使用的時(shí)候,動(dòng)態(tài)的添加到正在運(yùn)行的內(nèi)核中(也可以卸載),這種機(jī)制叫做“內(nèi)核模塊”的機(jī)制。內(nèi)核模塊通常通過(guò)使用makefile文件對(duì)模塊進(jìn)行編譯
模塊安裝與卸載:
1)加載:insmod hello.ko
2)卸載:rmmod hello
3)查看:lsmod
4)加載(自動(dòng)尋找模塊依賴):modprobe hello
modprobe會(huì)根據(jù)文件/lib/modules/version/modules.dep來(lái)查看要加載的模塊,看它是否還依賴于其他模塊,如果是,會(huì)先找到這些模塊,把它們先加載到內(nèi)核
實(shí)例分析:
1)moduleDep/1(一個(gè)模塊的編譯)
1 #include2 #include 3 4 //模塊入口函數(shù) 5 //__init:表示代碼段中的子段,里面的內(nèi)容只運(yùn)行一次并且回收內(nèi)存. 6 static int __init hello_init(void) 7 { 8 printk(KERN_EMERG "hello world!\n"); 9 return 0;10 }11 //模塊卸載函數(shù)12 //__exit:13 static void __exit hello_exit(void)14 {15 printk(KERN_EMERG "hello exit!\n");16 }17 //內(nèi)核符號(hào)導(dǎo)出 函數(shù)18 int add_integar(int a,int b)19 {20 return a+b; 21 }22 int sub_integar(int a,int b)23 {24 return a-b; 25 }26 27 module_init(hello_init);28 module_exit(hello_exit);29 //函數(shù)導(dǎo)出30 EXPORT_SYMBOL(add_integar);31 EXPORT_SYMBOL(sub_integar);
makefile:
#***次執(zhí)行KERNELRELEASE是空的,所以執(zhí)行else里面的 ifneq ($(KERNELRELEASE),) obj-m :=hello.o #else塊 elseKDIR:= /lib/modules/2.6.18-53.el5/build all: #KDIR 依賴內(nèi)核模塊源代碼路徑(內(nèi)核編譯安裝路徑) #PWD 表示內(nèi)核代碼在哪(當(dāng)前目錄) #modules 編譯的是模塊 make -C $(KDIR) M=$(PWD) modules clean: rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.order endif
2)moduleDep/2(兩個(gè)模塊的編譯)
#include#include //模塊可選信息 MODULE_LICENSE("GPL");//許可證聲明 MODULE_AUTHOR("liyuan");//作者聲明 MODULE_DESCRIPTION("This module is a param example.");//模塊描述 MODULE_VERSION("V1.0");//模塊別名 MODULE_ALIAS("a simple module");//模塊別名 //模塊參數(shù) static char *name = "liyuan arg"; static int age = 30; //S_IRUGO是參數(shù)權(quán)限,也可以用數(shù)字 module_param(age,int,S_IRUGO); module_param(name,charp,S_IRUGO); //使用外部文件函數(shù) extern int add(int a,int b); //聲明 外部?jī)?nèi)核符號(hào) 函數(shù) extern int add_integar(int a,int b); extern int sub_integar(int a,int b); static int __init mains_init(void) { //多文件編譯 printk(KERN_EMERG"param hi"); int vle=add(1,2); printk(KERN_EMERG"add value:%d\n",vle); //模塊參數(shù) printk(KERN_EMERG" name : %s\n",name); printk(KERN_EMERG" age : %d\n",age); //使用其他模塊的函數(shù)(內(nèi)核符號(hào)導(dǎo)出) int adds=add_integar(3,1); int subs=sub_integar(3,1); printk(KERN_EMERG" add_integar : %d\n",adds); printk(KERN_EMERG" sub_integar : %d\n",subs); return 0; } static void __exit mains_exit(void) { printk("param exit!"); } module_init(mains_init);52 module_exit(mains_exit);
add.c
int add(int a,int b) { return a+b; }
makefile
ifneq ($(KERNELRELEASE),) #兩個(gè)以上內(nèi)核源文件 生成單獨(dú)的內(nèi)核模塊名ma #內(nèi)核ma obj-m :=ma.o #下面的ma-objs前面必須和上面一樣為ma ma-objs := mains.o add.oelseKDIR:= /lib/modules/2.6.18-53.el5/build all: make -C $(KDIR) M=$(PWD) modules clean: rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.order endif
運(yùn)行帶參模塊:insmod hello.ko name=yuan age=12
內(nèi)核符號(hào)導(dǎo)出(/proc/kallsyms記錄了內(nèi)核中所有導(dǎo)出的符號(hào)的名字與地址):
一個(gè)內(nèi)核模塊的運(yùn)行依賴另一個(gè)內(nèi)核模塊的函數(shù)實(shí)現(xiàn),必須先運(yùn)行***個(gè)內(nèi)核模塊,這樣就需要進(jìn)行內(nèi)核符號(hào)導(dǎo)出。
注意:
錯(cuò)誤信息:disagrees about version of symbol struct_module insmod:error inserting ...
開(kāi)發(fā)內(nèi)核模塊時(shí)會(huì)出現(xiàn),內(nèi)核模塊不匹配的情況.是你當(dāng)前運(yùn)行的linux內(nèi)核與編譯連接所依賴的
內(nèi)核版本不匹配,解決方法:
使用modprobe --force-modversion強(qiáng)行插入
可使用uname -r進(jìn)行查看當(dāng)前運(yùn)行的內(nèi)核版本
printk內(nèi)核打印:
在
KERN_EMERG 0
用于緊急的消息,常常是那些崩潰的消息
KERN_ALERT 1
需要立刻行動(dòng)的消息
KERN_CRIT 2
嚴(yán)重情況
KERN_ERR 3
錯(cuò)誤情況
KERN_WARNING(printk默認(rèn)級(jí)別) 4
有問(wèn)題的警告
KERN_NOTICE 5
正常情況,但是仍然值得注意
KERN_INFO 6
信息消息
KERN_DEBUG 7
用作調(diào)試消息
不管是哪個(gè)級(jí)別的都會(huì)在/var/log/messages里面打印出來(lái)(messages可以刪除后,運(yùn)行內(nèi)核進(jìn)行測(cè)試內(nèi)核打印情況)控制臺(tái)打印(優(yōu)先級(jí)配置/proc/sys/kernel/printk)
6 4 1 7
Console_loglevel
Default_message_loglevel
Minimum_console_level
Default_console_loglevel
在vm+redhat安裝2.6.39內(nèi)核時(shí)出現(xiàn)的錯(cuò)誤
啟動(dòng)時(shí)報(bào)could not find filesystem '/dev/root'
解決方法
a.通過(guò)make menuconfig選中以下對(duì)應(yīng)的選項(xiàng)
General setup -->
[*] enable deprecated sysfs features to support old userspace tools
成功時(shí)下面那個(gè)也*了的
b.修改.config文件
修改.config文件中CONFIG_SYSFS_DEPRECATED_V2,將原本被注釋掉的
CONFIG_SYSFS_DEPRECATED_V2 改成CONFIG_SYSFS_DEPRECATED_V2=y
關(guān)于“Linux內(nèi)核編譯與開(kāi)發(fā)的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。