導航:首頁 > 編程系統 > linuxirqflagsh

linuxirqflagsh

發布時間:2023-02-22 03:04:45

linux驅動中斷,程序運行幾個小時後系統崩潰

中斷與定時器:
中斷的概念:指CPU在執行過程中,出現某些突發事件急待處理,CPU暫停執行當前程序,轉去處理突發事件
,處理完後CPU又返回原程序被中斷的位置繼續執行
中斷的分類:內部中斷和外部中斷
內部中斷:中斷源來自CPU內部(軟體中斷指令、溢出、觸發錯誤等)
外部中斷:中斷源來自CPU外部,由外設提出請求

屏蔽中斷和不可屏蔽中斷:
可屏蔽中斷:可以通過屏蔽字被屏蔽,屏蔽後,該中斷不再得到響應
不可平布中斷:不能被屏蔽

向量中斷和非向量中斷:
向量中斷:CPU通常為不同的中斷分配不同的中斷號,當檢測到某中斷號的中斷到來後,就自動跳轉到與該中斷號對應的地址執行
非向量中斷:多個中斷共享一個入口地址。進入該入口地址後再通過軟體判斷中斷標志來識別具體哪個是中斷
也就是說向量中斷由軟體提供中斷服務程序入口地址,非向量中斷由軟體提供中斷入口地址

/*典型的非向量中斷首先會判斷中斷源,然後調用不同中斷源的中斷處理程序*/
irq_handler()
{
...
int int_src = read_int_status();/*讀硬體的中斷相關寄存器*/
switch(int_src){//判斷中斷標志
case DEV_A:
dev_a_handler();
break;
case DEV_B:
dev_b_handler();
break;
...
default:
break;
}
...
}

定時器中斷原理:
定時器在硬體上也以來中斷,PIT(可編程間隔定時器)接收一個時鍾輸入,
當時鍾脈沖到來時,將目前計數值增1並與已經設置的計數值比較,若相等,證明計數周期滿,產生定時器中斷,並
復位計數值。

如下圖所示:

Linux中斷處理程序架構:
Linux將中斷分為:頂半部(top half)和底半部(bottom half)
頂板部:完成盡可能少的比較緊急的功能,它往往只是簡單的讀取寄存器中的中斷狀態並清除中斷標志後就進行
「登記中斷」(也就是將底半部處理程序掛在到設備的底半部執行隊列中)的工作
特點:響應速度快

底半部:中斷處理的大部分工作都在底半部,它幾乎做了中斷處理程序的所有事情。
特點:處理相對來說不是非常緊急的事件

小知識:Linux中查看/proc/interrupts文件可以獲得系統中斷的統計信息。

如下圖所示:

第一列是中斷號 第二列是向CPU產生該中斷的次數

介紹完相關基礎概念後,讓我們一起來探討一下Linux中斷編程

Linux中斷編程:
1.申請和釋放中斷
申請中斷:
int request_irq(unsigned int irq,irq_handler_t handler,
unsigned long irqflags,const char *devname,void *dev_id)
參數介紹:irq是要申請的硬體中斷號
handler是向系統登記的中斷處理程序(頂半部),是一個回調函數,中斷發生時,系統調用它,將
dev_id參數傳遞給它
irqflags:是中斷處理的屬性,可以指定中斷的觸發方式和處理方式:
觸發方式:IRQF_TRIGGER_RISING、IRQF_TRIGGER_FALLING、IRQF_TRIGGER_HIGH、IRQF_TRIGGER_LOW
處理方式:IRQF_DISABLE表明中斷處理程序是快速處理程序,快速處理程序被調用時屏蔽所有中斷
IRQF_SHARED表示多個設備共享中斷,dev_id在中斷共享時會用到,一般設置為NULL

返回值:為0表示成功,返回-EINVAL表示中斷號無效,返回-EBUSY表示中斷已經被佔用,且不能共享
頂半部的handler的類型irq_handler_t定義為
typedef irqreturn_t (*irq_handler_t)(int,void*);
typedef int irqreturn_t;

2.釋放IRQ
有請求當然就有釋放了
void free_irq(unsigned int irq,void *dev_id);
參數定義與request_irq類似

3.使能和屏蔽中斷
void disable_irq(int irq);//等待目前中斷處理完成(最好別在頂板部使用,你懂得)
void disable_irq_nosync(int irq);//立即返回
void enable_irq(int irq);//

4.屏蔽本CPU內所有中斷:
#define local_irq_save(flags)...//禁止中斷並保存狀態
void local_irq_disable(void);//禁止中斷,不保存狀態

下面來分別介紹一下頂半部和底半部的實現機制

底半部機制:
簡介:底半部機制主要有tasklet、工作隊列和軟中斷
1.底半部是想方法之一tasklet
(1)我們需要定義tasklet機器處理器並將兩者關聯
例如:
void my_tasklet_func(unsigned long);/*定義一個處理函數*/
DECLARE_TASKLET(my_tasklet,my_tasklet_func,data);
/*上述代碼定義了名為my_tasklet的tasklet並將其餘
my_tasklet_func()函數綁定,傳入的參數為data*/
(2)調度
tasklet_schele(&my_tasklet);
//使用此函數就能在是當的時候進行調度運行

tasklet使用模板:
/*定義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)
{
...
tasklet_schele(&xxx_tasklet);//調度地板部
...
}

/*設備驅動模塊載入函數*/
int __init xxx_init(void)
{
...
/*申請中斷*/
result = request_irq(xxx_irq,xxx_interrupt,
IRQF_DISABLED,"xxx",NULL);
...

return IRQ_HANDLED;
}

/*設備驅動模塊卸載函數*/
void __exit xxx_exit(void)
{
...
/*釋放中斷*/
free_irq(xxx_irq,xxx_interrupt);
...
}

2.底半部實現方法之二---工作隊列
使用方法和tasklet類似
相關操作:
struct work_struct my_wq;/*定義一個工作隊列*/
void my_wq_func(unsigned long);/*定義一個處理函數*/
通過INIT_WORK()可以初始化這個工作隊列並將工作隊列與處理函數綁定
INIT_WORK(&my_wq,(void (*)(void *))my_wq_func,NULL);
/*初始化工作隊列並將其與處理函數綁定*/
schele_work(&my_wq);/*調度工作隊列執行*/

/*工作隊列使用模板*/

/*定義工作隊列和關聯函數*/
struct work_struct(unsigned long);
void xxx_do_work(unsigned long);

/*中斷處理底半部*/
void xxx_do_work(unsigned long)
{
...
}

/*中斷處理頂半部*/
/*中斷處理頂半部*/
irqreturn_t xxx_interrupt(int irq,void *dev_id)
{
...
schele_work(&my_wq);//調度底半部
...
return IRQ_HANDLED;
}

/*設備驅動模塊載入函數*/
int xxx_init(void)
{
...
/*申請中斷*/
result = request_irq(xxx_irq,xxx_interrupt,
IRQF_DISABLED,"xxx",NULL);
...
/*初始化工作隊列*/
INIT_WORK(&my_wq,(void (*)(void *))xxx_do_work,NULL);
}

/*設備驅動模塊卸載函數*/
void xxx_exit(void)
{
...
/*釋放中斷*/
free_irq(xxx_irq,xxx_interrupt);
...
}

Ⅱ 幫幫我,linux2.6以後怎麼從struct sk

1.調度數據成員(1)volatilelongstates;表示進程的當前狀態:?TASK_RUNNING:正在運行或在就緒隊列run-queue中准備運行的進程,實際參與進程調度。?TASK_INTERRUPTIBLE:處於等待隊列中的進程,待資源有效時喚醒,也可由其它進程通過信號(signal)或定時中斷喚醒後進入就緒隊列run-queue。?TASK_UNINTERRUPTIBLE:處於等待隊列中的進程,待資源有效時喚醒,不可由其它進程通過信號(signal)或定時中斷喚醒。?TASK_ZOMBIE:表示進程結束但尚未消亡的一種狀態(僵死狀態)。此時,進程已經結束運行且釋放大部分資源,但尚未釋放進程式控制制塊。?TASK_STOPPED:進程被暫停,通過其它進程的信號才能喚醒。導致這種狀態的原因有二,或者是對收到SIGSTOP、SIGSTP、SIGTTIN或SIGTTOU信號的反應,或者是受其它進程的ptrace系統調用的控制而暫時將CPU交給控制進程。?TASK_SWAPPING:進程頁面被交換出內存的進程。(2)unsignedlongflags;進程標志:?PF_ALIGNWARN列印「對齊」警告信息。?PF_PTRACED被ptrace系統調用監控。?PF_TRACESYS正在跟蹤。?PF_FORKNOEXEC進程剛創建,但還沒執行。?PF_SUPERPRIV超級用戶特權。?PF_DUMPCOREmpedcore。?PF_SIGNALED進程被信號(signal)殺出。?PF_STARTING進程正被創建。?PF_EXITING進程開始關閉。?PF_USEDFPU該進程使用FPU(SMPonly)。?PF_DTRACEdelayedtrace(usedonm68k)。(3)longpriority;進程優先順序。Priority的值給出進程每次獲取CPU後可使用的時間(按jiffies計)。優先順序可通過系統調用sys_setpriorty改變(在kernel/sys.c中)。(4)unsignedlongrt_priority;rt_priority給出實時進程的優先順序,rt_priority+1000給出進程每次獲取CPU後可使用的時間(同樣按jiffies計)。實時進程的優先順序可通過系統調用sys_sched_setscheler()改變(見kernel/sched.c)。(5)longcounter;在輪轉法調度時表示進程當前還可運行多久。在進程開始運行是被賦為priority的值,以後每隔一個tick(時鍾中斷)遞減1,減到0時引起新一輪調度。重新調度將從run_queue隊列選出counter值最大的就緒進程並給予CPU使用權,因此counter起到了進程的動態優先順序的作用(priority則是靜態優先順序)。(6)unsignedlongpolicy;該進程的進程調度策略,可以通過系統調用sys_sched_setscheler()更改(見kernel/sched.c)。調度策略有:?SCHED_OTHER0非實時進程,基於優先權的輪轉法(roundrobin)。?SCHED_FIFO1實時進程,用先進先出演算法。?SCHED_RR2實時進程,用基於優先權的輪轉法。2.信號處理(1)unsignedlongsignal;進程接收到的信號。每位表示一種信號,共32種。置位有效。(2)unsignedlongblocked;進程所能接受信號的位掩碼。置位表示屏蔽,復位表示不屏蔽。(3)structsignal_struct*sig;因為signal和blocked都是32位的變數,Linux最多隻能接受32種信號。對每種信號,各進程可以由PCB的sig屬性選擇使用自定義的處理函數,或是系統的預設處理函數。指派各種信息處理函數的結構定義在include/linux/sched.h中。對信號的檢查安排在系統調用結束後,以及「慢速型」中斷服務程序結束後(IRQ#_interrupt(),參見9。5節「啟動內核」)。3.進程隊列指針(1)structtask_struct*next_task,*prev_task;所有進程(以PCB的形式)組成一個雙向鏈表。next_task和就是鏈表的前後指針。鏈表的頭和尾都是init_task(即0號進程)。(2)structtask_struct*next_run,*prev_run;由正在運行或是可以運行的,其進程狀態均為TASK_RUNNING的進程所組成的一個雙向循環鏈表,即run_queue就緒隊列。該鏈表的前後向指針用next_run和prev_run,鏈表的頭和尾都是init_task(即0號進程)。(3)structtask_struct*p_opptr,*p_pptr;和structtask_struct*p_cptr,*p_ysptr,*p_osptr;以上分別是指向原始父進程(originalparent)、父進程(parent)、子進程(youngestchild)及新老兄弟進程(youngersibling,oldersibling)的指針。4.進程標識(1)unsignedshortuid,gid;uid和gid是運行進程的用戶標識和用戶組標識。(2)intgroups[NGROUPS];與多數現代UNIX操作系統一樣,Linux允許進程同時擁有一組用戶組號。在進程訪問文件時,這些組號可用於合法性檢查。(3)unsignedshorteuid,egid;euid和egid又稱為有效的uid和gid。出於系統安全的許可權的考慮,運行程序時要檢查euid和egid的合法性。通常,uid等於euid,gid等於egid。有時候,系統會賦予一般用戶暫時擁有root的uid和gid(作為用戶進程的euid和egid),以便於進行運作。(4)unsignedshortfsuid,fsgid;fsuid和fsgid稱為文件系統的uid和gid,用於文件系統操作時的合法性檢查,是Linux獨特的標識類型。它們一般分別和euid和egid一致,但在NFS文件系統中NFS伺服器需要作為一個特殊的進程訪問文件,這時只修改客戶進程的fsuid和fsgid。(5)unsignedshortsuid,sgid;suid和sgid是根據POSIX標准引入的,在系統調用改變uid和gid時,用於保留真正的uid和gid。(6)intpid,pgrp,session;進程標識號、進程的組織號及session標識號,相關系統調用(見程序kernel/sys.c)有sys_setpgid、sys_getpgid、sys_setpgrp、sys_getpgrp、sys_getsid及sys_setsid幾種。(7)intleader;是否是session的主管,布爾量。5.時間數據成員(1)unsignedlongtimeout;用於軟體定時,指出進程間隔多久被重新喚醒。採用tick為單位。(2)unsignedlongit_real_value,it_real_iner;用於itimer(intervaltimer)軟體定時。採用jiffies為單位,每個tick使it_real_value減到0時向進程發信號SIGALRM,並重新置初值。初值由it_real_incr保存。具體代碼見kernel/itimer.c中的函數it_real_fn()。(3)structtimer_listreal_timer;一種定時器結構(Linux共有兩種定時器結構,另一種稱作old_timer)。數據結構的定義在include/linux/timer.h中,相關操作函數見kernel/sched.c中add_timer()和del_timer()等。(4)unsignedlongit_virt_value,it_virt_incr;關於進程用戶態執行時間的itimer軟體定時。採用jiffies為單位。進程在用戶態運行時,每個tick使it_virt_value減1,減到0時向進程發信號SIGVTALRM,並重新置初值。初值由it_virt_incr保存。具體代碼見kernel/sched.c中的函數do_it_virt()。(5)unsignedlongit_prof_value,it_prof_incr;同樣是itimer軟體定時。採用jiffies為單位。不管進程在用戶態或內核態運行,每個tick使it_prof_value減1,減到0時向進程發信號SIGPROF,並重新置初值。初值由it_prof_incr保存。具體代碼見kernel/sched.c中的函數do_it_prof。(6)longutime,stime,cutime,cstime,start_time;以上分別為進程在用戶態的運行時間、進程在內核態的運行時間、所有層次子進程在用戶態的運行時間總和、所有層次子進程在核心態的運行時間總和,以及創建該進程的時間。6.信號量數據成員(1)structsem_undo*semundo;進程每操作一次信號量,都生成一個對此次操作的undo操作,它由sem_undo結構描述。這些屬於同一進程的undo操作組成的鏈表就由semundo屬性指示。當進程異常終止時,系統會調用undo操作。sem_undo的成員semadj指向一個數據數組,表示各次undo的量。結構定義在include/linux/sem.h。(2)structsem_queue*semsleeping;每一信號量集合對應一個sem_queue等待隊列(見include/linux/sem.h)。進程因操作該信號量集合而阻塞時,它被掛到semsleeping指示的關於該信號量集合的sem_queue隊列。反過來,semsleeping。sleeper指向該進程的PCB。7.進程上下文環境(1)structdesc_struct*ldt;進程關於CPU段式存儲管理的局部描述符表的指針,用於模擬WINEWindows的程序。其他情況下取值NULL,進程的ldt就是arch/i386/traps.c定義的default_ldt。(2)structthread_structtss;任務狀態段,其內容與INTELCPU的TSS對應,如各種通用寄存器.CPU調度時,當前運行進程的TSS保存到PCB的tss,新選中進程的tss內容復制到CPU的TSS。結構定義在include/linux/tasks.h中。(3)unsignedlongsaved_kernel_stack;為MS-DOS的模擬程序(或叫系統調用vm86)保存的堆棧指針。(4)unsignedlongkernel_stack_page;在內核態運行時,每個進程都有一個內核堆棧,其基地址就保存在kernel_stack_page中。8.文件系統數據成員(1)structfs_struct*fs;fs保存了進程本身與VFS的關系消息,其中root指向根目錄結點,pwd指向當前目錄結點,umask給出新建文件的訪問模式(可由系統調用umask更改),count是Linux保留的屬性,如下頁圖所示。結構定義在include/linux/sched.h中。(2)structfiles_struct*files;files包含了進程當前所打開的文件(structfile*fd[NR_OPEN])。在Linux中,一個進程最多隻能同時打開NR_OPEN個文件。而且,前三項分別預先設置為標准輸入、標准輸出和出錯消息輸出文件。(3)intlink_count;文件鏈(link)的數目。9.內存數據成員(1)structmm_struct*mm;在linux中,採用按需分頁的策略解決進程的內存需求。task_struct的數據成員mm指向關於存儲管理的mm_struct結構。其中包含了一個虛存隊列mmap,指向由若干vm_area_struct描述的虛存塊。同時,為了加快訪問速度,mm中的mmap_avl維護了一個AVL樹。在樹中,所有的vm_area_struct虛存塊均由左指針指向相鄰的低虛存塊,右指針指向相鄰的高虛存塊。結構定義在include/linux/sched.h中。10.頁面管理(1)intswappable:1;進程佔用的內存頁面是否可換出。swappable為1表示可換出。對該標志的復位和置位均在do_fork()函數中執行(見kerenl/fork.c)。(2)unsignedlongswap_address;虛存地址比swap_address低的進程頁面,以前已經換出或已換出過,進程下一次可換出的頁面自swap_address開始。參見swap_out_process()和swap_out_pmd()(見mm/vmscan.c)。(3)unsignedlongmin_flt,maj_flt;該進程累計的minor缺頁次數和major缺頁次數。maj_flt基本與min_flt相同,但計數的范圍比後者廣(參見fs/buffer.c和mm/page_alloc.c)。min_flt只在do_no_page()、do_wp_page()里(見mm/memory.c)計數新增的可以寫操作的頁面。(4)unsignedlongnswap;該進程累計換出的頁面數。(5)unsignedlongcmin_flt,cmaj_flt,cnswap;以本進程作為祖先的所有層次子進程的累計換入頁面、換出頁面計數。(6)unsignedlongold_maj_flt,dec_flt;(7)unsignedlongswap_cnt;下一次信號最多可換出的頁數。11.支持對稱多處理器方式(SMP)時的數據成員(1)intprocessor;進程正在使用的CPU。(2)intlast_processor;進程最後一次使用的CPU。(3)intlock_depth;上下文切換時系統內核鎖的深度。12.其它數據成員(1)unsignedshortused_math;是否使用FPU。(2)charcomm[16];進程正在運行的可執行文件的文件名。(3)structrlimitrlim[RLIM_NLIMITS];結構rlimit用於資源管理,定義在linux/include/linux/resource.h中,成員共有兩項:rlim_cur是資源的當前最大數目;rlim_max是資源可有的最大數目。在i386環境中,受控資源共有RLIM_NLIMITS項,即10項,定義在linux/include/asm/resource.h中,見下表:(4)interrno;最後一次出錯的系統調用的錯誤號,0表示無錯誤。系統調用返回時,全程量也擁有該錯誤號。(5)longdebugreg[8];保存INTELCPU調試寄存器的值,在ptrace系統調用中使用。(6)structexec_domain*exec_domain;Linux可以運行由80386平台其它UNIX操作系統生成的符合iBCS2標準的程序。關於此類程序與Linux程序差異的消息就由exec_domain結構保存。(7)unsignedlongpersonality;Linux可以運行由80386平台其它UNIX操作系統生成的符合iBCS2標準的程序。Personality進一步描述進程執行的程序屬於何種UNIX平台的「個性」信息。通常有PER_Linux、PER_Linux_32BIT、PER_Linux_EM86、PER_SVR3、PER_SCOSVR3、PER_WYSEV386、PER_ISCR4、PER_BSD、PER_XENIX和PER_MASK等,參見include/linux/personality.h。(8)structlinux_binfmt*binfmt;指向進程所屬的全局執行文件格式結構,共有a。out、script、elf和java等四種。結構定義在include/linux/binfmts.h中(core_mp、load_shlib(fd)、load_binary、use_count)。(9)intexit_code,exit_signal;引起進程退出的返回代碼exit_code,引起錯誤的信號名exit_signal。(10)intmpable:1;布爾量,表示出錯時是否可以進行memorymp。(11)intdid_exec:1;按POSIX要求設計的布爾量,區分進程是正在執行老程序代碼,還是在執行execve裝入的新代碼。(12)inttty_old_pgrp;進程顯示終端所在的組標識。(13)structtty_struct*tty;指向進程所在的顯示終端的信息。如果進程不需要顯示終端,如0號進程,則該指針為空。結構定義在include/linux/tty.h中。(14)structwait_queue*wait_chldexit;在進程結束時,或發出系統調用wait4後,為了等待子進程的結束,而將自己(父進程)睡眠在該隊列上。結構定義在include/linux/wait.h中。13.進程隊列的全局變數(1)current;當前正在運行的進程的指針,在SMP中則指向CPU組中正被調度的CPU的當前進程:#definecurrent(0+current_set[smp_processor_id()])/*sched.h*/structtask_struct*current_set[NR_CPUS];(2)structtask_structinit_task;即0號進程的PCB,是進程的「根」,始終保持初值INIT_TASK。(3)structtask_struct*task[NR_TASKS];進程隊列數組,規定系統可同時運行的最大進程數(見kernel/sched.c)。NR_TASKS定義在include/linux/tasks.h中,值為512。每個進程佔一個數組元素(元素的下標不一定就是進程的pid),task[0]必須指向init_task(0號進程)。可以通過task[]數組遍歷所有進程的PCB。但Linux也提供一個宏定義for_each_task()(見include/linux/sched.h),它通過next_task遍歷所有進程的PCB:#definefor_each_task(p)\for(p=&init_task;(p=p->next_task)!=&init_task;)(4)unsignedlongvolatilejiffies;Linux的基準時間(見kernal/sched.c)。系統初始化時清0,以後每隔10ms由時鍾中斷服務程序do_timer()增1。(5)intneed_resched;重新調度標志位(見kernal/sched.c)。當需要Linux調度時置位。在系統調用返回前(或者其它情形下),判斷該標志是否置位。置位的話,馬上調用schele進行CPU調度。(6)unsignedlongintr_count;記錄中斷服務程序的嵌套層數(見kernal/softirq.c)。正常運行時,intr_count為0。當處理硬體中斷、執行任務隊列中的任務或者執行bottomhalf隊列中的任務時,intr_count非0。這時,內核禁止某些操作,例如不允許重新調度。

Ⅲ Linux內核中斷之中斷申請介面

本文基於 RockPI 4A 單板Linux4.4內核介紹中斷申請的常用介面函數。

1、文件

2、定義

說明:

1)、 irq :要申請的中斷號,可通過 platform_get_irq() 獲取,見「Linux內核中斷之獲取中斷號」。

2)、 handler :中斷處理函數,發生中斷時,先處理中斷處理函數,然後返回 IRQ_WAKE_THREAD 喚醒中斷處理線程。中斷處理函數盡可能簡單。

中斷處理函數定義: typedef irqreturn_t (*irq_handler_t)(int, void *);

中斷返回值如下:

3)、 thread_fn :中斷處理線程,該參數可為NULL。類似於中斷處理函數的下半部分。

4)、 irqflags :中斷類型標志。

定義文件: include/linux/interrupt.h ,內容如下:

5)、 devname :中斷名稱,可使用 cat /proc/interrupts 命令查看。

6)、 dev_id :設備ID,該值唯一。

在使用共享中斷時(即設置 IRQF_SHARED ),必須傳入 dev_id ,在中斷處理和釋放函數中都會使用該參數。

註:

1、 request_threaded_irq() 函數可替代 request_irq 加 tasklet 或 workqueue 的方式。

2、對應的中斷釋放函數為: void free_irq(unsigned int, void *) ,需要和中斷申請函數成對出現。

1、文件

2、定義

說明:

1)、 __must_check :指調用函數一定要處理函數的返回值,否則編譯器會給出警告。

2)、 request_irq() 函數本質上是中斷處理線程 thread_fn 為空的 request_threaded_irq() 函數。

對應的中斷釋放函數為: void free_irq(unsigned int, void *) ,需要和中斷申請函數成對出現。

1、文件

2、定義

說明

devm_request_threaded_irq() 本質上還是使用 request_threaded_irq() 函數實現中斷申請。

兩者區別:

1)多了一個 dev 參數;

2)在設備驅動卸載時,中斷會自動釋放;

3)如果想單獨釋放中斷,可使用 void devm_free_irq(struct device *dev, unsigned int irq, void *dev_id) 函數。

1、文件

2、定義

devm_request_irq() 函數本質上是中斷處理線程 thread_fn 為空的 devm_request_threaded_irq() 函數。

1、獲取中斷號

2、申請中斷

3、中斷處理函數

4、中斷處理線程

5、查看中斷

Ⅳ 關於linux中request_irq()

不對

Ⅳ Linux如何及時響應外部中斷

FPGA每隔100us給運行linux的ARM一個中斷,要求在20us內響應中斷,並讀走2000*16bit的數據。
目前主要的問題是,當系統同時發生多個中斷時,會嚴重影響linux對FPGA中斷的響應時間。如何解決?

1、首先想到了ARM的FIQ,它可以打斷IRQ中斷服務程序,保證對外部FIQ的及時響應。但是發現linux只實現了IRQ,沒有顯示FIQ。
linux是從devicetree讀取中斷號,加入中斷向量表的。

interrupts = <0x0 0x32 0x0>;中的第一個欄位0表示非共享中斷,非零表示共享中斷,SDK產生的dts統一為0,此時第二欄位的值比XPS中的小32;如果第一欄位非零,則第二欄位比XPS小16.
最後欄位表示中斷的觸發方式。
IRQ_TYPE_EDGE_RISING =0x00000001,
IRQ_TYPE_EDGE_FALLING =0x00000002,
IRQ_TYPE_LEVEL_HIGH =0x00000004,
IRQ_TYPE_LEVEL_LOW =0x00000008,
很明顯,devicetree根本沒有提供通知linux有FIQ的渠道。
2、再來看linux的IRQ
linux的中斷分為上半部和下半部,上半部運行在IRQ模式,會屏蔽所有中斷,下半部運行在SVC模式,會重新打開中斷。
也就是說,當一個中斷的上半部正在運行時(不能再次響應中斷),FPGA的中斷是不能被linux響應的;
反過來,當FPGA中斷的上半部正在運行時(不能再次響應中斷),其他的中斷也不能被linux響應;
unsigned long flags;
...
local_irq_save(flags);
....

local_irq_restore(flags);

3.
ARM有七種模式,我們這里只討論SVC、IRQ和FIQ模式。
我們可以假設ARM核心有兩根中斷引腳(實際上是看不見的),一根叫 irq pin, 一根叫fiq pin.
在ARM的cpsr中,有一個I位和一個F位,分別用來禁止IRQ和FIQ的。
先不說中斷控制器,只說ARM核心。正常情況下,ARM核都只是機械地隨著pc的指示去做事情,當CPSR中的I和F位為1的時候,IRQ和FIQ全部處於禁止狀態。無論你在irq
pin和fiq pin上面發什麼樣的中斷信號,ARM是不會理你的,你根本不能打斷他,因為他耳聾了,眼也瞎了。
在I位和F位為0的時候,當irq
pin上有中斷信號過來的時候,就會打斷arm的當前工作,並且切換到IRQ模式下,並且跳到相應的異常向量表(vector)位置去執行代碼。這個過程是自動的,但是返回到被中斷打斷的地方就得您親自動手了。當你跳到異常向量表,處於IRQ的模式的時候,這個時候如果irq
pin上面又來中斷信號了,這個時候ARM不會理你的,irq
pin就跟秘書一樣,ARM核心就像老闆,老闆本來在做事,結果來了一個客戶,秘書打斷它,讓客戶進去了。而這個時候再來一個客戶,要麼秘書不斷去敲門問,要麼客戶走人。老闆第一個客戶沒有會見完,是不會理你的。
但是有一種情況例外,當ARM處在IRQ模式,這個時候fiq pin來了一個中斷信號,fiq
pin是什麼?是快速中斷呀,比如是公安局的來查刑事案件,那才不管你老闆是不是在會見客戶,直接打斷,進入到fiq模式下,並且跳到相應的fiq的異常向量表處去執行代碼。那如果當ARM處理FIQ模式,fiq
pin又來中斷信號,又就是又一批公安來了,那沒戲,都是執法人員,你打不斷我。那如果這個時候irq
pin來了呢?來了也不理呀,正在辦案,還敢來妨礙公務。
所以得出一個結論: IRQ模式只能被FIQ模式打斷,FIQ模式下誰也打不斷。
在打不斷的情況下,irq pin 或 fiq pin隨便你怎麼發中斷信號,都是白發。
所以除了fiq能打斷irq以外,根本沒有所謂中斷嵌套的情況。
Linux不用FIQ,只用到了IRQ。但是我們有時候一個中斷需要處理很長時間,那我們就需要佔用IRQ模式那麼長的時間嗎?沒有,linux在IRQ模式下只是簡單的記錄是什麼中斷,馬上就切換回了SVC模式,換句話說,Linux的中斷處理都是在SVC模式下處理的。
只不過SVC模式下的ISR上半部關閉了當前中斷線,下半部才重新打開

Ⅵ Linux下通過哪個命令怎麼查看中斷

/proc/interrupts

Ⅶ linux 報錯沒有指明目標並且找不到 makefile

1 中斷共享

Linux系統運行幾個設備共享同一個中斷。需要共享的話,在申請的時候指明共享方式。系統提供的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);

如果共享中斷,irqflags設置SA_SHIRQ屬性,這樣就允許別的設備申請同一個中斷。需要注意所有用到這個中斷的設備在調用request_irq()都必須設置這個屬性。系統在回調每個中斷處理程序時,可以用dev_id這個參數找到相應的設備。系統在回調每個中斷處理程序時,可以用dev_id這個參數找到相應的設備。一般dev_id就設為device結構本身。系統處理共享中斷是用各自的dev_id參數依次調用每一個中斷處理程序。
2 硬體發送忙時的處理
主CPU的處理能力一般比網路發送要快,所以經常會遇到系統有數據要發,但上一包數據網路設備還沒發送完。因為在Linux里網路設備驅動程序一般不做數據緩存,不能發送的數據都是通知系統發送不成功,所以必須要有一個機制在硬體不忙時及時通知系統接著發送下面的數據。

一般對發送忙的處理在前面設備的發送方法(hard_start_xmit)里已經描述過,即如果發送忙,置tbusy為1。處理完發送數據後,在發送結束中斷里清tbusy,同時用mark_bh()調用通知系統繼續發送。

但在具體實現我的驅動程序時發現,這樣的處理系統好象並不能及時地知道硬體已經空閑了,即在mark_bh()以後,系統要等一段時間才會接著發送。造成發送效率很低。2M線路只有10%不到的使用率。內核版本為2.0.35。

我最後的實現是不把tbusy置1,讓系統始終認為硬體空閑,但是報告發送不成功。系統會一直嘗試重發。這樣處理就運行正常了。但是遍循內核源碼中的網路驅動程序,似乎沒有這樣處理的。不知道症結在哪裡。

3 流量控制(flow control)
網路數據的發送和接收都需要流量控制。這些控制是在系統里實現的,不需要驅動程序做工作。每個設備數據結構里都有一個參數dev->tx_queue_len,這個參數標明發送時最多緩存的數據包。在Linux系統里乙太網設備(10/100Mbps)標明發送時最多緩存的數據包。在Linux系統里乙太網設備(10/100Mbps)tx_queue_len一般設置為100,串列線路(非同步串口)為10。實際上如果看源碼可以知道,設置了dev->tx_queue_len並不是為緩存這些數據申請了空間。這個參數只是在收到協議層的數據包時判斷發送隊列里的數據是不是到了tx_queue_len的限度,以決定這一包數據加不加進發送隊列。發送時另一個方面的流控是更高層協議的發送窗口(TCP協議里就有發送窗口)。達到了窗口大小,高層協議就不會再發送數據。

接收流控也分兩個層次。netif_rx()緩存的數據包有限制。另外高層協議也會有一個最大的等待處理的數據量。

發送和接收流控處理在net/core/dev.c的do_dev_queue_xmit()和netif_rx()中。

4 調試
很多Linux的驅動程序都是編譯進內核的,形成一個大的內核文件。但對調試來說,這是相當麻煩的。調試驅動程序可以用mole方式載入。支持模塊方式的驅動程序必須提供兩個函數:int init_mole(void)和void cleanup_mole(void)。init_mole()在載入此模塊時調用,在這個函數里可以register_netdev()注冊設備。init_mole()返回0表示成功,返回負表示失敗。cleanup_mole()在驅動程序被卸載時調用,清除佔用的資源,調用unregister_netdev()。

模塊可以動態地載入、卸載。在2.0.xx版本里,還有kerneld自動載入模塊,但是2.2.xx中已經取消了kerneld。手工載入使用insmod命令,卸載用rmmod命令,看內核中的模塊用lsmod命令。

編譯驅動程序用gcc,主要命令行參數-DKERNEL -DMODULE。並且作為模塊載入的驅動程序,只編譯成obj形式(加-c參數)。編譯好的目標文放/lib/moles/2.x.xx/misc下,在啟動文件里用insmod載入。
Linux程序設計資料可以從網上獲得。這就是開放源代碼的好處。並且沒有什麼「未公開的秘密」。我編寫驅動程序時參閱的主要資料包括:
Linux內核源代碼
《The Linux Kernel Hacker's Guide》by Michael K. Johnson
《Linux Kernel Mole Programming Guide》by Ori Pomerantz
《Linux下的設備驅動程》by olly in BBS水木清華站
可以選擇一個模板作為開始,內核源代碼里有一個網路驅動程序的模板,drivers/net/skeleton.c。裡麵包含了驅動程序的基本內容。但這個模板是以乙太網設備為對象的,乙太網的處理在Linux系統里有特殊「待遇」,所以如果不是乙太網設備,有些細節上要注意,主要在初始化程序里。

最後,多參照別人寫的程序,聽聽其他開發者的經驗之談大概是最有效的幫助了。

Ⅷ Linux進入臨界去開關中斷的幾種方式

進入中斷時候關閉全抄局的中斷是為了避免程序處理中斷過程中,再進入另一個中斷打亂執行的順序,也就是為了防止中斷嵌套的情況發生。比如在irq_handler函數中首先就應該關閉中斷。或者,在某些操作順序中是不允許中斷發生打斷的情況。例如在驅動中常用的方式:

unsigned int flag;
local_irq_save(&flag);
... ... ... ...
local_irq_restore(&flag);

spin_loc_irqsave 禁止中斷(只在本地處理器)在獲得自旋鎖之前; 之前的中斷狀態保存在 flags 里. 如果你絕對確定在你的處理器上沒有禁止中斷的(或者, 換句話說, 你確信你應當在你釋放你的自旋鎖時打開中斷),你可以使用 spin_lock_irq 代替, 並且不必保持跟蹤 flags. 最後, spin_lock_bh 在獲取鎖之前禁止軟體中斷, 但是硬體中斷留作打開的。

Ⅸ Linux系統開機時啟動內核步驟是什麼

開機--加電自檢--讀取CMOS設置--從硬碟引導記錄查找系統所在位置--讀取GRUB配置文件(專/boot/grub/grub.conf),載入內核,驅屬動硬體--開啟init進程,讀取相應配置文件(/etc/inittab),打開默認運行級別,載入相應服務,開機啟動項--完成啟動過程

Ⅹ linux驅動程序中如何確定設備使用哪個中斷號

request_irqintrequest_irq(unsignedintirq,irqreturn_t(*handler)(int,void*,structpt_regs*),unsignedlongirqflags,constchar*devname,void*dev_id)

閱讀全文

與linuxirqflagsh相關的資料

熱點內容
上海漢得java程序員 瀏覽:288
如何利用大量數據來擬合函數 瀏覽:131
ocx文件編輯工具 瀏覽:802
高考生如何參考往年錄取數據 瀏覽:118
索尼錄屏文件夾 瀏覽:287
js清除html格式 瀏覽:748
游戲找隊友用什麼app 瀏覽:795
暗黑2源代碼 瀏覽:913
egg文件怎麼打開 瀏覽:835
剛開始學編程學哪個好 瀏覽:703
寬容房龍哪個版本好 瀏覽:769
如何做個小資料庫 瀏覽:529
win10應用程序池 瀏覽:533
讀取access最後一行資料庫 瀏覽:416
win10電腦怎麼把字放大縮小 瀏覽:385
奧迪A6鏈條數據多少正常 瀏覽:123
蘋果7手機代碼是什麼意思啊 瀏覽:637
蘋果文件沒有存儲許可權 瀏覽:291
手機wps文件名有括弧怎麼刪除 瀏覽:349
ps文件不能打包 瀏覽:489

友情鏈接