国产一级一区二区_segui88久久综合9999_97久久夜色精品国产_欧美色网一区二区

掃一掃
關(guān)注微信公眾號(hào)

黑客進(jìn)階之Linux設(shè)備驅(qū)動(dòng)編程中斷處理
2007-01-17   

與Linux設(shè)備驅(qū)動(dòng)中中斷處理相關(guān)的首先是申請(qǐng)與釋放IRQ的API request_irq()和free_irq(),request_irq()的原型為:

int request_irq(unsigned int irq,
void (*handler)(int irq, void *dev_id, struct pt_regs *regs),
unsigned long irqflags,
const char * devname,
void *dev_id);

Irq是要申請(qǐng)的硬件中斷號(hào);

Handler是向系統(tǒng)登記的中斷處理函數(shù),是一個(gè)回調(diào)函數(shù),中斷發(fā)生時(shí),系統(tǒng)調(diào)用這個(gè)函數(shù),dev_id參數(shù)將被傳遞;

Irqflags是中斷處理的屬性,若設(shè)置SA_INTERRUPT,標(biāo)明中斷處理程序是快速處理程序,快速處理程序被調(diào)用時(shí)屏蔽所有中斷,慢速處理程序不屏蔽;若設(shè)置SA_SHIRQ,則多個(gè)設(shè)備共享中斷,dev_id在中斷共享時(shí)會(huì)用到,一般設(shè)置為這個(gè)設(shè)備的device結(jié)構(gòu)本身或者NULL。

Free_irq()的原型為:

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

另外,與Linux中斷息息相關(guān)的一個(gè)重要概念是Linux中斷分為兩個(gè)半部:上半部(tophalf)和下半部(bottom half)。上半部的功能是"登記中斷",當(dāng)一個(gè)中斷發(fā)生時(shí),它進(jìn)行相應(yīng)地硬件讀寫后就把中斷例程的下半部掛到該設(shè)備的下半部執(zhí)行隊(duì)列中去。因此,上半部執(zhí)行的速度就會(huì)很快,可以服務(wù)更多的中斷請(qǐng)求。但是,僅有"登記中斷"是遠(yuǎn)遠(yuǎn)不夠的,因?yàn)橹袛嗟氖录赡芎軓?fù)雜。因此,Linux引入了一個(gè)下半部,來(lái)完成中斷事件的絕大多數(shù)使命。下半部和上半部最大的不同是下半部是可中斷的,而上半部是不可中斷的,下半部幾乎做了中斷處理程序所有的事情,而且可以被新的中斷打斷!下半部則相對(duì)來(lái)說(shuō)并不是非常緊急的,通常還是比較耗時(shí)的,因此由系統(tǒng)自行安排運(yùn)行時(shí)機(jī),不在中斷服務(wù)上下文中執(zhí)行。

Linux實(shí)現(xiàn)下半部的機(jī)制主要有tasklet和工作隊(duì)列。

Tasklet基于Linux softirq,其使用相當(dāng)簡(jiǎn)單,我們只需要定義tasklet及其處理函數(shù)并將二者關(guān)聯(lián):

void my_tasklet_func(unsigned long); //定義一個(gè)處理函數(shù):
DECLARE_TASKLET(my_tasklet,my_tasklet_func,data); //定義一個(gè)tasklet結(jié)構(gòu)my_tasklet,與
my_tasklet_func(data)函數(shù)相關(guān)聯(lián)

然后,在需要調(diào)度tasklet的時(shí)候引用一個(gè)簡(jiǎn)單的API就能使系統(tǒng)在適當(dāng)?shù)臅r(shí)候進(jìn)行調(diào)度運(yùn)行:

tasklet_schedule(&my_tasklet);

此外,Linux還提供了另外一些其它的控制tasklet調(diào)度與運(yùn)行的API:

DECLARE_TASKLET_DISABLED(name,function,data); //與DECLARE_TASKLET類似,但等待tasklet被使能
tasklet_enable(struct tasklet_struct *); //使能tasklet 
tasklet_disble(struct tasklet_struct *); //禁用tasklet 
tasklet_init(struct tasklet_struct *,void (*func)(unsigned long),unsigned long); //類似
DECLARE_TASKLET() 
tasklet_kill(struct tasklet_struct *); // 清除指定tasklet的可調(diào)度位,即不允許調(diào)度該tasklet

我們先來(lái)看一個(gè)tasklet的運(yùn)行實(shí)例,這個(gè)實(shí)例沒有任何實(shí)際意義,僅僅為了演示。它的功能是:在globalvar被寫入一次后,就調(diào)度一個(gè)tasklet,函數(shù)中輸出"tasklet is executing":

#include 
… 
//定義與綁定tasklet函數(shù)
void test_tasklet_action(unsigned long t);
DECLARE_TASKLET(test_tasklet, test_tasklet_action, 0);

void test_tasklet_action(unsigned long t)
{
 printk("tasklet is executing\n");
}

…

ssize_t globalvar_write(struct file *filp, const char *buf, size_t len, loff_t *off)
{
 …
 if (copy_from_user(&global_var, buf, sizeof(int)))
 {
return - EFAULT;
 }

 //調(diào)度tasklet執(zhí)行
 tasklet_schedule(&test_tasklet);
 return sizeof(int);
}

由于中斷與真實(shí)的硬件息息相關(guān),脫離硬件而空談中斷是毫無(wú)意義的,我們還是來(lái)舉一個(gè)簡(jiǎn)單的例子。這個(gè)例子來(lái)源于SAMSUNG S3C2410嵌入式系統(tǒng)實(shí)例,看看其中實(shí)時(shí)鐘的驅(qū)動(dòng)中與中斷相關(guān)的部分:

static struct fasync_struct *rtc_async_queue;
static int __init rtc_init(void)
{
 misc_register(&rtc_dev);
 create_proc_read_entry("driver/rtc", 0, 0, rtc_read_proc, NULL);

 #if RTC_IRQ
if (rtc_has_irq == 0)
 goto no_irq2;

init_timer(&rtc_irq_timer);
rtc_irq_timer.function = rtc_dropped_irq;
spin_lock_irq(&rtc_lock);
/* Initialize periodic freq. to CMOS reset default, which is 1024Hz */
CMOS_WRITE(((CMOS_READ(RTC_FREQ_SELECT) &0xF0) | 0x06), RTC_FREQ_SELECT);
spin_unlock_irq(&rtc_lock);
rtc_freq = 1024;
no_irq2:
 #endif

 printk(KERN_INFO "Real Time Clock Driver v" RTC_VERSION "\n");
 return 0;
}

static void __exit rtc_exit(void)
{
 remove_proc_entry("driver/rtc", NULL);
 misc_deregister(&rtc_dev);

 release_region(RTC_PORT(0), RTC_IO_EXTENT);
 if (rtc_has_irq)
free_irq(RTC_IRQ, NULL);
}
static void rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
 /*
 * Can be an alarm interrupt, update complete interrupt,
 * or a periodic interrupt. We store the status in the
 * low byte and the number of interrupts received since
 * the last read in the r emainder of rtc_irq_data.
 */

 spin_lock(&rtc_lock);
 rtc_irq_data += 0x100;
 rtc_irq_data &= ~0xff;
 rtc_irq_data |= (CMOS_READ(RTC_INTR_FLAGS) &0xF0);

 if (rtc_status &RTC_TIMER_ON)
mod_timer(&rtc_irq_timer, jiffies + HZ / rtc_freq + 2 * HZ / 100);

 spin_unlock(&rtc_lock);

 /* Now do the rest of the actions */
 wake_up_interruptible(&rtc_wait);

 kill_fasync(&rtc_async_queue, SIGIO, POLL_IN);
}

static int rtc_fasync (int fd, struct file *filp, int on)
{
 return fasync_helper (fd, filp, on, &rtc_async_queue);
}

static void rtc_dropped_irq(unsigned long data)
{
 unsigned long freq;

 spin_lock_irq(&rtc_lock);

 /* Just in case someone disabled the timer from behind our back... */
 if (rtc_status &RTC_TIMER_ON)
mod_timer(&rtc_irq_timer, jiffies + HZ / rtc_freq + 2 * HZ / 100);

 rtc_irq_data += ((rtc_freq / HZ) << 8);
 rtc_irq_data &= ~0xff;
 rtc_irq_data |= (CMOS_READ(RTC_INTR_FLAGS) &0xF0); /* restart */

 freq = rtc_freq;

 spin_unlock_irq(&rtc_lock);
 printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n", freq);

 /* Now we have new data */
 wake_up_interruptible(&rtc_wait);

 kill_fasync(&rtc_async_queue, SIGIO, POLL_IN);
}

RTC中斷發(fā)生后,激發(fā)了一個(gè)異步信號(hào),因此本驅(qū)動(dòng)程序提供了對(duì)第6節(jié)異步信號(hào)的支持。并不是每個(gè)中斷都需要一個(gè)下半部,如果本身要處理的事情并不復(fù)雜,可能只有一個(gè)上半部,本例中的RTC驅(qū)動(dòng)就是如此。

責(zé)任編輯 趙毅 zhaoyi#51cto.com TEL:(010)68476636-8001


熱詞搜索:

上一篇:教你如何防止自己的IP泄漏
下一篇:黑客教程:絕對(duì)調(diào)用IE瀏覽器的彈出窗口

分享到: 收藏
国产一级一区二区_segui88久久综合9999_97久久夜色精品国产_欧美色网一区二区
91亚洲精品一区二区乱码| 欧美影院精品一区| 91国偷自产一区二区开放时间 | 国产一区二区三区四区五区入口| 91麻豆swag| 久久综合九色综合欧美98| 亚洲免费观看视频| 国产成人av电影在线播放| 欧美精品1区2区3区| 日本一区二区成人在线| 免费观看在线色综合| 91福利视频网站| 一区视频在线播放| 国产精品一区三区| 日韩一区二区三区电影在线观看| 亚洲精品欧美专区| 国产成人精品免费| 久久综合久色欧美综合狠狠| 日韩精品免费视频人成| 91美女精品福利| 亚洲国产精品成人综合色在线婷婷| 日本特黄久久久高潮| 欧美三级电影网站| 一区二区三区小说| 在线亚洲一区观看| 亚洲欧美日韩人成在线播放| 99在线精品观看| 国产欧美日韩在线视频| 国内精品久久久久影院薰衣草| 在线观看91视频| 亚洲在线一区二区三区| 欧美色精品在线视频| 亚洲18影院在线观看| 欧美日韩一本到| 日韩中文字幕区一区有砖一区| 欧美日韩一区小说| 亚洲成人先锋电影| 欧美一区二区三区小说| 免费高清不卡av| 精品成人免费观看| 国产激情视频一区二区在线观看 | 在线观看日产精品| 一区二区三区在线视频播放 | 国产成人免费视频一区| 精品乱人伦小说| 国产精品一二三在| 国产精品久久久久三级| 色爱区综合激月婷婷| 亚洲bt欧美bt精品777| 日韩精品中文字幕在线不卡尤物 | 色综合久久综合| 婷婷夜色潮精品综合在线| 91精品国产高清一区二区三区| 久久精品国产**网站演员| 精品国产免费久久| 成人午夜免费av| 亚洲国产一区在线观看| 日韩亚洲欧美一区| 国产成人激情av| 亚洲精品日韩一| 亚洲精品一线二线三线无人区| 国产成人无遮挡在线视频| 一区二区三区四区国产精品| 91精品一区二区三区在线观看| 韩国理伦片一区二区三区在线播放| 国产精品伦一区二区三级视频| 日本乱人伦aⅴ精品| 麻豆精品在线看| 国产精品国产三级国产普通话蜜臀| 欧美在线免费视屏| 国产一区二区免费在线| 一区二区三区高清在线| 日韩欧美综合在线| 99精品国产91久久久久久| 天堂va蜜桃一区二区三区漫画版| 国产午夜亚洲精品不卡| 欧美日韩久久一区| 国产一区二区福利| 亚洲一区在线观看网站| 中文字幕乱码日本亚洲一区二区| 在线日韩av片| 国产精品白丝av| 日韩影院免费视频| 亚洲视频在线一区二区| 欧美成人精品福利| 欧美三级电影一区| av在线不卡免费看| 精品一区二区三区影院在线午夜| 亚洲黄色免费网站| 久久久久久99精品| 日韩一级大片在线观看| 色综合咪咪久久| 国产suv一区二区三区88区| 久久99国产精品免费| 亚洲国产综合人成综合网站| 中文字幕日韩一区二区| 久久日韩粉嫩一区二区三区| 6080yy午夜一二三区久久| 色综合天天性综合| 91免费国产视频网站| 国产成人a级片| 久草这里只有精品视频| 婷婷中文字幕综合| 亚洲成av人片在线| 亚洲午夜精品网| 一二三区精品视频| 亚洲色图.com| 亚洲免费三区一区二区| 亚洲欧洲韩国日本视频| 国产精品天干天干在线综合| 久久一区二区三区四区| 久久一区二区三区国产精品| 欧美精品一区二区三区四区| 日韩免费成人网| 欧美一区二区三区视频在线| 51精品国自产在线| 777午夜精品免费视频| 91麻豆精品国产91久久久使用方法 | 国产精品电影一区二区| 欧美精品一区二区三区在线播放 | 欧美国产一区二区| 国产视频一区二区在线| 国产人久久人人人人爽| 国产精品色婷婷久久58| 国产精品久久久久久亚洲毛片| 亚洲私人黄色宅男| 亚洲国产va精品久久久不卡综合| 亚洲成av人片一区二区三区| 偷拍自拍另类欧美| 青娱乐精品视频| 国产一区中文字幕| 成人深夜视频在线观看| av欧美精品.com| 欧美亚日韩国产aⅴ精品中极品| 欧美天堂一区二区三区| 日韩一区二区三区三四区视频在线观看| 欧美一区二区三区在线看| 久久天天做天天爱综合色| 中文字幕在线免费不卡| 亚洲一区二区在线观看视频| 午夜免费久久看| 国产一区二区中文字幕| 99久久精品国产毛片| 欧美日韩国产色站一区二区三区| 日韩一区二区在线观看| 国产亚洲自拍一区| 一区二区三区在线观看视频| 日本亚洲电影天堂| 成人激情开心网| 欧美日韩精品久久久| 2021中文字幕一区亚洲| 亚洲色图20p| 精品一区二区在线视频| 91丨porny丨中文| 国产午夜精品福利| 一区二区三区四区在线免费观看| 免费视频一区二区| 成人丝袜视频网| 欧美日本精品一区二区三区| 国产午夜精品一区二区三区四区| 亚洲综合小说图片| 韩国精品一区二区| 欧美系列一区二区| 国产精品水嫩水嫩| 蜜臀av性久久久久蜜臀aⅴ| 91污在线观看| 久久精品在线免费观看| 日韩国产精品91| 91一区在线观看| 久久免费的精品国产v∧| 午夜精品久久久久久不卡8050| 国产精品白丝jk黑袜喷水| 欧美精品九九99久久| 中文字幕字幕中文在线中不卡视频| 午夜国产不卡在线观看视频| 成人精品gif动图一区| 91麻豆精品国产91久久久更新时间 | 91麻豆免费看| 精品国产麻豆免费人成网站| 亚洲美女屁股眼交3| 国产91在线观看丝袜| 久久久美女毛片| 日本中文一区二区三区| 欧美自拍偷拍午夜视频| 亚洲欧洲美洲综合色网| 国产成人av网站| 2020国产精品久久精品美国| 日本不卡视频在线| 欧美三级午夜理伦三级中视频| 亚洲同性同志一二三专区| 成人av资源在线观看| 国产精品全国免费观看高清| 黄网站免费久久| 日韩女优电影在线观看| 免费精品99久久国产综合精品| 欧美乱妇一区二区三区不卡视频| 亚洲一区精品在线| 在线亚洲欧美专区二区| 一区二区三区四区在线| 色天使色偷偷av一区二区|