1. 程式人生 > >Arm+Linux核心驅動學習筆記

Arm+Linux核心驅動學習筆記

韋東山老師幫我們把框架搭建起來了,我們先來看一下: 框架: app:      open,read,write "1.txt" ---------------------------------------------  檔案的讀寫 檔案系統: vfat, ext2, ext3, yaffs2, jffs2      (把檔案的讀寫轉換為扇區的讀寫) -----------------ll_rw_block-----------------  扇區的讀寫                        1. 把"讀寫"放入佇列                        2. 呼叫佇列的處理函式(優化/調順序/合併)
            塊裝置驅動程式      --------------------------------------------- 硬體:        硬碟,flash 我們在來囉嗦一下:在應用程式對檔案的讀寫通過具體的檔案系統被轉換為對扇區的讀寫,對扇區的讀寫呼叫的是ll_rw_block這個函式,對扇區進行讀寫的時候會根據某種排程進行優化,之後通過塊裝置驅動程序來訪問具體的硬體。 那麼到底是不是這個樣子呢?閒話少說,來看原始碼: 由於我們主要關心核心而不是檔案系統,所以我們從ll_rw_block函式開始分析
ll_rw_block(int rw, int nr, struct buffer_head *bhs[])
          for (i = 0; i < nr; i++)  {
             struct buffer_head *bh = bhs[i];//將資料存進bh
             submit_bh(rw, bh);}//提交資料
               struct bio *bio; // bio即block input/output,接下來根據bh來構造bio
             bio->bi_size = bh->b_size;//這是一個例子
               submit_bio(rw, bio);//提交bio
             generic_make_request(bio);// 通用的構造請求: 使用bio來構造請求(request)
             __generic_make_request(bio);
             q = bdev_get_queue(bio->bi_bdev);// 找到佇列
               ret = q->make_request_fn(q, bio);//呼叫q中的構造請求函式,詳見註釋1
             __make_request;//上面的那條程式碼實際上是執行這個函式
               elv_merge(q, &req, bio);//先嚐試將bio合併到請求佇列中的某個請求中
               req = get_request_wait(q, rw_flags, bio);//如果無法將bio合併到某一請求,就會構造一個請求
               init_request_from_bio(req, bio);//根據bio初始化這個請求
               add_request(q, req);//把請求放入佇列 ,這裡採用的電梯排程演算法,詳見註釋2
             __generic_unplug_device(q);//在適當的時候處理佇列裡面的請求,這個有核心決定
               q->request_fn(q);//呼叫佇列的"處理函式,我們猜想他應該在裝置驅動程式裡                       //面被設定
上面就是讀寫塊裝置的流程框架了,由於本人比較笨,所以還得再來羅嗦一遍它的流程:
首先應用程式裡面用讀寫函式讀寫檔案,通過檔案系統呼叫ll_rw_block函式,在這個函式裡會根據傳遞進來的資料構造出來一個塊裝置輸入輸出結構體。然後先試圖將這個結構體合併到塊裝置的請求佇列中的某一個請求中,如果如法合併的話,就會根據這個結構體構造出來一個新的請求,然後根據電梯排程演算法將這個請求加入到請求佇列中去。之後核心在適當的時候會根據佇列裡面的處理函式來處理佇列裡面的請求。由此我們也可以猜測出來我們的驅動程式裡面需要做的事情了:應用程式裡面讀寫塊裝置的時候會將請求放入塊裝置佇列裡面,我們要處理請求的話當然是要在塊裝置驅動程式裡面為塊裝置分配一個佇列,然後初始化它,最主要的不要忘記佇列處理函式。
註釋1: q->make_request_fn是預設的函式,我們在核心中搜索過程如下: 首先我們發現q->make_request_fn在下面這個函式裡被設定:
void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn)
{
          q->make_request_fn = mfn;
}

那麼mfn這個函式是什麼東西呢?要想知道需要搜尋誰呼叫了blk_queue_make_request
blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id)
{
          blk_queue_make_request(q, __make_request);
}

終於我們找到了這個預設函式__make_request,也就是說ret = q->make_request_fn(q, bio);這調程式碼實際上是執行__make_request這個函式。 註釋2 電梯排程演算法:我們先來說一說電梯是怎樣工作的。當電梯上的時候,如果在電梯所在層的上層和下層都有請求的話,電梯會先處理上層的請求,同樣當電梯下的時候如果上層下層都有請求的話,電梯會先處理下層的請求。那麼我們這裡電梯排程演算法也是採用如此的策略,比如當讀資料的時候,如果有讀請求也有寫請求,那麼要先處理讀請求。在寫資料的時候,如果有讀請求也有寫請求,那麼先處理寫請求。

相關推薦

Arm+Linux核心驅動學習筆記

韋東山老師幫我們把框架搭建起來了,我們先來看一下: 框架: app:      open,read,write "1.txt" ---------------------------------------------  檔案的讀寫 檔案系統: vfat, ext2,

linux裝置驅動學習筆記--核心除錯方法之printk

1,printk類似於使用者態的printf函式,但是比printf函式多了一個日誌級別,核心中最常見的日誌輸出都是通過呼叫printk來實現的,其列印級別有8種可能的記錄字串, 在標頭檔案 <linux/kernel.h> 裡定義: KERN_EMERG

linux裝置驅動學習筆記--核心除錯方法之proc(補充seq_file)

上一節中的proc實現對於開關檔案,控制檔案,以及顯示很少資訊的檔案來說還是比較簡單的,但是對於需要輸出大量資訊像meminfo,或者結構化的資訊像cpuinfo等時就會顯得很笨拙,並且程式碼也很不好理解與維護。核心為了簡化這種proc檔案的實現提供了另外一種方案----s

linux裝置驅動學習筆記--核心除錯方法之proc

/proc 檔案系統是 GNU/Linux 特有的。它是一個虛擬的檔案系統,因此在該目錄中的所有檔案都不會消耗磁碟空間。通過它能夠非常簡便地瞭解系統資訊,尤其是其中的大部分檔案是人類可閱讀的(不過還是需要一些幫助)。許多程式實際上只是從 /proc 的檔案中收集資訊,然後按

linux核心程式設計學習筆記

常見問題 一、核心模組A呼叫核心模組B 檢視匯出的核心符號表 cat /proc/kallsyms | grep 'func_m2' 1、一個核心模組A呼叫另一個核心模組B的匯出函式,需要做到三點 1.模組B先載入 2.模組B函式匯出成功 3.模組B編譯後會有個Module.sy

Linux核心驅動學習(二)----根檔案系統的構成 (root filesystem)

1、建立根檔案系統目錄和檔案 1.1建立目錄 1.2建立裝置檔案(命令mknod);必須建立裝置檔案---consle\null 1.3建立配置檔案---複製已有的/etc目錄下的檔案

ARM Linux核心驅動異常定位除錯--反彙編arm-linux-objdump

最近在搞Atmel 的SAM9x25平臺,Linux系統,用於工業裝置。這也是我首次參與工業裝置的研發。在除錯Atmel SAM9x25的Linux串列埠裝置的時候,發現無論是讀還是寫,都會產生異常。相關的異常資訊如下: ===========================================

linux 核心hash_list學習筆記

linux核心為了方便進行連結串列的操作,定義了一系列很方便的巨集定義,在平時的專案開發中,應用巨集定義能使得專案事半功倍,下面是核心實現原始碼的實現,僅重定義了名字,正在學習,就暫時記錄下來吧: 結構定義: typedef struct hlist_node

Linux核心驅動學習(四)----記憶體管理子系統

kmalloc()和vmalloc()介紹 kmalloc() 用於申請較小的、連續的實體記憶體 1. 以位元組為單位進行分配,在<linux/slab.h>中 2. void *kmalloc(size_t size, int flags) 分配的記憶體實體地址上連續,虛擬地址上自然

linux核心模組學習筆記 ----- 核心模組的編譯和載入

核心模組的編譯 編譯方法一: 在系統中已經存在核心程式碼樹結構的前提下,假定核心程式碼目錄位於 /usr/src/linux-4.17-rc3目錄下。編寫如下makefile檔案,makefile檔案內容如下: obj-m:=module.o module-ob

linux I2C 裝置驅動學習筆記

一:I2C 概述           I2C是philips提出的外設匯流排.使用SCL時鐘線,SDA序列資料線這兩根訊號線就實現了裝置之間的資料互動,被非常廣泛地應用在CPU與EEPROM,實時鐘,小型LCD等裝置通訊中。  二:在linux下的驅動思路     linu

linux驅動學習筆記---s5pv210(一)

1,解壓核心原始碼 tar -xvf linux-3.0.8.tar.bz2 2,核心的編譯步驟:     a,設定交叉工具鏈--目標檔案執行在arm處理上, 修改Makefile          195 ARCH            ?= arm          1

Linux系統SPI驅動學習筆記(一)

  SPI是"Serial Peripheral Interface" 的縮寫,是一種四線制的同步序列通訊介面,用來連線微控制器、感測器、儲存裝置,SPI裝置分為主裝置和從裝置兩種,用於通訊和控制的四根線分別是: CS    片選訊號SCK  時鐘訊號MISO  主裝置的

使用Buildroot與Qemu學習ARM linux IIC驅動

Buildroot配置 下載最新的buildroot,然後進入 buildroot中進行配置 make mini2440_defconfig make xconfig 進入到Ker

Linux驅動學習筆記----------IIC框架與流程(一)

歷時一個月期末課程設計終於結束了!發現好多東西忘記了,iic流程也有些淡忘,有點慌,夜深人靜的時候就整理下吧!還有,杭州最近熱的我腦袋都不好用了! 關於iic: 1.是一種資料傳輸協議(spi,usb,sdio,uart…)

Linux裝置與驅動學習筆記(概述)

由於在下能力相當有限,有不當之處,還望批評指正^_^一、概述在核心中,匯流排/裝置/驅動模型實現了對匯流排/裝置/驅動的管理。涉及的概念有struct bus_type(匯流排型別)。核心並不關心每種匯流排的實現細節,也未預先定義一共有哪些具體的匯流排型別。因此,開發者甚至可

Java核心技術學習筆記-繼承

java 繼承按照我們中文通俗的理解是不需要付出努力,就獲得別人的能力或資產,比如繼承父輩的家產,繼承父輩的表達能力,繼承父輩的外貌等等。在類裏面的繼承,可以理解不需要重新開發代碼,就能復用父類的方法和域。 在繼承關系裏面,可以分為父類和子類,子類繼承父類,那子類就有了跟父類一樣對外的方法

Linux程序設計學習筆記——異步信號處理機制

基本概念 erro 驗證 添加 uid 函數 count ubun generate 轉載請註明出處: http://blog.csdn.net/suool/article/details/38453333 Linux常見信號與處理 基本概念 Linux的信號是一

Linux 程序設計學習筆記----Linux下文件類型和屬性管理

腳本 types.h 沒有 oot 創建 jsb 文件 屬性 文件大小 轉載請註明出處:http://blog.csdn.net/suool/article/details/38318225 部分內容整理自網絡,在此感謝各位大神。 Linux文件類型和權限 數據表示

Linux運維學習筆記之一:運維的原則和學習方法

linux 運維 筆記 一直在用Linux,但從未系統學習過,從1月1日開始學習到7月16日結束,近七個月學習,讓自已對Linux有了新的認識,老男孩老師的課真的不錯,實戰性很強。由於只能中午和晚上10點以後才有時間,所以所有的實驗是在不同電腦上完成的,文中IP可能有點問題,但應該不會影響實驗。同時,為了保證