Linux設備驅動——中斷、并發(fā)請求及周期性事件處理_第1頁
Linux設備驅動——中斷、并發(fā)請求及周期性事件處理_第2頁
Linux設備驅動——中斷、并發(fā)請求及周期性事件處理_第3頁
Linux設備驅動——中斷、并發(fā)請求及周期性事件處理_第4頁
Linux設備驅動——中斷、并發(fā)請求及周期性事件處理_第5頁
已閱讀5頁,還剩24頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

1、123 3Linux內(nèi)核中斷處理Linux內(nèi)核異步數(shù)據(jù)處理_kfifoLinux內(nèi)核并發(fā)與同步機制Linux下延時與內(nèi)核定時器4 4Linux內(nèi)核中斷處理Linux內(nèi)核異步數(shù)據(jù)處理_kfifoLinux內(nèi)核并發(fā)與同步機制Linux下延時與內(nèi)核定時器5 5 LinuxLinux操作系統(tǒng)下同裸機程序一樣,需要利用中斷操作系統(tǒng)下同裸機程序一樣,需要利用中斷機制來處理硬件的異步事件,但用戶態(tài)不允許中斷事機制來處理硬件的異步事件,但用戶態(tài)不允許中斷事件,因此中斷必須由設備驅動程序來接收與處理件,因此中斷必須由設備驅動程序來接收與處理 同裸機一樣,同裸機一樣,linuxlinux下的中斷分為兩種:下的中斷

2、分為兩種:irqirq、fiqfiq fiq fiq又稱快速中斷,在此期間機器的其他部分被鎖又稱快速中斷,在此期間機器的其他部分被鎖定,不會響應其它任何中斷定,不會響應其它任何中斷 irq irq又稱慢速中斷,處理需要較長的時間,在此期又稱慢速中斷,處理需要較長的時間,在此期間可能發(fā)生其它更高等級的中斷間可能發(fā)生其它更高等級的中斷 如果如果CPUCPU接收到一個中斷,它會停止一切工作,調(diào)接收到一個中斷,它會停止一切工作,調(diào)用中斷處理函數(shù),此時進程調(diào)度也會停止,所以就要用中斷處理函數(shù),此時進程調(diào)度也會停止,所以就要求我們的中斷處理一定要快求我們的中斷處理一定要快6 6#include /內(nèi)核中使

3、用中斷需添加此文件內(nèi)核中使用中斷需添加此文件/ 申請中斷申請中斷int request_irq(unsigned int irq, void(*handler)(int,void*,struct pt_regs*), unsigned long irqflag, const char *devname, void *dev_id);參數(shù)參數(shù)1:中斷號,所申請的中斷向量,比如:中斷號,所申請的中斷向量,比如EXIT0、uart中斷等中斷等參數(shù)參數(shù)2:中斷服務程序:中斷服務程序參數(shù)參數(shù)3:中斷屬性設置:中斷屬性設置/ SA_INTERRUPT, 快速中斷,禁止其他中斷快速中斷,禁止其他中斷/ SA

4、_SHIRQ, 共享中斷共享中斷/ SA_SAMPLE_RANDOM, 中斷可能被用來產(chǎn)生隨機數(shù)中斷可能被用來產(chǎn)生隨機數(shù)/ dev_id: 在共享中斷時用于區(qū)分不同的中斷處理程序在共享中斷時用于區(qū)分不同的中斷處理程序參數(shù)參數(shù)4:中斷名字,:中斷名字,cat /proc/interrupts 可察看系統(tǒng)中斷申請與使用情況可察看系統(tǒng)中斷申請與使用情況參數(shù)參數(shù)5:中斷參數(shù),作為共享中斷時的中斷區(qū)別參數(shù):中斷參數(shù),作為共享中斷時的中斷區(qū)別參數(shù)7 7/ 釋放中斷釋放中斷void free_irq(unsigned int irq, void *dev_id);參數(shù)參數(shù)1:所要清除中斷服務程序的中斷號:所

5、要清除中斷服務程序的中斷號參數(shù)參數(shù)2:中斷參數(shù),同申請時的值一致:中斷參數(shù),同申請時的值一致/ 使能中斷使能中斷void enable_irq(unsigned int irq);/ 禁止中斷禁止中斷void disable_irq(unsigned int irq);參數(shù):中斷號參數(shù):中斷號8 8#include / S3C2410使能使能GPIO的外部中斷功能的外部中斷功能int set_external_irq(int irq, int edge, int pullup);/ 參數(shù)參數(shù)1:中斷號:中斷號/ 參數(shù)參數(shù)2:外部中斷觸發(fā)方式外部中斷觸發(fā)方式/ EXT_LOWLEVEL,/ EX

6、T_HIGHLEVEL,/ EXT_FALLING_EDGE,/ EXT_RISING_EDGE,/ EXT_BOTH_EDGES/ 參數(shù)參數(shù)3:上拉是否使能:上拉是否使能 0:使能使能 1:禁止:禁止9 9/ 示例示例/ 中斷處理程序中斷處理程序void handler(int irq,void *dev_id,struct pt_regs *regs) / 中斷處理中斷處理參數(shù)參數(shù)1:中斷號,在不同中斷共用一個中斷服務程序時區(qū)分各中斷:中斷號,在不同中斷共用一個中斷服務程序時區(qū)分各中斷參數(shù)參數(shù)2:中斷參數(shù),不同設備分享同一中斷時,區(qū)分中斷來源:中斷參數(shù),不同設備分享同一中斷時,區(qū)分中斷來源

7、參數(shù)參數(shù)3:發(fā)生中斷時寄存器上保存的值傳遞給:發(fā)生中斷時寄存器上保存的值傳遞給regs,通常不使用本參數(shù),通常不使用本參數(shù)/ 在初始化時申請并初始化中斷在初始化時申請并初始化中斷set_external_irq(IRQ_EINT0, EXT_FALLING_EDGE, 0);request_irq(IRQ_EINT0,handler,SA_INTERRUPT,KEY,NULL);1010驅動程序對上層提供的read/write方法并不直接完成硬件的數(shù)據(jù)操作中斷處理程序相對獨立read/write方法與中斷 通過緩沖區(qū)交換數(shù)據(jù)1111Linux內(nèi)核中斷處理Linux內(nèi)核異步數(shù)據(jù)處理_kfifoL

8、inux內(nèi)核并發(fā)與同步機制Linux下延時與內(nèi)核定時器1212 在驅動編程中,經(jīng)常會遇到異步數(shù)據(jù)處理的情況,比如采用中斷或定時器處理數(shù)據(jù)輸入輸出等情況 此時數(shù)據(jù)的采集與處理往往不同步,于是驅動編程中數(shù)據(jù)采集方需要將采集的數(shù)據(jù)暫時放到一個緩沖區(qū)中,使用方在需要處理數(shù)據(jù)時從緩沖區(qū)中將數(shù)據(jù)讀出 驅動編程中常采用隊列這種數(shù)據(jù)結構來實現(xiàn)整個過程,我們可以選擇自己編寫一個隊列,也可以利用內(nèi)核中現(xiàn)有隊列kfifo來實現(xiàn)1313#include #include /為防止多個程序同時訪問該隊列,需要定義一個自旋為防止多個程序同時訪問該隊列,需要定義一個自旋鎖,該鎖由鎖,該鎖由kfifokfifo維護,我們只需

9、要定義它即可維護,我們只需要定義它即可static spinlock_tstatic spinlock_t buffer_lock=SPIN_LOCK_UNLOCKED; buffer_lock=SPIN_LOCK_UNLOCKED;/ / 定義一個定義一個kfifokfifo指針指針static struct kfifostatic struct kfifo * *buffer;buffer;/ / 使用使用kfifo_allockfifo_alloc創(chuàng)建一個創(chuàng)建一個BUFFER_SIZEBUFFER_SIZE大小的大小的fifo, fifo, 所有空間由所有空間由kfifokfifo自動分

10、配自動分配#define#define BUFFER_SIZE BUFFER_SIZE256256buffer = kfifo_alloc(BUFFER_SIZE,GFP_KERNEL,buffer = kfifo_alloc(BUFFER_SIZE,GFP_KERNEL, &buffer_lock); &buffer_lock);1414/ / 使用使用kfifo_putkfifo_put將數(shù)據(jù)放入將數(shù)據(jù)放入kfifokfifo內(nèi)內(nèi)kfifo_put(buffer, &key, sizeof(key);kfifo_put(buffer, &key, sizeo

11、f(key);/ / 使用使用kfifo_lenkfifo_len檢查檢查fifofifo內(nèi)的可用數(shù)據(jù)內(nèi)的可用數(shù)據(jù)/ / 使用使用kfifo_getkfifo_get從從fifofifo內(nèi)取出數(shù)據(jù)內(nèi)取出數(shù)據(jù)if(kfifo_len(buffer) = sizeof(key)if(kfifo_len(buffer) = sizeof(key)kfifo_get(buffer, &key, sizeof(key);kfifo_get(buffer, &key, sizeof(key);/釋放創(chuàng)建的釋放創(chuàng)建的FIFOFIFOkfifo_free(buffer);kfifo_free(

12、buffer);1515Linux內(nèi)核中斷處理Linux內(nèi)核異步數(shù)據(jù)處理_kfifoLinux內(nèi)核并發(fā)與同步機制Linux下延時與內(nèi)核定時器1616 中斷處理、多任務環(huán)境、多處理器(SMP)是現(xiàn)代操作系統(tǒng)的特征 當多個進程、線程或中斷、正常用戶程序同時訪問同一個資源,可能導致錯誤 因此內(nèi)核需要提供并發(fā)控制機制,對公共資源的訪問進行同步控制,確保共享資源的安全訪問 linux中包含了眾多的同步機制,包括信號量、自旋鎖、原子操作、讀寫鎖等1717 自旋鎖自旋鎖是一種輕量級的多處理器間的同步機制 它是一種忙等待機制,它要求持有鎖的進程或應用程序所占用的時間盡可能短,因為此時別的進程或 應用程序正在高

13、速運轉并等待鎖的釋放,所以不能長時間占有 信號量信號量是一種睡眠鎖,如果有一個任務試圖獲得一個已經(jīng)被占用的信號量時,信號量會將其推進一個等待隊列,然后讓其睡眠。當持有信號量的進程將信號量釋放后,處于等待隊列中的那個任務將被喚醒,并獲得該信號量。這就比自旋鎖提供更好的處理器利用率,因為把時間花費在忙等待上,但是,信號量比自旋鎖有更大的開銷。1818中。中。/定義自旋鎖,在編譯時對自旋鎖的初始化:定義自旋鎖,在編譯時對自旋鎖的初始化:spinlock_tspinlock_t my_lock=SPIN_LOCK_UNLOCKED; my_lock=SPIN_LOCK_UNLOCKED;/在使用中初始

14、化自旋鎖在使用中初始化自旋鎖voidvoid spin_lock_init( spin_lock_init(spinlock_tspinlock_t * *lock); lock); /獲得自旋鎖,進入臨界區(qū),自旋鎖忙則自旋等待:獲得自旋鎖,進入臨界區(qū),自旋鎖忙則自旋等待:spin_lock(&my_lock);spin_lock(&my_lock);/嘗試獲得自旋鎖,成功返回真,失敗則返回假嘗試獲得自旋鎖,成功返回真,失敗則返回假intint spin_trylock (spinlock_t spin_trylock (spinlock_t * *lock); lock);

15、/ /釋放自旋鎖,退出臨界區(qū)釋放自旋鎖,退出臨界區(qū)spin_unlock(&my_lock);spin_unlock(&my_lock);1919/ / 使用信號量控制并發(fā)請求使用信號量控制并發(fā)請求#include#include / / 定義信號量變量定義信號量變量struct struct semaphore bufflock;semaphore bufflock;/ / 初始化信號量初始化信號量void void sema_init(sema_init(struct struct semaphore semaphore * *sem, sem, intint););/ /

16、 獲取(等待)信號量,不能被打斷,會導致調(diào)用者睡眠獲取(等待)信號量,不能被打斷,會導致調(diào)用者睡眠void void down(down(struct struct semaphore semaphore * *sem);sem);/ / 獲?。ǖ却┬盘柫浚杀黄渌盘柎驍啵┇@?。ǖ却┬盘柫浚杀黄渌盘柎驍啵﹊nt int down_interruptible(down_interruptible(struct struct semaphore semaphore * *sem);sem);/嘗試獲得信號量,如過可獲得,他就獲得信號量并返回嘗試獲得信號量,如過可獲得,他就獲得信號量并返回

17、0 0,否則,否則返回非返回非0 0,不會導致調(diào)用者睡眠,不會導致調(diào)用者睡眠int int down_down_trylock(trylock(struct struct semaphore semaphore * *sem);sem);/ / 釋放信號量,即使信號量加釋放信號量,即使信號量加1 1void void up(up(struct struct semaphore semaphore * *sem);sem);2020Linux內(nèi)核中斷處理Linux內(nèi)核異步數(shù)據(jù)處理_kfifoLinux內(nèi)核并發(fā)與同步機制Linux下延時與內(nèi)核定時器2121 在驅動編程中經(jīng)常會用到一些延時函數(shù)或內(nèi)在

18、驅動編程中經(jīng)常會用到一些延時函數(shù)或內(nèi)核定時器來處理周期性事件核定時器來處理周期性事件 內(nèi)核中的短延時常用以下函數(shù):內(nèi)核中的短延時常用以下函數(shù): ndelay(n) /納秒級延時納秒級延時 udelay(n) /微秒級延時微秒級延時 mdelay(n) /毫秒級延時毫秒級延時 這三個延時函數(shù)輸入忙等待,一般不太長的這三個延時函數(shù)輸入忙等待,一般不太長的時間可以用它時間可以用它2222 內(nèi)核中有一個非常重要的全局變量:jiffies 它是一個無符號32位整數(shù),用來記錄自內(nèi)核上一次啟動以來的時鐘滴答數(shù) 在不同的平臺中,此時鐘滴答不一樣,在ARM平臺,一般為1/100s 我們可以利用此函數(shù)做一些延時操

19、作,例如系統(tǒng)中給出了以下幾個時間比較宏 #define time_after(a,b) /a是否在b之后 #define time_before(a,b) /a是否在b之前 #define time_after_eq(a,b) /a是否在b之后或等于b #define time_after_eq(a,b) /a是否在b之前或等于b2323/ 使用定時器處理周期性事件使用定時器處理周期性事件#include / 定義定時器定義定時器struct timer_lists /內(nèi)核原型內(nèi)核原型 struct list_head list; /用來形成鏈表用來形成鏈表,由內(nèi)核管理,申請一個定時器,自動加

20、入鏈表由內(nèi)核管理,申請一個定時器,自動加入鏈表 unsigned long expires; /定時器到期時間(指定一個時刻,而不是時間周期):定時器到期時間(指定一個時刻,而不是時間周期): jiffies,HZ unsigned long data; / 作為參數(shù)被傳入定時器處理函數(shù)作為參數(shù)被傳入定時器處理函數(shù) void (*function)(unsigned long); / 定時器處理函數(shù)定時器處理函數(shù);2424/ / 初始化定時器初始化定時器 把鏈表前后置空把鏈表前后置空void void init_timer(init_timer(struct struct timer_list

21、 timer_list * *timer);timer);/ / 添加定時器添加定時器 ,加入鏈表。開始起作用,加入鏈表。開始起作用void void add_timer(add_timer(struct struct timer_list timer_list * * timer); timer);/ / 刪除定時器刪除定時器int int del_timer(del_timer(struct struct timer_list timer_list * * timer); timer);void void timerHandler(timerHandler(unsigned long un

22、signed long data)data) / /data: data: 定時器參數(shù)定時器參數(shù) 2525/ / 定時器示例定時器示例struct struct timer_list myTimer; timer_list myTimer; init_timer(&myTimer);init_timer(&myTimer);myTimer.expires = jiffies + myTimer.expires = jiffies + 3 3 * * HZ; HZ;myTimer.data = myTimer.data = 0L0L; ;myTimer.function = ti

23、merHandler;myTimer.function = timerHandler;add_timer(&myTimer);add_timer(&myTimer);/ / 定時器處理函數(shù)定時器處理函數(shù)void void timerHandler(timerHandler(unsigned long unsigned long data)data) / / 如需重復執(zhí)行如需重復執(zhí)行, , 需要重新初始化并啟動定時器需要重新初始化并啟動定時器 myTimer.expires = jiffies + myTimer.expires = jiffies + 3 3 * * HZ; HZ; add_timer(&myTimer); add_timer(&myTimer); 2626/ / 使用內(nèi)核線程處理周期性事件使用內(nèi)核線程處理周期性事件#include#include / / 創(chuàng)建內(nèi)核線程(實際上是進程占用調(diào)度器,占用較多創(chuàng)建內(nèi)核線程(實際上是進程占用調(diào)度器,占用較多的資源)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論