国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
Request_irq和setup_irq的區(qū)別 - Linux Kernel&Drive...









Request_irqsetup_irq的區(qū)別

Author: Dongas

Data: 08-07-19

 

Linux 內(nèi)核提供了兩個(gè)注冊(cè)中斷處理函數(shù)的接口:setup_irqrequest_irq。這兩個(gè)函數(shù)都定義在kernel/irq/manage.c里。

/*

 * Internal function to register an irqaction - typically used to

 * allocate special interrupts that are part of the architecture.

 */

int setup_irq(unsigned int irq, struct irqaction *new);

 

/*

 *    request_irq - allocate an interrupt line

*    This call allocates interrupt resources and enables the

 *    interrupt line and IRQ handling.

*/

int request_irq(unsigned int irq,

              irqreturn_t (*handler)(int, void *, struct pt_regs *),

              unsigned long irqflags, const char *devname, void *dev_id)

 

這兩個(gè)函數(shù)有什么樣的區(qū)別呢?

 

先看看setup_irq

Setup_irq通常用在系統(tǒng)時(shí)鐘(GP Timer)驅(qū)動(dòng)里,注冊(cè)系統(tǒng)時(shí)鐘驅(qū)動(dòng)的中斷處理函數(shù)。

下面舉個(gè)列子, s3c2410 timer驅(qū)動(dòng):

/* arch/arm/mach-s3c2410/time.c */

static struct irqaction s3c2410_timer_irq = {

       .name          = "S3C2410 Timer Tick",

       .flags            = IRQF_DISABLED | IRQF_TIMER,

       .handler       = s3c2410_timer_interrupt,

};

 

static void __init s3c2410_timer_init (void)

{

       s3c2410_timer_setup();

       setup_irq(IRQ_TIMER4, &s3c2410_timer_irq);

}

 

struct sys_timer s3c24xx_timer = {

       .init        = s3c2410_timer_init,

       .offset           = s3c2410_gettimeoffset,

       .resume        = s3c2410_timer_setup

};

 

struct sys_timer s3c24xx_timer = {

       .init        = s3c2410_timer_init,

       .offset           = s3c2410_gettimeoffset,

       .resume        = s3c2410_timer_setup

};

可以看到,setup_irq的使用流程很簡(jiǎn)單。首先定義s3c2410 timer驅(qū)動(dòng)的irqaction結(jié)構(gòu)體,該結(jié)構(gòu)體用于描述timer中斷的基本屬性包括中斷名、類別以及該中斷handler等。然后通過(guò)setup_irq函數(shù)將timerirqaction注冊(cè)進(jìn)內(nèi)核。其中,IRQ_TIMER4s3c2410 timer的中斷號(hào)。

 

 

再看看request_irq

request_irq源碼如下:

/* kernel/irq/manage.c */

int request_irq(unsigned int irq,

              irqreturn_t (*handler)(int, void *, struct pt_regs *),

              unsigned long irqflags, const char *devname, void *dev_id)

{

       struct irqaction *action;

       int retval;

 

#ifdef CONFIG_LOCKDEP

       /*

        * Lockdep wants atomic interrupt handlers:

        */

       irqflags |= SA_INTERRUPT;

#endif

       /*

        * Sanity-check: shared interrupts must pass in a real dev-ID,

        * otherwise we'll have trouble later trying to figure out

        * which interrupt is which (messes up the interrupt freeing

        * logic etc).

        */

       if ((irqflags & IRQF_SHARED) && !dev_id)   /* 使用共享中斷但沒(méi)有提供非NULLdev_id則返回錯(cuò)誤 */

              return -EINVAL;

       if (irq >= NR_IRQS)            /* 中斷號(hào)超出最大值 */

              return -EINVAL;

       if (irq_desc[irq].status & IRQ_NOREQUEST) /* 該中斷號(hào)已被使用并且未共享 */

              return -EINVAL;

       if (!handler)

              return -EINVAL;

 

       action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC);     /* 動(dòng)態(tài)創(chuàng)建一個(gè)irqaction */

       if (!action)

              return -ENOMEM;

/* 下面幾行是根據(jù)request_irq 傳進(jìn)來(lái)的參數(shù)對(duì)irqaction結(jié)構(gòu)體賦值 */

       action->handler = handler;  

       action->flags = irqflags;

       cpus_clear(action->mask);

       action->name = devname;

       action->next = NULL;

       action->dev_id = dev_id;

 

       select_smp_affinity(irq);

 

       retval = setup_irq(irq, action);      /* 調(diào)用setup_irq注冊(cè)該中斷的irqaction結(jié)構(gòu)體 */

       if (retval)

              kfree(action);

 

       return retval;

}

由上可以看出,request_irq的大致流程為先對(duì)申請(qǐng)的中斷線進(jìn)行安全檢測(cè),然后根據(jù)request_irq傳進(jìn)來(lái)的參數(shù),動(dòng)態(tài)創(chuàng)建該中斷對(duì)應(yīng)的irqaction結(jié)構(gòu)體,最后通過(guò)setup_irq函數(shù)將該irqaction注冊(cè)進(jìn)內(nèi)核適當(dāng)?shù)奈恢谩?/span>

 

這兩個(gè)函數(shù)的使用流程搞清楚了,那么兩者之間的聯(lián)系也就清楚了:

1) Request_irq的注冊(cè)過(guò)程包含setup_irq,最終是調(diào)用setup_irq。

2) Request_irqsetup_irq多一套錯(cuò)誤檢測(cè)機(jī)制,即kmalloc前面3if語(yǔ)句。

Setup_irq通常是直接注冊(cè)irqaction,并沒(méi)針對(duì)相應(yīng)中斷線進(jìn)行錯(cuò)誤檢測(cè),如該irq 線是否已經(jīng)被占用等。因此setup_irq通常只用在特定的中斷線上,如System timer。除系統(tǒng)時(shí)鐘驅(qū)動(dòng)外,大部份驅(qū)動(dòng)還是通過(guò)request_irq注冊(cè)中斷。

 

這里有個(gè)小問(wèn)題:

既然Request_irq實(shí)際上就是包含了setup_irq的注冊(cè)過(guò)程,那系統(tǒng)時(shí)鐘驅(qū)動(dòng)(GP Timer Driver)中斷可以用request_irq來(lái)注冊(cè)嗎?

 

做個(gè)小試驗(yàn), s3c2410 timer驅(qū)動(dòng)的setup_irq那行去掉,改為用request_irq注冊(cè)。

修改后代碼如下:

static void __init s3c2410_timer_init (void)

{

       s3c2410_timer_setup();

       //setup_irq(IRQ_TIMER4, &s3c2410_timer_irq);

       request_irq(IRQ_TIMER4, s3c2410_timer_interrupt,

        IRQF_DISABLED | IRQF_TIMER, "S3C2410 Timer Tick", NULL);

}

編譯運(yùn)行。

結(jié)果:內(nèi)核掛掉

 

為什么呢?很明顯,系統(tǒng)時(shí)鐘驅(qū)動(dòng)中斷不能用request_irq注冊(cè),大致搜了一下源碼也發(fā)現(xiàn),看到其他平臺(tái)相關(guān)的時(shí)鐘驅(qū)動(dòng)中斷部分都是用的setup_irq注冊(cè)的。

我們來(lái)分析一下原因。

看看request_irqsetup_irq 還有哪些細(xì)節(jié)不一樣?

 

 

仔細(xì)觀察后注意到request_irq內(nèi)有這么一行代碼:

action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC);

作用為動(dòng)態(tài)創(chuàng)建一個(gè)irqaction

 

Kmalloc實(shí)際上也是使用的slab機(jī)制進(jìn)行分配的。源碼如下:

/* include/linux/slab.h */

static inline void *kmalloc(size_t size, gfp_t flags)

{

       if (__builtin_constant_p(size)) {

              int i = 0;

#define CACHE(x) \

              if (size <= x) \

                     goto found; \

              else \

                     i++;

#include "kmalloc_sizes.h"

#undef CACHE

              {

                     extern void __you_cannot_kmalloc_that_much(void);

                     __you_cannot_kmalloc_that_much();

              }

found:

              return kmem_cache_alloc((flags & GFP_DMA) ?

                     malloc_sizes[i].cs_dmacachep :

                     malloc_sizes[i].cs_cachep, flags);

       }

       return __kmalloc(size, flags);

}

 

使用slab機(jī)制分配內(nèi)存必須先對(duì)slab進(jìn)行初始化,包括mem_initkmem_cache_init

看看kernel的初始化流程:

/* init/main.c */

asmlinkage void __init start_kernel(void)

{

       ……

       time_init();

       ……

       vfs_caches_init_early();

       cpuset_init_early();

       mem_init();  ?------ initializes the memory data structures

       kmem_cache_init(); ?---- set up the general caches

       ……

}

 

Time_init函數(shù)在mem_initkmem_cache_init之前被調(diào)用,而time_init會(huì)調(diào)用體系結(jié)構(gòu)相關(guān)部分系統(tǒng)時(shí)鐘驅(qū)動(dòng)的初始化函數(shù)。拿s3c2410的例子來(lái)說(shuō),time_init最終會(huì)調(diào)用s3c2410_timer_init函數(shù),進(jìn)行s3c2410時(shí)鐘驅(qū)動(dòng)的初始化和注冊(cè)中斷處理函數(shù)。

具體過(guò)程如下:

time_init函數(shù)定義在arch/arm/kernel/time.c內(nèi):

void __init time_init(void)

{

#ifndef CONFIG_GENERIC_TIME

       if (system_timer->offset == NULL)

              system_timer->offset = dummy_gettimeoffset;

#endif

       system_timer->init();  ?-這行實(shí)際執(zhí)行的就是s3c2410_timer_init

 

#ifdef CONFIG_NO_IDLE_HZ

       if (system_timer->dyn_tick)

              system_timer->dyn_tick->lock = SPIN_LOCK_UNLOCKED;

#endif

}

system_timersetup_arch(arch/arm/kernel/setup.c)內(nèi)通過(guò)map_desc機(jī)制被初始化為s3c24xx_timer. 如上面s3c2410時(shí)鐘驅(qū)動(dòng)代碼所示,s3c24xx_timerinit成員即指向s3c2410_timer_init函數(shù)。

 

現(xiàn)在我們搞清楚了,我們大概的估計(jì)是系統(tǒng)時(shí)鐘驅(qū)動(dòng)(GP Timer Driver)的中斷處理函數(shù)不能用request_irq注冊(cè)是因?yàn)?/span>request_irq內(nèi)會(huì)調(diào)用kmalloc動(dòng)態(tài)分配內(nèi)存創(chuàng)建timerirqaction結(jié)構(gòu)體。而kmalloc也是使用的slab內(nèi)存分配機(jī)制,使用kmalloc前必須先對(duì)kernelslab以及mem data structure進(jìn)行初始化。而這部分初始化工作是在系統(tǒng)時(shí)鐘驅(qū)動(dòng)初始化之后才進(jìn)行的,所以造成kmalloc失敗,從而造成系統(tǒng)時(shí)鐘驅(qū)動(dòng)的中斷未注冊(cè)成功,進(jìn)而內(nèi)核掛掉。

 









本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
內(nèi)核編程
深入分析request_irq的dev_id參數(shù)作用
嵌入式linux驅(qū)動(dòng)之中斷架構(gòu)
linux中斷處理之IRQ中斷
[原創(chuàng)]Linux arm 啟動(dòng) c語(yǔ)言部分詳解第一講(from Start kernel) - 安裝啟動(dòng) - 文檔專區(qū) - Linux論壇
linux mips啟動(dòng)分析 - MIPS技術(shù)及應(yīng)用社區(qū)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服