linux核心-中斷處理程式
中斷共享是指多個裝置共享一根中斷線的情況
中斷共享的使用方法:
(1).在申請中斷時,使用IRQF_SHARED標識
(2).在中斷到來時,會遍歷共享此中斷的所有中斷處理程式,直到某一個函式返回
IRQ_HANDLED,在中斷處理程式頂半部中,應迅速根據硬體暫存器中的資訊參照dev_id引數
判斷是否為本裝置的中斷,若不是立即返回IR1_NONE
/*共享中斷程式設計模板*/
irqreturn_t xxx_interrupt(int irq,void *dev_id,struct pt_regs *regs)
{
...
int status = read_int_status();/*獲知中斷源*/
if(!is_myint(dev_id,status))/*判斷是否為本裝置中斷*/
return IRQ_NONE;/*不是本裝置中斷,立即返回*/
/*是本裝置中斷,進行處理*/
...
return IRQ_HANDLED;/*返回IRQ_HANDLER表明中斷已經被處理*/
}
/*裝置模組載入函式*/
int xxx_init(void)
{
...
/*申請共享中斷*/
result = request_irq(sh_irq,xxx_interrupt,IRQF_SHARE,"xxx",xxx_dev);
...
}
/*裝置驅動模組解除安裝函式*/
void xxx_exit()
{
...
/*釋放中斷*/
free_irq(xxx_irq,xxx_interrupt);
...
}
核心定時器
核心定時器程式設計:
簡介:軟體意義上的定時器最終是依賴於硬體定時器實現的,核心在時鐘中斷髮生後檢測各
定時器是否到期,到期後定時器處理函式作為軟中斷在底半部執行。
Linux核心定時器操作:
1.timer_list結構體
每一個timer_list對應一個定時器
struct timer_list{
struct list_head entry;/*定時器列表*/
unsigned long expires;/*定時器到期時間*/
void (*function)(unsigned long);/*定時器處理函式*/
unsigned long data;/*作為引數被傳遞給定時器處理函式*/
struct timer_base_s *base;
...
};
當定時器滿的時候,定時器處理函式將被執行
2.初始化定時器
void init_timer(struct timer_list * timer);
//初始化timer_list的entry的next為NULL,並給base指標賦值。
TIMER_INITIALIZER(_function,_expires,_data);//此巨集用來
//賦值定時器結構體的function、expires
、data和base成員
#define TIMER_INITIALIZER(function,_expires,_data){
.entry = {.prev = TIMER_ENTRY_STATIC},\
.function= (_function), \
.expires = (_expire), \
.data = (_data), \
.base = &boot_tvec_bases,\
}
DEFINE_TIMER(_name,_function,_expires,_data)//定義一個定時器結構體變數
//併為此變數取名_name
//還有一個setup_timer()函式也可以用於定時器結構體的初始化,此函式大家自己去網上查吧
3.增加定時器
void add_timer(struct timer_list * timer);
//註冊核心定時器,也就是將定時器加入到核心動態定時器連結串列當中
4.刪除定時器
del_timer(struct timer_list *timer);
del_timer_sync()//在刪除一個定時器時等待刪除操作被處理完(不能用於中斷上下文中)
5.修改定時器expires
int mod_timer(struct timer_list * timer,unsigned long expires);
//修改定時器的到期時間
/*核心定時器使用模板*/
/*xxx裝置結構體*/
struct xxx_dev{
struct cdev cdev;
...
timer_list xxx_timer;/*裝置要使用的定時器*/
};
/*xxx驅動中的某函式*/
xxx_funcl(...)
{
struct xxx_dev *dev = filp->private_data;
...
/*初始化定時器*/
init_timer(&dev->xxx_timer);
dev->xxx_timer.function = &xxx_do_timer;
dev->xxx_timer.data = (unsigned long)dev;
/*裝置結構體指標作為定時器處理函式引數*/
dev->xxx_timer.expires = jiffes + delays;
/*新增(註冊)定時器*/
add_timer(&dev->xxx_timer);
...
}
/*xxx驅動中的某函式*/ xxx_func2(...)
{
...
/*刪除定時器*/
del_timer(&dev->xxx_timer);
...
}
/*定時器處理函式*/
static void xxx_do_timer(unsigned long arg)
{
struct xxx_device *dev = (struct xxx_device *)(arg);
...
/*排程定時器再執行*/
dev->xxx_timer.expires = jiffes + delay;
add_timer(&dev -> xxx_timer);
...
}
//定時器到期時間往往是在jiffies的基礎上新增一個時延,若為HZ
則表示延遲一秒
核心中的延遲工作:
簡介:對於這種週期性的工作,Linux提供了一套封裝好的快捷機制, 本質上利用工作佇列和定時器實現
這其中用到兩個結構體:
(1)struct delayed_work{
struct work_struct work;
struct timer_list timer;
};
(2)struct work_struct{
atomic_long_t data;
...
}
相關操作:
int schedule_delay_work(struct delayed_work *work,unsigned long delay);
//當指定的delay到來時delay_work中的work成員的work_func_t型別成員func()會被執行
work_func_t型別定義如下:
typedef void (*work_func_t)(struct work_struct *work);
//delay引數的單位是jiffes
mescs_to_jiffies(unsigned long mesc);//將毫秒轉化成jiffes單位
int cancel_delayed_work(struct delayed_work *work);
int cancel_delayed_work_sync(struct delayed_work *work);//等待直到刪除(不能用於中斷上下文)
核心延遲:
短延遲:
Linux核心提供瞭如下三個函式分別進行納秒、微妙和毫秒延遲:
void ndelay(unsigned long nsecs);
void udelay(unsigned long usecs);
void mdelay(unsigned long msecs);
機制:根據CPU頻率進行一定次數的迴圈(忙等待)
注意:在Linux核心中最好不要使用毫秒級的延時,因為這樣會無謂消耗CPU的資源
對於毫秒以上的延時,Linux提供如下函式
void msleep(unsigned int millisecs);
unsigned long msleep_interruptible(unsigned int millisecs);//可以被打斷
void ssleep(unsigned int seconds);
//上述函式使得呼叫它的程序睡眠指定的時間
長延遲:
機制:設定當前jiffies加上時間間隔的jiffies,直到未來的jiffies達到目標jiffires
/*例項:先延遲100個jiffies再延遲2s*/
unsigned long delay = jiffies + 100;
while(time_before(jiffies,delay));
/*再延遲2s*/
unsigned long delay = jiffies + 2*Hz;
while(time_before(jiffies,delay));//迴圈直到到達指定的時間
與timer_before()相對應的還有一個time_after
睡著延遲:
睡著延遲是比忙等待更好的一種方法
機制:在等待的時間到來之前程序處於睡眠狀態,CPU資源被其他程序使用
實現函式有:
schedule_timeout()
schedule_timeout_uninterruptible()
其實在短延遲中的msleep() msleep_interruptible()
本質上都是依賴於此函式實現的
下面兩個函式可以讓當前程序加入到等待佇列中,從而在等待佇列上睡眠,當超時
發生時,程序被喚醒
sleep_on_timeout(wait_queue_head_t *q,unsigned long timeout);
相關推薦
linux核心-中斷處理程式
中斷共享 中斷共享是指多個裝置共享一根中斷線的情況 中斷共享的使用方法: (1).在申請中斷時,使用IRQF_SHARED標識 (2).在中斷到來時,會遍歷共享此中斷的所有中斷處理程式,直到某一個函式返回 IRQ_HANDLED,在中斷處理程式頂半部中,應迅速根據硬體暫存器中的資訊參照dev_id引
9.Linux核心設計與實現 P91---中斷和中斷處理程式 (轉)
中斷還是中斷,我講了很多次的中斷了,今天還是要講中斷,為啥呢?因為在作業系統中,中斷是必須要講的.. 那麼什麼叫中斷呢, 中斷還是打斷,這樣一說你就不明白了。唉,中斷還真是有點像打斷。我們知道linux管理所有的硬體裝置,要做的第一件事先是通訊。然後,我們天天在說一句話:處理器的速度跟
linux核心分析--中斷和中斷處理程式
寫在前面: 在前面的這篇文章講解了關於中斷的基本概念,從巨集觀的角度瞭解了中斷的基本知識。從這篇文章中要明白幾點知識 1、中斷是由硬體產生的非同步中斷,而異常則是處理器產生的同步中斷 2、中斷質上是一種特殊的電訊號,由硬體裝置發向處理器,
Linux核心中斷機制(三):中斷處理上
核心中斷處理過程 S3C2410和Linux2.6.26核心為例講解處理過程 1.中斷向量表arch\arm\kernel\entry-armv.S __vectors_start: swi SYS_ERROR0 b vector_und + stubs_offset l
Linux核心中斷引入使用者空間(非同步通知機制)
當linux核心空間發生中斷後怎麼使使用者空間的應用程式執行相應的函式呢,當晶片有資料到來時核心會產生一箇中斷,但是怎樣通知應用程式來取資料,以前這個問題一直困擾我很長時間,後來發現linux中有非同步通知機制,在使用者程式中用signal註冊一個響應SIGIO訊號的回撥函式,然後在驅動程式中向該程
中斷處理程式的設計
在嵌入式系統的設計中,與外設互動,基本是兩種模式:輪詢和中斷。考慮到CPU與外設之間的速度差,如果涉及到與外設通訊,一般採用中斷的方式:只有當外設完成了資料傳送或者接收,才中斷CPU,獲得處理,這樣可以保證CPU的處理效率最高。 與資料收發相關的中斷,中斷處理程式與外部程式
Linux異常中斷處理結構
核心在start_kernel()函式(init/main.c)中會呼叫trap_init()個函式來設定異常的處理函式。 1、trap_init()函式 /* * Copy the vectors, stubs and kuser helpers (in entry
Linux系統中斷處理程式設計
與裸機中斷處理流程相似,Linux系統的中斷處理流程如下: ①中斷產生時,系統跳轉到統一的中斷入口irq_svc處執行 ②獲取中斷號 ③根據中斷號找到結構陣列irq_desc[]中對應的一項,irq_desc結構是中斷處理描述符 ④從irq_desc結構
深入理解 Linux 核心---中斷和異常
中斷或異常會改變處理器執行的指令順序。 異常: 來源:CPU 控制單元, 時機:只有在一條指令終止執行後 CPU 才會發出中斷。 原因:程式產生錯誤,或核心必須處理的異常條件。 中斷: 來源:間隔定時器或 I/O 裝置。 時機:隨機產生。 原因:依照 CP
基於PPC64架構 Linux 核心訊號處理過程棧處理分析
handle_rt_signal64主要負責訊號處理棧處理分析,如下圖所示 int handle_rt_signal64(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user
中斷處理程式與中斷服務例程
1. 什麼是中斷 簡單來說中斷就是硬體裝置與處理器的一種交流方式,比如當我按下一個鍵時,只有當處理器知道我按下了這個鍵並且做出相應的處理時,按鍵這個操作才是有效的。我們知道處理器的速度遠遠高於外圍裝置的速度,處理器與外設選擇合適的交流方式就格外重要。輪詢是一種方式,這種
linux 核心崩潰處理
pc : [<bf0000b8] 1.定位程式碼崩潰在核心中還是xxx.ko cat /proc/kallsyms >1.txt c0034818 T __kmalloc ... c00082a8 t quiet_kernel /*最開始的是虛擬地址*/
linux核心中斷分析
知識要點 一、struct irq_chip、struct irq_desc[]、struct irqaction三者之間的關係 二、Linux核心中中斷的初始化流程、中斷的註冊流程、中斷的執行流程 三、多核cpu的中斷親和力和中斷負載均衡 四、中斷的上半部和下半部 一、s
linux 核心中斷trace機制使用
如果要開啟Linux核心的中斷trace機制,需要在config裡面,開啟如下選項: CONFIG_IRQSOFF_TRACER=y 並且需要重新編譯核心。 然後,依次輸入以下命令: echo 0 > /sys/kernel/debug/tracing/trac
LINUX-核心-中斷分析-中斷向量表(2)-mips
mips中斷概念 在《MIPS體系結構透視》的第5章說到,在MIPS中,中斷、陷阱、系統呼叫和任何可以中斷程式正常執行流的情況全被都被稱為異常。 以上這種統一到“異常”的概念及其邏輯當然會體現在MIPS的異常入口點的設計中,特別如MIPS中斷入口點的引出。
彙編--學習筆記(十三)-中斷及中斷處理程式
中斷時電腦科學中最基本、也是十分重要的一個概念,可以說沒有中斷概念的引入和應用就不會有今天的計算機,至少不會有搞效率的計算機。 一、基本概念 二、BIOS中斷服務 三、DOS中斷服務 四、中斷處理技術 五、中斷處理程式例項 一、中斷: 定義:
Linux核心中斷和異常分析(上)
中斷,通常被定義為一個事件。打個比方,你燒熱水,水沸騰了,這時候你要去關掉燒熱水的電磁爐,然後再去辦之前手中停不下來的事情。那麼熱水沸騰就是打斷你正常工作的一個訊號機制。當然,還有其它的情況,我們以後
linux 核心 中斷親和力-affinity
中斷繫結——中斷親和力(IRQ Affinity) 在 SMP 體系結構中,我們可以通過呼叫系統呼叫和一組相關的巨集來設定 CPU 親和力(CPU affinity),將一個或多個程序繫結到一個或多個處理器上執行。中斷在這方面也毫不示弱,也具有相同的特性。中斷親和力是指將一個或多箇中斷源繫結到特定的 CP
LINUX系統中斷處理結構及中斷函式的實現
中斷系統流程解析: asm_do_IRQ(unsigned int irq, struct pt_regs *regs) handle_IRQ(irq, regs); generic_handle_irq(irq);/*Garmen:進行一般的中斷處理*/
關於中斷處理程式中的關中斷函式disable_irq和disable_irq_nosync
disable_irq關閉中斷並等待中斷處理完後返回, 而disable_irq_nosync立即返回. 那麼在中斷處理程式中應該使用哪一個函式來關閉中斷呢? 在<linux裝置驅動開發詳解>中的按鍵驅動中, 使用disable_irq來關閉中斷, 但是我在