Linux 中斷機制

來源:互聯網
上載者:User

1. 中斷處理常式架構
中斷服務程式的執行不存在於進程上下文,要求中斷服務程式的時間短,核心中對時鐘的處理也採用中斷方式
中斷機制提供了硬體和軟體之間非同步傳遞資訊的方式,硬體裝置在發生某個事件時通過中斷通知軟體進行處理
中斷實現了硬體裝置按需獲得處理器關注的機制,與查詢方式相比可以大大節省CPU時間
中斷處理常式可以分成兩部分上半部是實際ISR,在中斷髮生時被調用。
下半部是tasklet或work_queue,被上半部調度,在稍後的安全時間被調用

頂半部完成比較緊急的功能,(簡單地讀取寄存器中的中斷狀態並清除中斷標誌),執行速度快。
底半部可以被中斷打斷,完成絕大多數費時的任務(底半部機制有tasklet, work_queue)

2. 申請IRQ
request_irq()函數來註冊中斷服務函數,Linux2.6核心所需包含的標頭檔是#include <linux/interrupt.h>
定義如下
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
   const char *name, void *dev)
{
return request_threaded_irq(irq, handler, NULL, flags, name, dev);
}

參數:
@irq:是要申請的硬體中斷號
@handler:向系統登記的中斷處理函數(頂半部),是一個回呼函數,中斷髮生時,系統調用這個函數
dev參數將傳給它。
@flags:中斷處理屬性在<linux/interrupt.h>中有定義
#define IRQF_DISABLED 0x00000020
表明中斷處理常式是快速處理常式,被調用時屏掉所有中斷
#define IRQF_SHARED 0x00000080
表示多個裝置共用中斷,參數dev在中斷共用時會用到。
@name:裝置驅動的名稱用在/proc/interrupt系統檔案上

3. 釋放IRQ
void free_irq(unsigned int irq, void *dev_id)

4. 中斷底半部機制
Linux實現底半部的機制主要有tasklet、workqueue、soft_irq
1)tasklet
每個tasklet都和一個函數相關聯。當tasklet被運行時,該函數就被調用,並且tasklet可以調度自己
I)定義一個tasklet 結構
struct tasklet_struct keyboard_tasklet;
II)定義一個tasklet處理函數
static void keyboard_func(unsigned long);
III)tasklet結構與函數綁定
static DECLARE_TASKLET(keyboard_tasklet, keyboard_func, data);
傳入這個函數的參數為data
IV)調度tasklet

tasklet_schedule(&keyboard_tasklet);

tasklet使用模板/**定義tasklet和底半部函數並關聯*/struct tasklet_struct xxx_tasklet;void xxx_do_tasklet(unsigned long);DECLARE_TASKLET(xxx_tasklet, xxx_do_tasklet, 0);/**中斷處理底半部*/void xxx_do_tasklet(unsigned long){}/**中斷處理頂半部*/irqreturn_t xxx_interrupt(int irq, void *dev_id){...taklet_schedule(&xxx_tasklet);...return IRQ_HANDLED;}/**裝置驅動模組載入函數*/int __init xxx_init(void){.../**申請中斷*/result = request_irq(xxx_irq, xxx_interrupt, IRQF_DISABLED, "xxx", NULL);...}/**裝置驅移除函數*/void __exit xxx_exit(void){.../**釋放中斷*/free_irq(dev->irq, dev);...}

2)工作隊列tasklet運行於中斷上下文 工作隊列運行於進程上下文 tasklet處理函數中不能睡眠,而工作隊列處理函數中允許睡眠 I)定義一個工作隊列結構struct work_struct my_wq;II)定義一個處理函數void my_wq_func(unsigned long);III)初始化這個工作隊列並將工作隊列與函數綁定INIT_WORK(&my_wq, (void(*)(void *))my_wq_func, NULL);IV)調度工作隊列執行schedule_work()schedule_work(&my_wq);-----------------------------------------------------工作隊列使用模板/**定義工作隊列和關聯函數*/struct work_struct xxx_wq;void xxx_do_work(unsigned long);/**中斷處理底半部*/void xxx_do_work(unsigned long){...}/**中斷處理頂半部*/irqreturn_t xxx_interrupt(int irq, void *dev_id){...schedule_work(&xxx_wq);...return IRQ_HANDLED;}/**裝置驅動模組載入函數*/int __init xxx_init(void){.../**申請中斷*/result = request_irq(xxx_irq, xxx_interrupt, IRQF_DISABLED, "xxx", NULL);.../**初始化工作隊列*/INIT_WORK(&xxx_wq, (void(*)(void*))xxx_do_work, NULL);...}/**裝置驅動移除函數*/void xxx_exit(void){.../**釋放中斷*/free_irq(&dev->irq, dev);...}

5. 中斷例子/***interrupt key kernel 2.6.35.7*/#include <linux/module.h>#include <linux/init.h>#include <linux/interrupt.h>#include <linux/fs.h>#include <mach/gpio.h>#define KEY_MAJOR 233#define DEVICE_NAME "gpio_key1"struct work_struct work;static void gpio_key_work_func(struct work_struct *work){printk("the code is 101\n");}static irqreturn_t gpio_key_isr(int irq, void *dev_id){schedule_work(&work);return IRQ_HANDLED;}int key_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){return 0;}static const struct file_operations key_ops = {.owner = THIS_MODULE,.ioctl = key_ioctl,};static int __init gpio_keys_init(void){int ret = 0;int irq;//中斷號unsigned long irqflags;ret = register_chrdev(KEY_MAJOR, DEVICE_NAME, &key_ops);if (ret < 0) {printk("can't register gpio_keys_number\n");return -1;}//申請管腳gpio_request(S3C64XX_GPN(0), "HOME");//設定為輸入gpio_direction_input(S3C64XX_GPN(0));irq = gpio_to_irq(S3C64XX_GPN(0));printk("the gpio_key irq is [%d]\n ", irq);irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;ret = request_irq(irq, gpio_key_isr, irqflags, "HOME", NULL);if (ret) {printk("can't get gpio irq\n");return -1;}INIT_WORK(&work, gpio_key_work_func);printk("gpio_keys init\n");return 0;}static void __exit gpio_keys_exit(void){unregister_chrdev(KEY_MAJOR, DEVICE_NAME);}module_init(gpio_keys_init);module_exit(gpio_keys_exit);MODULE_LICENSE("GPL");-------------------------------測試,按鍵# the code is 101# cat /proc/interrupts 101:          6    s3c-eint  HOME中斷被用了6次

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.