RK3568驅動(dòng)指南|第二篇 字符設備基礎-第14章 內核空間與用戶(hù)空間數據交互實(shí)驗
第14章 內核空間與用戶(hù)空間數據交互實(shí)驗
在“第12章 字符設備驅動(dòng)框架實(shí)驗”中,已經(jīng)對file_operations結構體的進(jìn)行了填充,該結構體的每一個(gè)成員都對應著(zhù)一個(gè)系統調用,例如read、write等,在對應的實(shí)驗中,只是對調用函數進(jìn)行了標志打印,并沒(méi)有真正實(shí)現設備的讀寫(xiě)功能,而在本章節將對內核空間與用戶(hù)空間的數據交換功能進(jìn)行實(shí)現。
14.1 內核空間與用戶(hù)空間
Linux系統將可訪(fǎng)問(wèn)的內存空間分為了兩個(gè)部分,一部分是內核空間,一部分是用戶(hù)空間。操作系統和驅動(dòng)程序運行在內核空間(內核態(tài)),應用程序運行在用戶(hù)空間(用戶(hù)態(tài))。
那么為什么要區分用戶(hù)空間和內核空間呢?
(1)內核空間中的代碼控制了硬件資源,用戶(hù)空間中的代碼只能通過(guò)內核暴露的系統調用接口來(lái)使用系統中的硬件資源,這樣的設計可以保證操作系統自身的安全性和穩定性。
(2)從另一方面來(lái)說(shuō),內核空間的代碼更偏向于系統管理,而用戶(hù)空間中的代碼更偏重業(yè)務(wù)邏輯實(shí)現,倆者的分工不同。
硬件資源管理都是在內核空間完成的,應用程序無(wú)法直接對硬件進(jìn)行操作,只能通過(guò)調用相應的內核接口來(lái)完成相應的操作。比如應用程序要對磁盤(pán)上的一個(gè)文件進(jìn)行讀取,應用程序可以向內核發(fā)起一個(gè)“系統調用”申請——我要讀取磁盤(pán)上的文件。這個(gè)過(guò)程其實(shí)是通過(guò)一個(gè)特殊的指令讓進(jìn)程從用戶(hù)態(tài)進(jìn)入到了內核態(tài)。在內核空間中,CPU可以執行任何命令,包括從磁盤(pán)上讀取數據,具體過(guò)程是先把數據讀取到內核空間中,然后再把數據拷貝到用戶(hù)空間并從內核態(tài)切換到用戶(hù)態(tài)。此時(shí)應用程序已經(jīng)從系統調用中返回并拿到了想要的數據,可以繼續往下執行了。
進(jìn)程只有從用戶(hù)空間切換到內核空間才可以使用系統的硬件資源,切換的方式有三種:系統調用,軟中斷,硬中斷,如下圖(圖 14-1)所示:
14.2 用戶(hù)空間和內核空間數據交換
內核空間和用戶(hù)空間的內存是不能互相訪(fǎng)問(wèn)的。但是很多應用程序都需要和內核進(jìn)行數據的交換,例如應用程序使用read函數從驅動(dòng)中讀取數據,使用write函數向驅動(dòng)中寫(xiě)數據,上述功能就需要使用copy_from_user和copy_to_user倆個(gè)函數來(lái)完成。copy_from_user函數是將用戶(hù)空間的數據拷貝到內核空間。copy_to_user函數是將內核空間的數據拷貝到用戶(hù)空間。
這倆個(gè)函數定義在了kernel/include/linux/uaccess.h文件下,如下所示:
copy_to_user
函數原型:
unsigned long copy_to_user_inatomic(void __user *to, const void
*from, unsigned long n);
函數作用:
把內核空間的數據復制到用戶(hù)空間。
參數含義:
*to是用戶(hù)空間的指針
*from是內核空間的指針
n是從內核空間向用戶(hù)空間拷貝的字節數
copy_from_user
函數原型:
unsigned long copy_from_user(void *to, const void __user *from,
unsigned long n)
函數作用:
把用戶(hù)空間的數據復制到內核空間。
參數含義:
*to是內核空間的指針
*from是用戶(hù)空間的指針
n是從用戶(hù)空間向內核空間拷貝的字節數
14.3 實(shí)驗程序編寫(xiě)
14.3.1 驅動(dòng)程序編寫(xiě)
本驅動(dòng)程序對應的網(wǎng)盤(pán)路徑為:iTOP-RK3568開(kāi)發(fā)板【底板V1.7版本】\03_【iTOP-RK3568開(kāi)發(fā)板】指南教程\02_Linux驅動(dòng)配套資料\04_Linux驅動(dòng)例程\09\module。
在該實(shí)驗中將實(shí)現內核空間和用戶(hù)空間進(jìn)行數據交換的功能。以12章編寫(xiě)的字符設備驅動(dòng)框架實(shí)驗為基礎編寫(xiě)驅動(dòng)程序,程序使用copy_to_user函數和copy_from_user函數來(lái)實(shí)現內核空間和用戶(hù)空間互傳數據的功能,編寫(xiě)完成的file.c代碼如下所示:
以上代碼在cdev_test_read函數中使用copy_to_user函數將內核數據拷貝到用戶(hù)空間,在cdev_test_write函數中使用copy_from_user函數將用戶(hù)空間數據拷貝到內核空間。
14.3.2 編寫(xiě)測試 APP
本應用程序對應的網(wǎng)盤(pán)路徑為:iTOP-RK3568開(kāi)發(fā)板【底板V1.7版本】\03_【iTOP-RK3568開(kāi)發(fā)板】指南教程\02_Linux驅動(dòng)配套資料\04_Linux驅動(dòng)例程\09\app。
編寫(xiě)測試APP其實(shí)是在編寫(xiě)Linux應用,編譯完成的應用程序app.c代碼如下所示:
14.4 運行測試
14.4.1 編譯驅動(dòng)程序
在上一小節中的file.c代碼同一目錄下創(chuàng )建 Makefile 文件,Makefile 文件內容如下 所示:
對于Makefile的內容注釋已在上圖添加,保存退出之后,來(lái)到存放file.c和Makefile文件目錄下,如下圖(圖14-2)所示:
然后使用命令“make”進(jìn)行驅動(dòng)的編譯,編譯完成如下圖(圖14-3)所示:
編譯完生成 file.ko目標文件,如下圖(圖 14-4)所示:
至此我們的驅動(dòng)模塊就編譯成功了,下面進(jìn)行應用程序編譯.

下面進(jìn)行驅動(dòng)程序的測試。

輸入以下命令運行應用程序,如下圖(圖 14-7)所示
由上圖可知,打印“This is cdev_test_open”信息說(shuō)明成功打開(kāi)了字符設備驅動(dòng)。
打印“ This is cdev_test_read”和“buf1 is This is cdev_test_read!”說(shuō)明應用程序成功讀取到內核的數據。
打印“This is cdev_test_write”和“kbuf is nihao”說(shuō)明應用程序向內核寫(xiě)數據成功。
最后打印“This is cdev_test_release”說(shuō)明卸載字符設備。
更多內容可以了解迅為RK3568開(kāi)發(fā)板
*博客內容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀(guān)點(diǎn),如有侵權請聯(lián)系工作人員刪除。