国产无码免费,人妻口爆,国产V在线,99中文精品7,国产成人无码AA精品一,制度丝袜诱惑av,久久99免费麻辣视频,蜜臀久久99精品久久久久久酒店
        訂閱
        糾錯
        加入自媒體

        Linux驅動實踐:一起來梳理【中斷】的前世今生

        2021-12-15 11:31
        道哥分享
        關注

        目錄

        · Linux 中斷的知識點梳理

        中斷的分類

        中斷號和中斷向量

        中斷服務程序ISR

        上半部分和下半部分

        · 中斷處理的注冊和注銷 API

        · 實操:捕獲鍵盤中斷

        示例代碼

        驅動程序傳參

        IO編址:IO端口和IO內存

        編譯、測試、驗證

        別人的經驗,我們的階梯!

        大家好,我是道哥,今天我為大伙兒解說的技術知識點是:【Linux 中斷的注冊和處理】。

        在前兩篇文章中,描述的是在應用層如何調用驅動函數來控制GPIO,以及在驅動中如何發送發送信號給應用層。

        假如存在這樣一個需求:應用程序需要監控某個硬件GPIO口的電平狀態,當發生變化時,應用程序就做出相應的動作。

        利用之前已經介紹的知識,是可以完成這個需求的。

        比如:在驅動程序中不停的讀取GPIO口的狀態,一旦發生變化,就把新的電平狀態通過信號發送到應用層。

        這樣的方式稱作:輪詢。

        輪詢方式的缺點顯而易見:輪詢的時間間隔應該是多少毫秒(or 微秒),才比較合適呢?

        輪詢太慢:可能會丟失信號;輪詢太快:消耗 CPU 資源!

        因此,在實際的產品中,用中斷觸發的方式才是更切合實際的選擇!

        本文所有的描述和測試,都是在 x86 平臺上完成的;

        Linux 中斷的知識點梳理

        中斷的分類

        Linux 的版本在持續更新,對中斷的處理方式也在不停的發生變化。

        下面幾張圖,是以前在學習時畫的思維導圖。

        這幾張圖比較清晰地描述了在Linux操作系統中,關于中斷的一些基本概念。

        這張圖的結構還是比較清晰的,基本上概括了Linux系統中的中斷分類。

        另外,在很多關于中斷的書籍中,大部分都是從基礎的 PIC(可編程中斷控制器)開始講解的。

        如果您想非常具體、專業、深入的了解關于中斷的相關內容,有一篇文章《Interrupt in Linux.pdf》講得非常好(文章的后面部分我也沒有看懂)。

        在文末有下載鏈接,感興趣的小伙伴可以學習一下。

        中斷號和中斷向量

        這張圖只要記住中斷號與中斷向量的關系就可以了:

        1. 中斷號與中斷控制器(PIC/APIC)相關;

        2. 中斷向量與 CPU 相關,用來查找中斷處理函數的入口地址;

        中斷服務例程 ISR

        中斷服務程序,就是針對每一個中斷如何進行處理。

        如果您了解Linux中斷的相關內容,一定會看到這樣的描述:中斷處理分為上半部分和下半部分。

        上半部分不能消耗太多的時間,主要處理與硬件相關的重要工作;其他不重要的工作,都放在下半部分去做。

        從上面這張圖中可以看出,用來完成下半部分工作有好幾種機制可以選擇,每一種方式都是針對不同的需求場景。

        在每一種下半部分機制中,Linux都設計了非常方便的接口函數。

        作為開發者的我們來說,使用這些下半部分的機制很簡單,只需要幾個函數調用即可。

        例如:如果使用工作隊列來實現下半部分的工作,只需要2步動作:

        1. 定義處理函數

        image.png

        2. 在中斷處理函數中,注冊注冊函數

        INIT_WORK(&mywork, mywork_handler);                                                        

        schedule_work(&mywork);

        下面幾張圖,是針對每一種“下半部分”處理機制的一些特點,注意:有些機制在新版本中已經廢棄不用了,了解即可。

        中斷處理的注冊和注銷 API

        所謂的中斷注冊,就是告訴操作系統:我對哪個中斷感興趣。

        當這些中斷發生的時候,請通知我。通知的方式就是:調用一個預先注冊好的回調函數。

        驅動程序可以通過函數 request_irq(),向操作系統注冊,并且激活指定的中斷線:

        image.png

        參數說明:

        irq: 申請的硬件中斷號;

        handler: 中斷處理函數。一旦中斷發生,這個函數就被調用;

        flags: 中斷的屬性,例如:IRQF_DISABLED,IRQF_TIMER,IRQF_SHARED;

        devname: 中斷驅動程序的名稱,在 /proc/interrupts 文件中看到對應的內容;

        dev_id: 中斷程序的唯一標識,比如:在共享中斷中,可以用來區分不同的中斷處理程序;

        驅動程序通過函數 free_irq(),向操作系統注銷一個中斷處理函數:

        void free_irq(unsigned int irq, void *dev_id);

        參數說明:

        irq: 硬件中斷號;

        dev_id: 中斷程序的唯一標識;

        實操:捕獲鍵盤中斷 示例代碼

        有了上面的知識鋪墊,下面就來實操一下,實現的功能是:

        捕獲鍵盤的中斷,在中斷處理函數中,打印出按鍵的掃描碼,如果是 ESC 鍵被按下,就打印出指定的信息。

        與往常一樣,操作的目錄位于:tmp/linux-4.15/drivers 目錄下。

        $ mkdir my_driver_interrupt

        $ touch driver_interrupt.c

        文件內容:

        image.png

        上面的代碼,有兩個小的知識點。

        向驅動程序傳參

        示例代碼中,在調用 request_irq 時,需要指定中斷號和驅動程序的名稱。

        這兩個參數是在加載驅動模塊的時候,從命令行傳入的。

        在驅動程序中,通過下面兩行代碼即可實現參數的接收:

        module_param(irq, int, 0644);
        module_param(devname, charp, 0644);

        module_param 是一個宏定義,定義在 include/linux/moduleparam.h 文件中,具體定義如下:

        #define module_param(name, type, perm)                
           module_param_named(name, name, type, perm);

        name: 存儲參數的變量名;

        type: 變量的類型;

        perm: 訪問參數的權限,表示此參數在sysfs文件系統中所對應的文件節點的屬性;

        IO地址:IO端口和IO內存

        這是讀取 IO 外設的兩種不同方式。

        IO 端口有兩種編址方式:統一編址和獨立編址。

        統一編制

        把主存單元所在的地址空間,劃出一部分出來,專門用來把IO外設寄存器的地址映射到這部分劃出來的地址空間中。

        統一編址的好處是:讀取IO外設的時候,就好像讀取普通的內存地址空間中的數據一樣。

        獨立編址

        IO 外設的地址空間,與主存單元的地址空間是兩個獨立的地址空間,此時,IO地址一般稱作: IO端口。

        我們在讀寫IO外設的時候,從這些 “IO端口” 中讀寫就可以了。不同的外設,被分配了不同的 IO 端口號。

        CPU 提供了一些列函數來讀寫 IO 端口,例如:

        // 讀寫一個字節

        unsigned inb(unsigned port);

        void outb(unsigned char byte, unsigned port);

        // 讀寫一個字

        unsigned inw(unsigned port);

        void outw(unsigned short word, unsigned port);

        編譯、驗證

        編譯驅動模塊:

        $ make

        輸出文件:driver_interrupt.ko

        因為我們捕獲的是鍵盤中斷(中斷號:1),先看一下在加載驅動模塊之前的中斷驅動程序 head /proc/interrupts:

        可以把 demsg 的輸出也清理一下:dmesg -c

        執行下面指令來加載驅動模塊(傳遞2個參數):

        insmod driver_interrupt.ko irq=1 devname=myirq

        再次執行一下指令 head /proc/interrupts 查看驅動程序:

        在中斷號 1 的右側,是不是看到了我們的驅動程序:my_irq?

        再來看一下 dmesg 的輸出信息:

        成功注冊了中斷號1的處理函數!

        此時,按幾次鍵盤左上角的 ESC 鍵,然后再查看 dmesg 的輸出信息:

        以上,就是最簡單的中斷注冊和相應的中斷處理函數!

        在實際的項目中,如果要把中斷信息通知到應用層,可以通過上一篇文章介紹的發送信號來實現,或者通過其他的回調機制也可以。

        下一篇文章,我們在這個示例代碼上進行擴展,看一下:中斷處理中每一個“下半部分”機制應該如何編程。

        聲明: 本文由入駐維科號的作者撰寫,觀點僅代表作者本人,不代表OFweek立場。如有侵權或其他問題,請聯系舉報。

        發表評論

        0條評論,0人參與

        請輸入評論內容...

        請輸入評論/評論長度6~500個字

        您提交的評論過于頻繁,請輸入驗證碼繼續

        暫無評論

        暫無評論

          掃碼關注公眾號
          OFweek人工智能網
          獲取更多精彩內容
          文章糾錯
          x
          *文字標題:
          *糾錯內容:
          聯系郵箱:
          *驗 證 碼:

          粵公網安備 44030502002758號

          主站蜘蛛池模板: 日日夜夜噜噜| 超碰资源总站| 亚洲欧美另类图片| 国产成人无码A片免费看| 99精品丰满人妻无码一区二区| 北安市| jizz在线视频| 亚洲天堂男人| 亚洲91视频| 亚洲熟女VS国产对比| 91视频在线看| 亚洲中文字幕av| 无码18禁成人免费| 亚欧女AV| 奇米久久| 柳河县| 都安| 海角社区91熟女丝袜脚国产| 欧美视频一区| 伊人久久综合| 亚洲欧美V| 丝袜一级A片| 亚洲无码2| 老司机免费视频| 国产中文在线| 杨浦区| 虎林市| 亚洲中文字幕在线看| 欧美成人综合| 制服.丝袜.亚洲.中文.综合懂| 梅河口市| 文登市| 亚洲午夜视频| 青青草99| 色窝视频| 泸溪县| 西峡县| 苍南县| 赤峰市| 亚洲无码2| 日韩丨亚洲丨制服|痴汉|