一 linux中斷機制由來:
核心空間和使用者空間是現代作業系統的兩種工作模式,核心模組執行在核心空間,而使用者態應用程式執行在使用者空間,他們代表不同的級別,對系統資源有著不同的訪問許可權,核心模組執行在最高端別(核心態),這個級別下的所用操作都受系統信任,而應用程式執行在比較低階別的(使用者態)。處理器總是處於以下狀態中的一種:
核心態:執行於程序上下文,核心態代表程序執行於核心空間
核心態:執行於中斷上下文,核心態代表硬體執行於核心空間
使用者態:執行於使用者空間
linux作業系統是以程序排程為單位,中斷服務程式的執行並不在程序上下文中,所以要求中斷服務程式的時間要盡量短,為此,linux在中斷處理中引入了頂半部和底半部分離的機制。
2 根據中斷是否可以遮蔽 :分為 可遮蔽中斷 和 不可遮蔽中斷
3 根據中斷入口跳轉方式不同:分為 向量中斷 和 非向量中斷
向量中斷 :採用向量中斷的cpu通常為不同的中斷分配不同的中斷號,當檢測到某中斷號的中斷到來後,就會自動跳轉到與該中斷號對應的位址執行,不同的中斷號有不同的入口位址,向量中斷是由硬體提供中斷服務程式入口位址。
三 linux中斷處理機制
作業系統是以程序排程為單位,中斷服務程式的執行並不在程序上下文中,裝置的中斷會打斷核心程序的正常排程執行,所以系統對更高吞吐率的追求勢必要求中斷服務程式盡量短小精悍,但是大多數中斷來臨時,要完成的工作量往往不會小,可能需要較大量的耗時處理。中斷處理機制就是為了在中斷處理程式執行時間盡量短和中斷處理完需要完成的工作量盡量大之間找乙個平衡點,由此,linux將中斷處理程式分解為兩個半部:頂半部 和 底半部
頂半部 :又稱硬中斷,用於完成比較緊急的功能,往往只是簡單的讀取暫存器中的中斷狀態,並在清除中斷標誌後,啟動 底半部(軟中斷),意味著將底半部處理流程序列掛到底半部執行佇列中去,這樣頂半部的執行時間就很快,從而服務更多的中斷請求。中斷無法打斷頂半部
底半部 :又稱軟中斷,他需要完成中斷事件的絕大多數任務,由系統自行安排執行時機,它可以被新的中斷打斷,軟中斷的處理非常像硬中斷。然而,它們僅僅是由當前正在執行的程序所產生的(硬中斷是由硬體產生的)
四 實現底半部機制:
linux 實現底半部的機制主要有 tasklet、工作佇列、軟中斷和執行緒化irq等方式
4.1 tasklet機制
tasklet 是 linux中斷處理機制中的 軟中斷延遲機制,在linux中存在著硬中斷和軟中斷之別在linux 接收到 硬體中斷 之後,通過tasklet函式來設定軟中斷被執行的優先程度從而導致 軟中斷處理函式被優先執行的差異性
模板://定義底半部處理函式
void ***_do_tasklet(unsigned long);
//定義乙個 tasklet結構體 ***_tasklet,與底半部處理函式 ***_do_tasklet 繫結
declare_tasklet(***_tasklet,***_do_tasklet,0);
//中斷處理底半部
void ***_do_tasklet(undigned long)
//中斷處理頂半部
irqreturn_t ***_interrupt(int irq,void *dev_id)
//裝置驅動模組載入
int __init ***_init(void)
void _exit ***_exit(void)
rk3288 android7.1 **筆記:
場景:3288主機板i2c4 連線外部微控制器小板,外部小板發生變化時通過中斷提示3288主機板,3288主機板通過i2c獲取外部小板某暫存器內數值。
//中斷處理底半部
void chensai_do_tasklet(unsigned long date)
declare_tasklet(chensai_tasklet,chensai_do_tasklet,0);
//中斷頂半部
static irqreturn_t chensai_irq_handler(int irq, void *dev_id)
static int chensai_probe(struct i2c_client *client, const struct i2c_device_id *id)
//申請該gpio
if (gpio_request(gpio_num, "irq-gpio"))
//將該引腳設定為輸入
gpio_direction_input(gpio_num);
chensai_irq_num = gpio_to_irq(gpio_num); //將gpio轉換成對應的中斷號
dbg("%s chensai_irq_num=%d\n", __func__, chensai_irq_num);
//初始化中斷 中斷方式為下降沿觸發
ret = request_irq(chensai_irq_num, chensai_irq_handler, irq_type_edge_falling, "chensai_irq", null);
if (ret)
...return 0;
}static const struct i2c_device_id chensai_id = ,
{}};
module_device_table(i2c, chensai_id);
static struct i2c_driver chensai_drv = ,
.probe = chensai_probe,
.id_table = chensai_id,
};static int chensai_init(void)
static void chensai_exit(void)
module_init(chensai_init);
module_exit(chensai_exit);
module_license("gpl");
裝置樹:
&i2c4 ;
};4.2:工作佇列
工作佇列與tasklet方法非常類似,使用乙個結構體定義乙個工作佇列和乙個底半部執行函式,而且工作佇列的執行上下文是核心程序,所以可以排程和睡眠,(中斷上下文中不能睡眠)
//定義乙個工作佇列
struct work_struct ***_wq;
//中斷處理底半部
void ***_do_work(struct work_struct *work)
//處理底半部中斷處理函式
void ***_do_work(struct work_struct *work)
//中斷處理頂半部
irqreturn_t ***_interrupt(int irq,void *dev_id)
//裝置驅動模組載入
int ***_init(void)
//void _exit ***_exit(void)
4.3:軟中斷
Linux中斷和中斷處理
眾所周知,處理器的速度跟外圍的硬體裝置的速度往往不在乙個數量級上,因此,如果核心採取讓處理器傳送乙個請求,然後專門等待回應的辦法,顯然差強人意。既然硬體處理的這麼慢,那麼核心就應該在這期間去處理其他事務,等待硬體真正完成了請求的操作後,再回過頭來對它進行處理。輪詢 polling 可能會是一種解決辦...
Linux程序簡述
對於程序的建立,系統呼叫fork 允許乙個程序 父程序 建立乙個新程序 子程序 新的程序幾乎就等於父程序的翻版,子程序獲得了父程序的棧,資料段,堆和執行文字段的拷貝。對於程序的終止,則是使用exit status 函式,此函式會將程序所占用的所有資源 記憶體,檔案描述符等 歸還核心,交給核心進行再次...
linux中斷巢狀以及中斷丟失
在linux核心裡,如果驅動在申請註冊中斷的時候沒有特別的指定,do irq在做中斷響應的時候,是開啟中斷的,如果在驅動的中斷處理函式正在執行的過程中,出現同一裝置的中斷或者不同裝置的中斷,這時候新的中斷會被立即處理,還是被pending,等當前中斷處理完成後,再做處理。在2.4和2.6核心裡,關於...