linux 在某个core上的中断 affinity c语言函数,Linux中断处理体系结构
各種的異常的C處理函數可以分為5類,他們分布在不同的文件中。
1、在arch/arm/kernel/trapsc.c中
未定義指令異常,總入口函數為do_undefinstr.
2、在arch/arm/mm/fault.c中
與內存訪問相關的異常的C處理函數,
3、在arch/arm/mm/irq.c中
中斷處理函數
4、在arch/arm/kernel/aclls.S中
swi異常的處理函數執政被組織成一個表格:swi指令集起碼的位[23:0]被用來作為索引。這樣,通過不同的”swi index”指令就可以調用不同的swi異常處理函數,它們被稱為系統調用,比如sys_open,sys_read,sys_write等。
5、沒有使用的異常。
中斷處理體系結構
Linux內核將所有的中斷統一編號,使用一個irq_desc結構數組來描述這些中斷:每個數組項對應一個中斷(也有可能是一組中斷,他們共用相同的中斷號),里面記錄了中斷的名稱,中斷狀態,中斷標記(比如中斷類型,是否共享中斷等),并提供了中斷的底層硬件訪問函數(清除,屏蔽,使能中斷),提供了這個中斷的處理函數入口,通過它可以調用用戶注冊的中斷處理函數。
struct irq_desc {
irq_flow_handler_t handle_irq; /當前中斷的處理函數入口/
struct irq_chip chip; /底層的硬件訪問*/
struct msi_desc *msi_desc;
void *handler_data;
void *chip_data;
struct irqaction action; / IRQ action list 用戶提供的中斷處理函數鏈表*/
unsigned int status; /* IRQ status IRQ狀態*/
unsigned int depth; /* nested irq disables */
unsigned int wake_depth; /* nested wake enables */
unsigned int irq_count; /* For detecting broken IRQs */
unsigned int irqs_unhandled;
spinlock_t lock;
#ifdef CONFIG_SMP
cpumask_t affinity;
unsigned int cpu;
#endif
#if defined(CONFIG_GENERIC_PENDING_IRQ) || defined(CONFIG_IRQBALANCE)
cpumask_t pending_mask;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *dir;
#endif
const char name; /中斷名稱*/
} ____cacheline_internodealigned_in_smp;
struct irq_chip {
const char *name;
unsigned int (startup)(unsigned int irq); /啟動中斷,如果不設置,缺省為”enable”*/
void (shutdown)(unsigned int irq); /關閉中斷,如果不設置,缺省為”disable”*/
void (enable)(unsigned int irq); /使能中斷,如果不設置,缺省為”unmask”*/
void (disable)(unsigned int irq); /禁止中斷,如果不設置,缺省為”mask”*/
void (ack)(unsigned int irq); / 相應中斷,通常是清除當前中斷使得可以接收下一個中斷*/
void (mask)(unsigned int irq); /屏蔽中斷源*/
void (mask_ack)(unsigned int irq); /屏蔽和相應中斷*/
void (unmask)(unsigned int irq); /開啟中斷源*/
void (*eoi)(unsigned int irq);
void (*end)(unsigned int irq);
void (*set_affinity)(unsigned int irq, cpumask_t dest);
int (*retrigger)(unsigned int irq);
int (*set_type)(unsigned int irq, unsigned int flow_type);
int (*set_wake)(unsigned int irq, unsigned int on);
/* Currently used only by UML, might disappear one day.*/
#ifdef CONFIG_IRQ_RELEASE_METHOD
void (*release)(unsigned int irq, void *dev_id);
#endif
/*
* For compatibility, ->typename is copied into ->name.
* Will disappear.
*/
const char *typename;
};
struct irqaction {
irq_handler_t handler; /用戶注冊的中斷處理函數/
unsigned long flags; /中斷標志,比如是否共享中斷,電平觸發還是邊沿觸發等/
cpumask_t mask; /用于SMP(對稱多處理器系統)/
const char name; /用戶注冊的中斷名字,”cat /proc/interrupts”時可以看到*/
void dev_id; /用戶傳給上面的handler的參數,還可以用來區分共享中斷*/
struct irqaction *next;
int irq; /中斷號/
struct proc_dir_entry *dir;
};
中斷處理流程如下:
1、發生中斷時,CPU執行異常向量vector_irq的代碼。
2、在vector_irq里面,最終會調用中斷處理的總入口函數asm_do_IRQ.
3、asm_do_IRQ根據中斷號調用irq_desc數組項中的handle_irq.
4、handle_irq會使用chip成員中的函數來設置硬件,比如清除中斷,禁止中斷,重新使能中斷等。
5、handle_irq逐個調用用戶在action鏈表中注冊的處理函數。
可見,中斷體系結構的初始化就是構造這些數據結構,比如irq_desc數組項中的handle_irq,chip等成員;用戶注冊中斷時就是構造action鏈表;用戶卸載中斷就是從action鏈表中去除不需要的項。
用戶(即驅動程序)通過request_irq函數向內核注冊中斷處理函數,request_irq函數根據中斷號找到irq_desc數組項,然后在它的action鏈表中添加一個表項。
int request_irq(unsigned int irq, irq_handler_t handler,
unsigned long irqflags, const char *devname, void *dev_id)
{
…
action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
…
action->handler = handler;
action->flags = irqflags;
cpus_clear(action->mask);
action->name = devname;
action->next = NULL;
action->dev_id = dev_id;
…
retval = setup_irq(irq, action);
…
}
requset_irq函數首先使用這4個參數構造一個irqaction結構,然后調用setup_irq函數將它鏈入鏈表中;
setup_irq函數完成了3個功能:
1、將新建的irqaction結構鏈入irq_desc[irq]結構的action鏈表中。如果action鏈表為空,則直接鏈入。如果先判斷新建的irqaction結構和鏈表中的irqaction結構所表示的中斷類型是否一致:即是否都聲明為“可共享的”,是否都是用相同的觸發方式(電平,邊沿,極性),如果一致,則將新建的irqaction結構鏈入。
2、設置irq_desc[irq]結構中chip成員的還沒設置的指針,讓它們只想一些默認函數。
3、設置中斷的觸發方式。
4、啟動中斷。
asm_do_IRQ是中斷的C語言總入口函數;
中斷是一種很稀缺的資源,當不再使用一個設備時,應該釋放它占據的中斷。這通過free_irq函數來實現;
void free_irq(unsigned int irq, void *dev_id)
總結
以上是生活随笔為你收集整理的linux 在某个core上的中断 affinity c语言函数,Linux中断处理体系结构的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux 函数 缩小文件,linux
- 下一篇: linux服务器ftp上传文件为空,Li