日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux设备驱动(一)

發(fā)布時(shí)間:2023/12/31 linux 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux设备驱动(一) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • 基本概念
    • 什么是設(shè)備驅(qū)動
    • 無操作系統(tǒng)下的驅(qū)動
    • 有操作系統(tǒng)下的驅(qū)動
    • linux設(shè)備分類
      • 字符設(shè)備
      • 塊設(shè)備
      • 網(wǎng)絡(luò)設(shè)備
    • 內(nèi)核的組成
      • 源碼目錄結(jié)構(gòu)
      • 內(nèi)核主要組成部分
        • 進(jìn)程調(diào)度SCHED
        • 內(nèi)存管理MM
        • 虛擬文件系統(tǒng)VFS
        • 網(wǎng)絡(luò)接口NET
        • 進(jìn)程間通信IPC
    • 內(nèi)核代碼命名風(fēng)格
    • GNU C對ANSI C的拓展
    • 變長數(shù)組
    • case
    • 語句表達(dá)式
    • typeof關(guān)鍵字
    • 標(biāo)號元素
    • 特殊屬性說明
    • 內(nèi)建函數(shù)
    • 工具鏈
  • 環(huán)境搭建

基本概念

什么是設(shè)備驅(qū)動

計(jì)算機(jī)的運(yùn)行,需要軟件和硬件的合作,沒有軟件的硬件,是一堆廢鐵,沒有硬件的軟件,是空中樓閣,軟件運(yùn)行在硬件基礎(chǔ)之上。

軟件又分為系統(tǒng)軟件和應(yīng)用軟件,系統(tǒng)軟件屏蔽了底層硬件的差異,向應(yīng)用層提供統(tǒng)一的接口,因而應(yīng)用層的程序員,不需要知道不同網(wǎng)卡、硬盤等硬件之間有什么差異,只需要調(diào)用相同的讀寫函數(shù),即可完成對設(shè)備的讀寫操作。這個(gè)屏蔽具體硬件差異過程的重任,就落到了設(shè)備驅(qū)動的頭上。設(shè)備驅(qū)動程序,僅僅是系統(tǒng)軟件的一部分。

設(shè)備驅(qū)動是底層硬件和上層應(yīng)用之間的紐帶,設(shè)備驅(qū)動最通俗的解釋是:驅(qū)使硬件設(shè)備行動。設(shè)備驅(qū)動與底層硬件直接打交道,完成寄存器的讀寫等、中斷處理等等操作。

無操作系統(tǒng)下的驅(qū)動

計(jì)算機(jī)的運(yùn)轉(zhuǎn)不一定需要操作系統(tǒng),目前stm8,stm32等主流單片機(jī)都可以直接跑裸機(jī)程序,一般認(rèn)為只需要完成main函數(shù)和中斷服務(wù)函數(shù)即可(當(dāng)然IDE也幫我們完成了很多其它的底層工作)。這樣簡單的應(yīng)用場景,并不需要操作系統(tǒng)提供的多任務(wù)調(diào)度,內(nèi)存管理,文件系統(tǒng)等功能。

雖然沒有操作系統(tǒng),但是并不意味著沒有驅(qū)動程序。一般情況下,每一個(gè)硬件設(shè)備,都對應(yīng)了一個(gè).c和.h文件,例如EEPROM芯片AT24C04,在程序中肯定會對該芯片多次的進(jìn)行讀寫操作,為了方便,肯定會將這些重復(fù)使用的代碼實(shí)現(xiàn)為函數(shù),加入到整個(gè)工程之中,這些代碼,也可以稱之為驅(qū)動。只不過這些驅(qū)動程序的接口直接提供給應(yīng)用層,應(yīng)用層沒有跨越任何層次,就直接訪問到了底層硬件。

有操作系統(tǒng)下的驅(qū)動

驅(qū)動程序?qū)儆趦?nèi)核的一部分,內(nèi)核是操作系統(tǒng)最核心的部分,它負(fù)責(zé)管理系統(tǒng)的進(jìn)程、內(nèi)存、設(shè)備驅(qū)動程序、文件和網(wǎng)絡(luò)系統(tǒng),決定著系統(tǒng)的性能和穩(wěn)定性,因此驅(qū)動程序要按照內(nèi)核的規(guī)定的格式和提供的接口來寫。

在有操作系統(tǒng)的情況下,驅(qū)動程序其實(shí)是連接硬件和內(nèi)核的一個(gè)橋梁,操作系統(tǒng)的存在,讓驅(qū)動程序增加了很多代碼,操作系統(tǒng)就是通過給驅(qū)動程序編寫者制造麻煩,達(dá)到方便應(yīng)用開發(fā)者的目的。

linux設(shè)備分類

驅(qū)動設(shè)備針對的存儲器和外設(shè),而不是針對cpu內(nèi)核,linux系統(tǒng)將存儲器和外設(shè)分為三大類:

  • 字符設(shè)備
  • 塊設(shè)備
  • 網(wǎng)絡(luò)設(shè)備

字符設(shè)備

字符設(shè)備指那些必須以串行順序依次進(jìn)行訪問(字符流)的設(shè)備,如鍵盤、鼠標(biāo)、串口等,系統(tǒng)虛擬出一個(gè)文件,對該文件調(diào)用讀寫函數(shù)(read、write)即可完成對字符設(shè)備的操作

塊設(shè)備

系統(tǒng)可以隨機(jī)訪問快設(shè)備,以塊為單位進(jìn)行操作,如硬盤、FLASH、CD-ROM等,系統(tǒng)虛擬出一個(gè)文件,或者在塊設(shè)備上建立文件系統(tǒng),對這些文件調(diào)用讀寫函數(shù)(read、write)即可完成對塊設(shè)備的操作

網(wǎng)絡(luò)設(shè)備

網(wǎng)絡(luò)設(shè)備通常指有線網(wǎng)卡、無線網(wǎng)卡等,網(wǎng)絡(luò)設(shè)備面向數(shù)據(jù)包的接收和發(fā)送而設(shè)計(jì),與字符設(shè)備和塊設(shè)備不同,網(wǎng)絡(luò)通信主要依靠套接字接口

內(nèi)核的組成

源碼目錄結(jié)構(gòu)

Linux 內(nèi)核源代碼包含如下目錄。

  • arch :包含和硬件體系結(jié)構(gòu)相關(guān)的代碼,每種平臺占一個(gè)相應(yīng)的目錄,如 i386、arm、
    arm64、powerpc、mips 等。Linux 內(nèi)核目前已經(jīng)支持 30 種左右的體系結(jié)構(gòu)。在 arch
    目錄下,存放的是各個(gè)平臺以及各個(gè)平臺的芯片對 Linux 內(nèi)核進(jìn)程調(diào)度、內(nèi)存管理、
    中斷等的支持,以及每個(gè)具體的 SoC 和電路板的板級支持代碼。
  • block:塊設(shè)備驅(qū)動程序 I/O 調(diào)度。
  • crypto:常用加密和散列算法(如 AES、SHA 等),還有一些壓縮和 CRC 校驗(yàn)算法。
  • documentation:內(nèi)核各部分的通用解釋和注釋。
  • drivers :設(shè)備驅(qū)動程序,每個(gè)不同的驅(qū)動占用一個(gè)子目錄,如 char、block、net、
    mtd、i2c 等。
  • fs:所支持的各種文件系統(tǒng),如 EXT、FAT、NTFS、JFFS2 等。
  • include:頭文件,與系統(tǒng)相關(guān)的頭文件放置在 include/linux 子目錄下。
  • init:內(nèi)核初始化代碼。著名的 start_kernel() 就位于 init/main.c 文件中。
  • ipc:進(jìn)程間通信的代碼。
  • kernel :內(nèi)核最核心的部分,包括進(jìn)程調(diào)度、定時(shí)器等,而和平臺相關(guān)的一部分代碼
    放在 arch/*/kernel 目錄下。
  • ib:庫文件代碼。
  • mm:內(nèi)存管理代碼,和平臺相關(guān)的一部分代碼放在 arch/*/mm 目錄下。
  • net:網(wǎng)絡(luò)相關(guān)代碼,實(shí)現(xiàn)各種常見的網(wǎng)絡(luò)協(xié)議。
  • scripts:用于配置內(nèi)核的腳本文件。
  • security:主要是一個(gè) SELinux 的模塊。
  • sound:ALSA、OSS 音頻設(shè)備的驅(qū)動核心代碼和常用設(shè)備驅(qū)動。
  • usr:實(shí)現(xiàn)用于打包和壓縮的 cpio 等。
  • include:內(nèi)核 API 級別頭文件。

內(nèi)核主要組成部分

進(jìn)程調(diào)度SCHED

進(jìn)程調(diào)度控制系統(tǒng)使得多個(gè)進(jìn)程在CPU的中微觀上分時(shí)執(zhí)行,宏觀上并發(fā)執(zhí)行
進(jìn)程整體上可以分為五種狀態(tài):

  • 就緒態(tài):資源準(zhǔn)備就緒,等待系統(tǒng)調(diào)用該進(jìn)程
  • 執(zhí)行態(tài):當(dāng)前CPU正在執(zhí)行該進(jìn)程
  • 睡眠態(tài):等待其它進(jìn)程釋放資源
  • 暫停態(tài):停止執(zhí)行,等待某種信號
  • 僵尸態(tài):進(jìn)程已死,資源未釋放

內(nèi)存管理MM

內(nèi)存管理的主要作用是控制多個(gè)進(jìn)程安全地共享主內(nèi)存區(qū)域。當(dāng)CPU提供內(nèi)存管理單元(MMU)時(shí),Linux內(nèi)存管理對每個(gè)進(jìn)程提供虛擬地址到物理地址的轉(zhuǎn)換

每個(gè)進(jìn)程擁有虛擬的4G內(nèi)存空間,其中3G是用戶空間,是屬于進(jìn)程私有的,1G是內(nèi)核空間,是所有進(jìn)程共享的

虛擬文件系統(tǒng)VFS

用戶通過虛擬文件系統(tǒng),對文件進(jìn)行操作,即可達(dá)到訪問硬件的目的,虛擬文件系統(tǒng)隱藏了硬件差異,向上為用戶提供統(tǒng)一的接口,向下調(diào)用驅(qū)動程序?qū)崿F(xiàn)的file_operations結(jié)構(gòu)體中的成員函數(shù)

網(wǎng)絡(luò)接口NET

網(wǎng)絡(luò)接口提供了對各種網(wǎng)絡(luò)標(biāo)準(zhǔn)的存取和各種網(wǎng)絡(luò)硬件的支持。在 Linux中網(wǎng)絡(luò)接口可分為網(wǎng)絡(luò)協(xié)議和網(wǎng)絡(luò)驅(qū)動程序,網(wǎng)絡(luò)協(xié)議部分負(fù)責(zé)實(shí)現(xiàn)每一種可能的網(wǎng)絡(luò)傳輸協(xié)議,網(wǎng)絡(luò)設(shè)備驅(qū)動程序負(fù)責(zé)與硬件設(shè)備通信,每一種可能的硬件設(shè)備都有相應(yīng)的設(shè)備驅(qū)動程序。

進(jìn)程間通信IPC

Linux支持進(jìn)程間通信的多種機(jī)制,包括信號量、共享內(nèi)存、消息隊(duì)列、管道、套接字等。利用這些機(jī)制,可以實(shí)現(xiàn)進(jìn)程間的同步、互斥和消息傳遞。

內(nèi)核代碼命名風(fēng)格

與windows下流行的編程命名風(fēng)格不同,linux社區(qū)形成了自己的一套風(fēng)格

#define PI 3.1415926 int min_value, max_value; void send_data(void);
  • 宏:大寫
  • 變量:全部小寫,單詞之間以下劃線分隔
  • 函數(shù):同變量
  • 縮進(jìn):tab鍵
  • 括號{}:
    1.if、for、switch、while、else、else if { 不會另起一行
    2.函數(shù)的 { 需要另起一行
    3.只有一行代碼,不要用括號{}
  • switch:switch、case、default關(guān)鍵字左對齊

GNU C對ANSI C的拓展

Linux使用的C編譯器是GNU C編譯器,對標(biāo)準(zhǔn)C進(jìn)行了一系列拓展,增強(qiáng)C的功能

變長數(shù)組

GNU C可以使用0長度數(shù)組,也可以使用變量定義數(shù)組長度

struct var_data { int len; char data[0]; };int n=10; int array[n];

其實(shí)也就是C99中新增加的伸縮數(shù)組和變長數(shù)組的概念

伸縮的意思是,比如定義一個(gè)結(jié)構(gòu)體,可以讓其成員擁有不固定的長度,因此用sizeof去求該結(jié)構(gòu)體類型,會忽略掉不固定的部分,而實(shí)際定義的時(shí)候,一般需要用malloc進(jìn)行內(nèi)存分配

變長數(shù)組不是指數(shù)組的長度在程序運(yùn)行期間可變,而是指定義時(shí)可以利用變量,對長度進(jìn)行說明,一旦定義了一個(gè)數(shù)組,其長度就不能變了

case

GNU C 支持 case x…y 這樣的語法,區(qū)間 [x,y] 中的數(shù)都會滿足這個(gè) case 的條件

switch (ch) { case '0'... '9': c -= '0'; break; case 'a'... 'f': c -= 'a' - 10; break; case 'A'... 'F': c -= 'A' - 10; break; }

語句表達(dá)式

GNU C 把包含在括號中的復(fù)合語句看成是一個(gè)表達(dá)式,稱為語句表達(dá)式,它可以出現(xiàn)在任何允許表達(dá)式的地方。我們可以在語句表達(dá)式中使用原本只能在復(fù)合語句中使用的循環(huán)、局部變量等,

typeof關(guān)鍵字

typeof(x) 語句可以獲得 x 的類型,可以方便一些宏的實(shí)現(xiàn),例如求兩數(shù)中較大的值
# define max(a,b) ...
具體實(shí)現(xiàn)中,需要先判斷傳入數(shù)據(jù)的類型,此處可以通過typeof進(jìn)行判斷

標(biāo)號元素

C99標(biāo)準(zhǔn)已經(jīng)增加了標(biāo)號元素的使用,也就是數(shù)組、結(jié)構(gòu)體等初始化過程不需要按順序來,可以隨意指定,例如:

int a[10] = {[1] = 2,[3] = 5,0, }

在Linux內(nèi)核代碼中,推薦以下格式進(jìn)行初始化:

struct file_operations ext2_file_operations = {.llseek = generic_file_llseek,.read = generic_file_read,... };

特殊屬性說明

GNU C 允許聲明函數(shù)、變量和類型的特殊屬性,以便手動優(yōu)化代碼和定制代碼檢查的方法。要指定一個(gè)聲明的屬性,只需要在聲明后添加_ _attribute_ _ (( ATTRIBUTE ))

其中 ATTRIBUTE 為屬性說明,如果存在多個(gè)屬性,則以逗號分隔。GNU C 支持 noreturn、format、section、aligned、packed 等十多個(gè)屬性

  • noreturn 屬性作用于函數(shù),表示該函數(shù)從不返回。這會讓編譯器優(yōu)化代碼,并消除不必要的警告信息
  • format 屬性也用于函數(shù),表示該函數(shù)使用 printf、scanf 或 strftime 風(fēng)格的參數(shù),指定format 屬性可以讓編譯器根據(jù)格式串檢查參數(shù)類型
  • unused 屬性作用于函數(shù)和變量,表示該函數(shù)或變量可能不會用到,這個(gè)屬性可以避免編譯器產(chǎn)生警告信息
  • aligned 屬性用于變量、結(jié)構(gòu)體或聯(lián)合體,指定變量、結(jié)構(gòu)體或聯(lián)合體的對齊方式,以字節(jié)為單位
  • packed 屬性作用于變量和類型,用于變量或結(jié)構(gòu)體成員時(shí)表示使用最小可能的對齊,用于枚舉、結(jié)構(gòu)體或聯(lián)合體類型時(shí)表示該類型使用最小的內(nèi)存

內(nèi)建函數(shù)

內(nèi)建函數(shù)是編譯器內(nèi)部實(shí)現(xiàn)的函數(shù),這些函數(shù)可以直接使用,無須聲明或者添加頭文件,不屬于標(biāo)準(zhǔn)庫函數(shù)的內(nèi)建函數(shù)通常以_ _builtin開頭,還有一小部分內(nèi)建函數(shù)與標(biāo)準(zhǔn)庫函數(shù)同名,不過編譯器做了優(yōu)化或者重構(gòu)。

工具鏈

最方便的就是直接下載已經(jīng)編譯好的工具鏈,目前最常用的是Linaro提供的,可以在下面的網(wǎng)址進(jìn)行下載

http://www.linaro.org/downloads/

Linaro 是 ARM Linux 領(lǐng)域中最著名最具技術(shù)成就的開源組織,其會員包括 ARM、Broadcom、Samsung、TI、Qualcomm 等,國內(nèi)的海思、中興、全志和中國臺灣的 MediaTek 也是它的會員

工具鏈包含了很多程序,例如arm-linux-gnueabihf-gcc
下面介紹一下常用的幾種

  • gcc:編譯C源碼
  • g++:編譯C++源碼
  • gdb:調(diào)試
  • strip:刪除符號表和調(diào)試信息,縮減可執(zhí)行文件的體積
  • objdump:反匯編
  • ld:鏈接器
  • gprof:檢查函數(shù)被調(diào)用的次數(shù)和時(shí)間
  • nm:顯示符號信息
  • readelf:查看ELF格式文件信息
  • addr2line:將指令的地址和可執(zhí)行映像轉(zhuǎn)換為文件名、函數(shù)名和源代碼行數(shù)的工具

環(huán)境搭建

練習(xí)驅(qū)動程序開發(fā),最好的方式是虛擬機(jī)+qemu,不需要額外購買開發(fā)板,具體搭建的過程可以參考我之前的博客

https://blog.csdn.net/whitefish520/article/details/103850361

總結(jié)

以上是生活随笔為你收集整理的linux设备驱动(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。