0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Openwrt開發(fā)指南 第15章 驅(qū)動(dòng)開發(fā)之字符設(shè)備驅(qū)動(dòng)程序之概念介紹

嵌入式大雜燴 ? 來源:嵌入式大雜燴 ? 作者:嵌入式大雜燴 ? 2023-06-30 09:00 ? 次閱讀

1 應(yīng)用程序、庫、內(nèi)核、驅(qū)動(dòng)程序的關(guān)系

從上到下,一個(gè)軟件系統(tǒng)可以分為:應(yīng)用程序、庫、操作系統(tǒng)(內(nèi)核)、驅(qū)動(dòng)程序。開發(fā)人員可以專注于自己熟悉的部分,對于相鄰層,只需要了解它的接口,無需關(guān)注它的實(shí)現(xiàn)細(xì)節(jié)。

以點(diǎn)亮一個(gè) LED 為例,這 4 層軟件的協(xié)作關(guān)系如下,如圖 1 所示

C:\\Users\\ouxiaolong\\Desktop\\Linux 字符設(shè)備驅(qū)動(dòng)結(jié)構(gòu)(一)—— cdev 結(jié)構(gòu)體、設(shè)備號相關(guān)知識(shí)解析 - 知秋一葉 - 博客頻道 - CSDN.NET.png

圖1

1). 應(yīng)用程序使用庫提供的 open 函數(shù)打開代表 LED 的設(shè)備文件。

2). 庫根據(jù) open 函數(shù)傳入的參數(shù)執(zhí)行“SWI”指令,這條指令會(huì)引起 CPU 異常,進(jìn)入內(nèi)核。

3). 內(nèi)核的異常處理函數(shù)根據(jù)這些參數(shù)找到相應(yīng)的驅(qū)動(dòng)程序,返回一個(gè)文件句柄給庫,進(jìn)而返回給應(yīng)用程序

4). 應(yīng)用程序得到文件句柄后,使用庫提供的 write 或 ioclt 函數(shù)發(fā)出控制命令。

5). 庫根據(jù) write 和 ioclt 函數(shù)傳人的參數(shù)執(zhí)行 “swi” 指令, 這條指令會(huì)引起 CPU 異常,進(jìn)入內(nèi)核。

6). 內(nèi)核的異常處理函數(shù)根據(jù)這些參數(shù)調(diào)用驅(qū)動(dòng)程序的相關(guān)函數(shù),點(diǎn)亮 LED。庫(比如 glibc)給應(yīng)用程序提供的 open、read、write、ioctl、mmap 等接口函數(shù)被稱為系統(tǒng)調(diào)用,它們都是設(shè)置好相關(guān)寄存器后,執(zhí)行某條指令引發(fā)異常進(jìn)入內(nèi)核。除系統(tǒng)調(diào)用接口外, 庫還提供其他函數(shù), 比如字符串處理函數(shù)(strcpy、 strcmp 等)、 輸入/輸出函數(shù)(scanf、printf 等)、數(shù)學(xué)庫,還有應(yīng)用程序的啟動(dòng)代碼等。

在異常處理函數(shù)中,內(nèi)核會(huì)根據(jù)傳入的參數(shù)執(zhí)行各種操作,比如根據(jù)設(shè)備文件名找到對應(yīng)的驅(qū)動(dòng)程序,調(diào)用驅(qū)動(dòng)程序的相關(guān)函數(shù)等。

一般來說,當(dāng)應(yīng)用程序調(diào)用 open、read、write、ioctl、mmap 等函數(shù)后,將會(huì)使用驅(qū)動(dòng)程序中的 open、read、write、ioctl、mmap 函數(shù)來執(zhí)行相關(guān)操作,比如初始化、讀、寫等。

實(shí)際上,內(nèi)核和驅(qū)動(dòng)程序之間并沒有界線,因?yàn)轵?qū)動(dòng)程序最終是要編進(jìn)內(nèi)核去的:通過靜態(tài)鏈接和動(dòng)態(tài)加載。

從上面操作 LED 的過程可以知道,與應(yīng)用程序不同,驅(qū)動(dòng)程序從不主動(dòng)運(yùn)行,它是被動(dòng)的:根據(jù)應(yīng)用程序的要求進(jìn)行初始化,根據(jù)應(yīng)用程序的要求進(jìn)行讀寫。驅(qū)動(dòng)程序加載進(jìn)內(nèi)核時(shí),只是告訴內(nèi)核“我在這里,我能做這些工作” ,至于這些“工作”何時(shí)開始,取決于應(yīng)用程序。當(dāng)然,這不是絕對的,比如用戶完全可以寫一個(gè)系統(tǒng)時(shí)鐘觸發(fā)的驅(qū)動(dòng)程序,讓它自動(dòng)點(diǎn)亮 LED。

Linux 系統(tǒng)中,應(yīng)用程序運(yùn)行于“用戶空間” ,擁有 MMU 的系統(tǒng)能夠限制應(yīng)用程序的權(quán)限(比如將它限制于某個(gè)內(nèi)存塊中),這可以避免應(yīng)用程序的錯(cuò)誤使整個(gè)系統(tǒng)崩潰。而驅(qū)動(dòng)程序運(yùn)行于“內(nèi)核空間” ,它是系統(tǒng)“信任”的一部分,驅(qū)動(dòng)程序的錯(cuò)誤有可能導(dǎo)致整個(gè)系統(tǒng)崩潰。

2 Linux 驅(qū)動(dòng)程序分類

Linux 的外設(shè)可以分為 3 類:自費(fèi)設(shè)備、塊設(shè)備和網(wǎng)絡(luò)接口。

字符設(shè)備是能夠像字節(jié)流(比如文件)一樣被訪問的設(shè)備,就是說對它的讀寫是以字節(jié)為單位的。 比如串口在進(jìn)行收發(fā)數(shù)據(jù)時(shí)就是一個(gè)字節(jié)一個(gè)字節(jié)的進(jìn)行的,我們可以在驅(qū)動(dòng)程序內(nèi)部使用緩沖區(qū)來存放數(shù)據(jù)以提高效率,但是串口本身對這并沒有要求。字符設(shè)備的驅(qū)動(dòng)程序中實(shí)現(xiàn)了 open、close、read、write 等系統(tǒng)調(diào)用,應(yīng)用程序可以通過設(shè)備文件(比如/dev/ttySAC0 等)來訪問字符設(shè)備。

塊設(shè)備上的數(shù)據(jù)以塊的形式存放,比如 NAND Flash 上的數(shù)據(jù)就是以頁為單位存放的。塊設(shè)備驅(qū)動(dòng)程序向用戶層提供的接口與字符設(shè)備一樣, 應(yīng)用程序也可以通過相應(yīng)的設(shè)備文件(比如/dev/mtdblock0、/dev/hda1 等)來調(diào)用 open、close、read、write 等系統(tǒng)調(diào)用,與塊設(shè)備傳送任意字節(jié)的數(shù)據(jù)。對用戶而言,字符設(shè)備和塊設(shè)備的訪問方式?jīng)]有差別。塊設(shè)備驅(qū)動(dòng)程序的特別之處如下。

1). 操作硬件的接口實(shí)現(xiàn)方式不一樣。

塊設(shè)備驅(qū)動(dòng)程序先將用戶發(fā)來的數(shù)據(jù)組織成塊,再寫入設(shè)備;或從設(shè)備中讀出若干塊數(shù)據(jù),再從中挑出用戶需要的。

2). 數(shù)據(jù)塊上的數(shù)據(jù)可以有一定的格式。

通常在塊設(shè)備中按照一定的格式存放數(shù)據(jù),不同的文件系統(tǒng)類型就是用來定義這些格式的。內(nèi)核中,文件系統(tǒng)的層次位于塊設(shè)備驅(qū)動(dòng)程序上面,這意味著塊設(shè)備驅(qū)動(dòng)程序除了向用戶層提供與字符設(shè)備一樣的接口外,還要向內(nèi)核其他部件提供一些接口,這些接口用戶是看不到的。這些接口使得可以在塊設(shè)備上存放文件系統(tǒng),掛載塊設(shè)備。

網(wǎng)絡(luò)接口同時(shí)具有字符設(shè)備、塊設(shè)備的部分特點(diǎn),無法將它歸入這兩類中:如果說它是字符設(shè)備,他的輸入/輸出卻是有結(jié)構(gòu)的、成塊的(報(bào)文、包、幀);如果說它是塊設(shè)備,它的“塊”又不是固定大小的,大到數(shù)百甚至數(shù)千字節(jié),小到幾字節(jié)。UNIX 式的操作系統(tǒng)訪問網(wǎng)絡(luò)接口的方法是給它們分配一個(gè)惟一的名字(比如 eth0),但這個(gè)名字在文件系統(tǒng)中(比如/dev 目錄下)不存在對應(yīng)的節(jié)點(diǎn)項(xiàng)。應(yīng)用程序、內(nèi)核和網(wǎng)絡(luò)驅(qū)動(dòng)程序間的通信完全不同于字符設(shè)備、塊設(shè)備,庫、內(nèi)核提供了一套和數(shù)據(jù)包傳輸相關(guān)的函數(shù),而不是 open、read、write 等。

3 Linux 驅(qū)動(dòng)程序開發(fā)步驟

Linux 內(nèi)核就是由各種驅(qū)動(dòng)組成的,內(nèi)核源碼中有大約 85%是各種驅(qū)動(dòng)程序的代碼。內(nèi)核中驅(qū)動(dòng)程序種類齊全,可以在同類驅(qū)動(dòng)的基礎(chǔ)上進(jìn)行修改以符合具體單板。

編寫驅(qū)動(dòng)程序的難點(diǎn)并不是硬件的具體操作,而是弄清楚現(xiàn)有驅(qū)動(dòng)程序的框架,在這個(gè)框架中加入這個(gè)硬件。比如,x86 架構(gòu)的內(nèi)核對 IDE 硬盤的支持非常完善:首先通過 BIOS 得到硬盤的信息,或者使用默認(rèn) I/O 地址去枚舉硬盤,然后識(shí)別分區(qū)、掛載文件系統(tǒng)。對于其他架構(gòu)的內(nèi)核,只是要指定了硬盤的訪問地址和中斷號,后面的枚舉、識(shí)別和掛接的過程完全是一樣的。也許修改的代碼不超過 10 行,花費(fèi)精力的地方在于:了解硬盤驅(qū)動(dòng)的框架, 找到修改的位置。

編寫驅(qū)動(dòng)程序還有很多需要注意的地方,比如:驅(qū)動(dòng)程序可能同時(shí)被多個(gè)進(jìn)程使用,這需要考慮并發(fā)的問題;盡可能發(fā)揮硬件的作用以提高性能。比如在硬盤驅(qū)動(dòng)程序中既可以使用 DMA 也可以不用,使用 DMA 時(shí)程序比較復(fù)雜,但是可以提高效率;處理硬件的各種異常情況(即使效率低),否則出錯(cuò)時(shí)可能導(dǎo)致整個(gè)系統(tǒng)崩潰。

一般來說,編寫一個(gè) Linux 設(shè)備驅(qū)動(dòng)程序的大致流程如下。

1). 查看原理圖、數(shù)據(jù)手冊,了解設(shè)備的操作方法。

2). 在內(nèi)核中找到相近的驅(qū)動(dòng)程序,以它為模板進(jìn)行開發(fā),有時(shí)候需要從零開始。

3). 實(shí)現(xiàn)驅(qū)動(dòng)程序的初始化:比如向內(nèi)核注冊這個(gè)驅(qū)動(dòng)程序,這樣應(yīng)用程序傳入文件名時(shí),內(nèi)核才能找到相應(yīng)的驅(qū)動(dòng)程序。

4). 設(shè)計(jì)所要實(shí)現(xiàn)的操作,比如 open、close、read、write 等函數(shù)。

5). 實(shí)現(xiàn)中斷服務(wù)(中斷并不是每個(gè)設(shè)備驅(qū)動(dòng)所必須的)。

6). 編譯該驅(qū)動(dòng)程序到內(nèi)核中,或者用 insmod 命令加載。

7). 測試驅(qū)動(dòng)程序。

4 驅(qū)動(dòng)程序的加載和卸載

可以將驅(qū)動(dòng)程序靜態(tài)編譯進(jìn)內(nèi)核中,也可以將它作為模塊在使用時(shí)再加載。在配置內(nèi)核時(shí),如果某個(gè)配置選項(xiàng)被設(shè)為 m,就表示它將會(huì)被編譯成一個(gè)模塊。在 2.6 的內(nèi)核中,模塊的擴(kuò)展名為.ko,可以使用 insmod 命令加載,使用 rmmod 命令卸載,使用 lsmod 命令查看內(nèi)核中已經(jīng)加載了哪些模塊。

當(dāng)使用 insmod 加載模塊時(shí),模塊的初始化函數(shù)被調(diào)用,它用來向內(nèi)核注冊驅(qū)動(dòng)程序; 當(dāng)使用 rmmod 卸載模塊時(shí),模塊的清除函數(shù)被調(diào)用。在驅(qū)動(dòng)代碼中,這兩個(gè)函數(shù)要么取固定的名字:init_module 和 cleanup_module,要么使用以下兩行來標(biāo)記它們(假設(shè)初始化函數(shù)、清除函數(shù)為 my_init 和 my_cleanup)。

moudle_init(my_init);

module_exit(my_cleanup);

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 內(nèi)核
    +關(guān)注

    關(guān)注

    3

    文章

    1361

    瀏覽量

    40185
  • 操作系統(tǒng)
    +關(guān)注

    關(guān)注

    37

    文章

    6689

    瀏覽量

    123141
  • 驅(qū)動(dòng)程序
    +關(guān)注

    關(guān)注

    19

    文章

    818

    瀏覽量

    47906
  • 應(yīng)用程序
    +關(guān)注

    關(guān)注

    37

    文章

    3237

    瀏覽量

    57547
  • OpenWrt
    +關(guān)注

    關(guān)注

    10

    文章

    127

    瀏覽量

    39247
收藏 人收藏

    評論

    相關(guān)推薦

    Openwrt開發(fā)指南 16 驅(qū)動(dòng)開發(fā)字符設(shè)備驅(qū)動(dòng)程序框架

    我們在學(xué)習(xí) C 語言的時(shí)候,知道每個(gè)應(yīng)用程序的入口函數(shù),即第一個(gè)被執(zhí)行的函數(shù)是 main函數(shù),那么,我們自己的驅(qū)動(dòng)程序,哪個(gè)函數(shù)是入口函數(shù)呢?
    的頭像 發(fā)表于 06-30 09:01 ?3312次閱讀
    <b class='flag-5'>Openwrt</b><b class='flag-5'>開發(fā)指南</b> <b class='flag-5'>第</b>16<b class='flag-5'>章</b> <b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>開發(fā)</b><b class='flag-5'>之</b><b class='flag-5'>字符</b><b class='flag-5'>設(shè)備</b><b class='flag-5'>驅(qū)動(dòng)程序</b>框架

    Openwrt開發(fā)指南 25 配置OpenWrt支持網(wǎng)絡(luò)攝像頭

    Openwrt開發(fā)指南 25 配置OpenWrt支持網(wǎng)絡(luò)攝像頭
    的頭像 發(fā)表于 07-13 08:56 ?2261次閱讀
    <b class='flag-5'>Openwrt</b><b class='flag-5'>開發(fā)指南</b> <b class='flag-5'>第</b>25<b class='flag-5'>章</b> 配置<b class='flag-5'>OpenWrt</b>支持網(wǎng)絡(luò)攝像頭

    Openwrt開發(fā)指南 17 驅(qū)動(dòng)開發(fā)字符設(shè)備驅(qū)動(dòng)程序

    首先將 RT5350_drv 文件夾傳到 OpenWrt 源碼的chaos_calmer/package/kernel 目錄下。然后進(jìn)入 OpenWrt 源碼的頂層目錄,執(zhí)行 make menuconfig。
    的頭像 發(fā)表于 07-02 09:20 ?3096次閱讀
    <b class='flag-5'>Openwrt</b><b class='flag-5'>開發(fā)指南</b> <b class='flag-5'>第</b>17<b class='flag-5'>章</b> <b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>開發(fā)</b><b class='flag-5'>之</b><b class='flag-5'>字符</b><b class='flag-5'>設(shè)備</b><b class='flag-5'>驅(qū)動(dòng)程序</b>

    Openwrt開發(fā)指南 18 驅(qū)動(dòng)開發(fā)字符設(shè)備應(yīng)用程序

    在前面的章節(jié)中, 我們成功的寫出了我們自己的驅(qū)動(dòng)程序, 并且向應(yīng)用程序提供了 open、read、write 三個(gè)接口,那么接下來我們就來編寫應(yīng)用程序,調(diào)用這些接口。
    的頭像 發(fā)表于 07-02 09:21 ?2467次閱讀
    <b class='flag-5'>Openwrt</b><b class='flag-5'>開發(fā)指南</b> <b class='flag-5'>第</b>18<b class='flag-5'>章</b> <b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>開發(fā)</b><b class='flag-5'>之</b><b class='flag-5'>字符</b><b class='flag-5'>設(shè)備</b>應(yīng)用<b class='flag-5'>程序</b>

    Openwrt開發(fā)指南 20 驅(qū)動(dòng)開發(fā)LED應(yīng)用程序

    在前面的章節(jié)中, 我們成功的寫出了我們自己的驅(qū)動(dòng)程序, 并且向應(yīng)用程序提供了 open、ioctl 兩個(gè)接口,那么接下來我們就來編寫應(yīng)用程序,調(diào)用這些接口。
    的頭像 發(fā)表于 07-03 09:02 ?2560次閱讀
    <b class='flag-5'>Openwrt</b><b class='flag-5'>開發(fā)指南</b> <b class='flag-5'>第</b>20<b class='flag-5'>章</b> <b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>開發(fā)</b><b class='flag-5'>之</b>LED應(yīng)用<b class='flag-5'>程序</b>

    Openwrt開發(fā)指南 22 Openwrt串口的使用2

    在上一中,我們成功的讓驅(qū)動(dòng)程序支持了串口 2,并且做了簡單的測試。接下來,我們就為串口 2 添加一個(gè)應(yīng)用程序,從而實(shí)現(xiàn) Wi-Fi 串口。實(shí)現(xiàn)過程非常簡單,首先進(jìn)入 OpenWrt
    的頭像 發(fā)表于 07-05 09:09 ?3915次閱讀
    <b class='flag-5'>Openwrt</b><b class='flag-5'>開發(fā)指南</b> <b class='flag-5'>第</b>22<b class='flag-5'>章</b> <b class='flag-5'>Openwrt</b>串口的使用2

    Openwrt開發(fā)指南 24 配置開發(fā)板支持U盤

    Openwrt開發(fā)指南 24 配置開發(fā)板支持U盤
    的頭像 發(fā)表于 07-13 08:55 ?2877次閱讀
    <b class='flag-5'>Openwrt</b><b class='flag-5'>開發(fā)指南</b> <b class='flag-5'>第</b>24<b class='flag-5'>章</b> 配置<b class='flag-5'>開發(fā)</b>板支持U盤

    ArmSoM系列板卡 嵌入式Linux驅(qū)動(dòng)開發(fā)實(shí)戰(zhàn)指南 字符設(shè)備驅(qū)動(dòng)

    字符設(shè)備驅(qū)動(dòng) 本章,我們將學(xué)習(xí)字符設(shè)備使用、字符設(shè)備
    的頭像 發(fā)表于 04-10 09:53 ?986次閱讀
    ArmSoM系列板卡 嵌入式Linux<b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>開發(fā)</b>實(shí)戰(zhàn)<b class='flag-5'>指南</b> <b class='flag-5'>之</b> <b class='flag-5'>字符</b><b class='flag-5'>設(shè)備</b><b class='flag-5'>驅(qū)動(dòng)</b>

    PCI設(shè)備WINDOWS驅(qū)動(dòng)程序開發(fā)

    PCI設(shè)備WINDOWS驅(qū)動(dòng)程序開發(fā) 本文主要介紹了在Windows9x操作系統(tǒng)下開發(fā)PCI設(shè)備
    發(fā)表于 05-03 11:54 ?3305次閱讀

    Windows WDM設(shè)備驅(qū)動(dòng)程序開發(fā)指南

    書主要介紹Windows 98和Windows 2000新的驅(qū)動(dòng)程序模型(WDM)。描述了WDM設(shè)備驅(qū)動(dòng)程序的結(jié)構(gòu)、功能和開發(fā)方法.
    發(fā)表于 12-12 15:31 ?0次下載
    Windows WDM<b class='flag-5'>設(shè)備</b><b class='flag-5'>驅(qū)動(dòng)程序</b><b class='flag-5'>開發(fā)指南</b>

    基于Windows CE.NET的設(shè)備驅(qū)動(dòng)程序開發(fā)

    本文闡述了設(shè)備驅(qū)動(dòng)程序概念和結(jié)構(gòu) 介紹了 Windows CE. NET環(huán)境下開發(fā)驅(qū)動(dòng)程序的特
    發(fā)表于 04-18 11:28 ?0次下載

    Linux設(shè)備驅(qū)動(dòng)開發(fā)字符設(shè)備驅(qū)動(dòng)編程分析

    1.字符設(shè)備驅(qū)動(dòng)編寫流程 設(shè)備驅(qū)動(dòng)程序可以使用模塊的方式動(dòng)態(tài)加載到內(nèi)核中去。加載模塊的方式與以往的應(yīng)用
    發(fā)表于 10-18 17:33 ?1次下載
    Linux<b class='flag-5'>設(shè)備</b><b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>開發(fā)</b><b class='flag-5'>之</b><b class='flag-5'>字符</b><b class='flag-5'>設(shè)備</b><b class='flag-5'>驅(qū)動(dòng)</b>編程分析

    《Linux設(shè)備驅(qū)動(dòng)開發(fā)詳解》6、字符設(shè)備驅(qū)動(dòng)

    《Linux設(shè)備驅(qū)動(dòng)開發(fā)詳解》6、字符設(shè)備
    發(fā)表于 10-27 11:46 ?23次下載
    《Linux<b class='flag-5'>設(shè)備</b><b class='flag-5'>驅(qū)動(dòng)</b><b class='flag-5'>開發(fā)</b>詳解》<b class='flag-5'>第</b>6<b class='flag-5'>章</b>、<b class='flag-5'>字符</b><b class='flag-5'>設(shè)備</b><b class='flag-5'>驅(qū)動(dòng)</b>

    Linux設(shè)備驅(qū)動(dòng)程序的平臺(tái)驅(qū)動(dòng)程序字符驅(qū)動(dòng)程序介紹

    了解Linux設(shè)備驅(qū)動(dòng)程序的基礎(chǔ)知識(shí),重點(diǎn)介紹平臺(tái)驅(qū)動(dòng)程序字符驅(qū)動(dòng)程序。 提出了簡單的平臺(tái)
    的頭像 發(fā)表于 11-27 06:32 ?4252次閱讀

    UM2298_STM32Cube BSP驅(qū)動(dòng)程序開發(fā)指南

    UM2298_STM32Cube BSP驅(qū)動(dòng)程序開發(fā)指南
    發(fā)表于 11-22 19:19 ?1次下載
    UM2298_STM32Cube BSP<b class='flag-5'>驅(qū)動(dòng)程序</b><b class='flag-5'>開發(fā)指南</b>