欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
Linux驅動(dòng)編程必備基礎知識

驅動(dòng)程序是專(zhuān)用于控制和管理特定硬件設備的軟件,因此也被稱(chēng)作設備驅動(dòng)程序。從操作系統的角度來(lái)看,它可以位于內核空間(以特權模式運行),也可以位于用戶(hù)空間(具有較低的權限) 。

對于 Linux 驅動(dòng)程序來(lái)說(shuō),其運行在內核空間,把硬件功能提供給用戶(hù)程序。

本篇文章主要介紹Linux驅動(dòng)程序的一些基礎知識。后面的文章再逐步展開(kāi)。

內核空間和用戶(hù)空間

內核空間和用戶(hù)空間的概念有點(diǎn)抽象,主要涉及內存的訪(fǎng)問(wèn)權限。內核是有特權的,而用戶(hù)應用程序則是受限制的。

內核空間

內核駐留和運行的地址空間。

內核內存受訪(fǎng)問(wèn)標志保護,只能由內核訪(fǎng)問(wèn),用戶(hù)應用程不能訪(fǎng)問(wèn)。另一方面,內核可以訪(fǎng)問(wèn)整個(gè)系統內存,因為它在系統上以更高的優(yōu)先級運行。在內核模式下,CPU可以訪(fǎng)問(wèn)整個(gè)內存(內核空間和用戶(hù)空間)

用戶(hù)空間

用戶(hù)程序運行的地址空間。

在用戶(hù)模式下,CPU只能訪(fǎng)問(wèn)標有用戶(hù)空間訪(fǎng)問(wèn)權限的內存。用戶(hù)應用程序運行到內核空間的唯一方法是通過(guò)系統調用。

當進(jìn)程執行系統調用時(shí),軟件中斷被發(fā)送到內核,這將打開(kāi)特權模式,以便該進(jìn)程可以在內核空間中運行。系統調用返回時(shí),內核關(guān)閉特權模式,進(jìn)程再次受限。

模塊

Linux內核可以在運行時(shí)擴展。當系統運行時(shí),我們可以向內核添加、刪除功能。

可以在運行時(shí)添加到內核中的代碼被稱(chēng)為“模塊”。內核模塊是即插即用的,一旦插入就可以使用。

模塊要運行,應該先把它加載到內核,可以用 insmod 或 modprobe 來(lái)實(shí)現,前者需要指定模塊路徑作為參數,這是開(kāi)發(fā)期間的首選;后者更智能化,是生產(chǎn)系統中的首選。

insmod /test/mydrv.ko

常用的模塊卸載命令是 rmmod,使用該命令時(shí),應該把要卸載的模塊名作為參數向其傳遞。當卸載某個(gè)模塊時(shí),不會(huì )有其他影響,則會(huì )直接卸載;若有不良影響,內核會(huì )阻止這次卸載。

rmmod mymodule

或者使用下邊的指令

modeprobe -r mymodule

設備模塊分類(lèi)

Linux系統的模塊有三種基本類(lèi)型:

  • 字符模塊

  • 塊模塊

  • 網(wǎng)絡(luò )模塊

對應的設備設備驅動(dòng)程序:

  • 字符設備驅動(dòng)

  • 塊設備驅動(dòng)

  • 網(wǎng)絡(luò )設備驅動(dòng)

字符設備是個(gè)能夠像字節流一樣被訪(fǎng)問(wèn)的設備,由字符設備驅動(dòng)程序來(lái)實(shí)現。

塊設備每次只能傳輸一個(gè)或者多個(gè)完整的塊,每塊包含512字節(或者2的更高次冪字節的數據)。

網(wǎng)絡(luò )接口由內核中的網(wǎng)絡(luò )子系統驅動(dòng),負責發(fā)送和接收數據包。網(wǎng)絡(luò )驅動(dòng)程序不需要知道各個(gè)連接的相關(guān)信息,它只負責處理數據包即可。

當然還有其他劃分驅動(dòng)程序模塊的方法,此處不再贅述。

驅動(dòng)程序框架

Linux 驅動(dòng)程序是有固定框架的,我們按照既定的框架,填寫(xiě)內容即可。

先看一個(gè)簡(jiǎn)單的內核模塊程序 helloworld.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>

/* 模塊入口點(diǎn)函數 */
static int helloworld_init(void)
{
pr_info('Hello world!\n');
return 0;
}

/* 模塊出口點(diǎn)函數 */
static void helloworld_exit(void)
{
pr_info('End of the world\n');
}

/* 指定函數用途 */
module_init(helloworld_init);
module_exit(helloworld_exit);

MODULE_AUTHOR('zsky');
MODULE_LICENSE('GPL');

內核驅動(dòng)程序與用戶(hù)空間的程序是有很大區別的。

內核模塊驅動(dòng)程序有入口點(diǎn)和出口點(diǎn),函數名字可以任意。用戶(hù)程序的入口函數名稱(chēng)一般為 main()。

對于內核模塊程序來(lái)說(shuō),需要開(kāi)發(fā)人員指定入點(diǎn)和出點(diǎn)函數。在上例中,module_init()用于聲明模塊加載(使用 insmod 或 modprobe)時(shí)應該調用的函數為 helloworld_init,入口函數中要完成的操作是定義模塊的行為。

module_exit() 用于聲明模塊卸載(使用 rmmod )時(shí)應該調用的函數為  helloworld_exit。

模塊加載或者卸載后,init 函數或者 exit 函數立即運行一次。

在編寫(xiě)驅動(dòng)程序的時(shí)候,需要包含很多頭文件,以便獲取函數、數據類(lèi)型、變量的定義。有幾個(gè)頭文件是專(zhuān)門(mén)用于模塊的:

#include <linux/init.h>
#include <linux/module.h>

module.h包含可裝載模塊需要的大量符號和函數的定義。init.h 用于指定入口函數和出口函數。

模塊信息

內核模塊使用其 .modinfo 部分來(lái)存儲關(guān)于模塊的信息,所有MODULE_*宏都用參數傳遞的值更新這部分的內容 。

其中一些宏是 MODULE_DESCRIPTION()、MODULE_AUTHOR() 和 MODULE_LICENSE()。

MODULE_LICENSE() 告訴內核模塊采用何種許可,他對模塊行為有影響,如果與指定的許可不兼容將導致內核模塊被污染。

MODULE_AUTHOR() 用于聲明模塊的作者。

MODULE_DESCRIPTION() 簡(jiǎn)要描述模塊的功能。

錯誤和消息打印

在模塊函數處理過(guò)程中,一定要檢測返回值,確保所有的請求操作已經(jīng)真正成功。

當遇到錯誤時(shí),必須撤銷(xiāo)在這個(gè)錯誤發(fā)生之前的所有設置。通常的做法是使用goto語(yǔ)句。

ptr = kmalloc(sizeof (device_t));
if(!ptr)
{
  ret = -ENOMEM
  goto err_alloc;
}
ev = init(&ptr);
if(dev)
{
ret = -EIO
 goto err_init;
}
eturn 0;

err_init:
  free(ptr);
err_alloc:
  return ret;

若模塊裝載過(guò)程中出錯,要將出錯之前的任何注冊工作全部撤銷(xiāo),否則內核會(huì )處于一種不穩定的狀態(tài),因為內核中包含了一些指向并不存在的代碼內部指針。

錯誤有時(shí)會(huì )跨越內核空間,傳播到用戶(hù)空間。如果返回的錯誤是對系統調用(open、read、ioctl、mmap)的響應,則該值將自動(dòng)賦給用戶(hù)空間 errno 全局變量,在該變量上調用 strerror(errno) 可以將錯誤轉換為可讀字符串。

當返回指針的函數返回錯誤時(shí),通常返回的是NULL 指針。而去檢查為什么會(huì )返回空指針是沒(méi)有任何意義的,因為無(wú)法準確了解為什么會(huì )返回空指針。為此,內核提供了3個(gè)函數 ERR_PTR、IS_ERR 和 PTR_ERR:

void *ERR_PTR(long error);
long IS_ERR(const void *ptr);
long PTR_ERR(const void *ptr);

ERR_PTR 函數實(shí)際上把錯誤值作為指針?lè )祷?。假若函數在內存申請失敗后要執行語(yǔ)句 return -ENOMEM,則必須改為這樣的語(yǔ)句:return ERR_PTR (-ENOMEM);。

IS_ERR 函數用于檢查返回值是否是指針錯誤:if(IS_ERR(foo))。

PTR_ERR 函數返回實(shí)際錯誤代碼:return PTR_ERR(foo);。

消息打印--printk()

不同于用戶(hù)空間的 printf()函數。printk()是在內核空間使用的,其作用和在用戶(hù)空間使用 printf() 一樣,執行 dmesg 命令可以顯示 printk() 寫(xiě)入的信息。

根據所打印消息的重要性不同,可以選用 include/linux/kern_levels.h 中定義的八個(gè)級別的日志消息,每個(gè)級別對應iyge字符串格式的數字,其優(yōu)先級與該數字的值成反比:

#define KERN_SOH '\001'  /* ASCII頭開(kāi)始 */
#define KERN_SOH_ASCII '\001'

#define KERN_EMERG KERN_SOH   '0'   /* 系統不可用*/
#define KERN_ALERT KERN_SOH   '1'   /* 必須立即采取行動(dòng)*/
#define KERN_CRIT KERN_SOH     '2'   /* 重要條件*/
#define KERN_ERR KERN_SOH     '3'   /* 錯誤條件*/
#define KERN_WARNING KERN_SOH '4'   /* 警報條件*/
#define KERN_NOTICE KERN_SOH   '5'   /* 正常但重要的情況*/
#define KERN_INFO KERN_SOH     '6'   /* 信息 */
#define KERN_DEBUG KERN_SOH   '7'   /* 調試級別消息 */

舉例:

printk(KERN_ERR 'This is an error\n');

實(shí)際上可以使用以下宏,其名稱(chēng)更有意義,它們是對前面所定義內容的包裝—— pr_emerg、pr_alert、pr_crit、pr_err、pr_warning、pr_notice、pr_info和 pr_debug。

printk() 的實(shí)現是這樣的:調用它時(shí),內核會(huì )將消息日志級別與當前控制臺的日志級別進(jìn)行比較;如果前者比后者更高(值更低),則消息會(huì )立即打印到控制臺。

模塊參數

像用戶(hù)程序一樣,內核模塊也可以接收命令行參數。這樣能夠根據給定的參數動(dòng)態(tài)地改變模塊的行為,開(kāi)發(fā)者不必在測試/調試期間無(wú)限期地修改/編譯模塊。 

為了對此進(jìn)行設置,首先應該聲明用于保存命令行參數值的變量,并在每個(gè)變量上使用 module_param() 宏:

module_param(name, type, perm);
  • name:用作參數的變量的名稱(chēng)。

  • type:參數的類(lèi)型(bool、charp、byte、short、ushort、int、uint、long、ulong),其中 charp 代表字符指針。

  • perm:代表/sys/module/<module>/parameters/<param>文件的權限,其中包括S_IWUSR、S_IRUSR、S_IXUSR、S_IRGRP、S_WGRP和S_IRUGO 。

當使用模塊參數時(shí),應該用 MODULE_PARM_DESC 描述每個(gè)參數。這個(gè)宏將把每個(gè)參數的描述填充到模塊信息部分。

舉例:

module_param(myint, int, S_IRUGO);
module_param(mystr, charp, S_IRUGO);
module_param_array(myarr, int,NULL, S_IWUSR|S_IRUSR);

MODULE_PARM_DESC(myint,'this is my int variable');
MODULE_PARM_DESC(mystr,'this is my char pointer variable');
MODULE_PARM_DESC(myarr,'this is my array of int');

要在加載該模塊時(shí)提供參數,請執行以下操作:

# insmod hellomodule-params.ko 
mystring='packtpub' myint=15 myArray=1,2,3

在加載模塊之前,執行modinfo可以顯示該模塊支 持的參數說(shuō)明:

modinfo ./helloworld-params.ko

好了,感謝閱讀。加油~

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
【百度分享】基于內核模塊的測試代碼編寫(xiě)(一)
2.6內核模塊的編寫(xiě)框架和編譯方法
ldd3之模塊學(xué)習總結(頁(yè) 1) - 文檔專(zhuān)區 - 無(wú)分類(lèi)文檔 - Linux論壇 - p...
小白學(xué)Linux之內核模塊編程-tiger
內核模塊編譯說(shuō)明
linux驅動(dòng)程序開(kāi)發(fā)詳細介紹
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久