當前位置:首頁 » 操作系統 » linux程序崩潰

linux程序崩潰

發布時間: 2023-08-01 20:42:39

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);
...
}

⑵ Linux下多線程程序崩潰時怎麼提取出所有線程的函數調用棧

gcc編譯時加-g參數,然後用gdb去跑,掛掉的時候使用bt命令就可以看到某一線程的調用棧了,你可以使用thread命令去切換線程,就可以看到不同線程的調用棧了,具體去網路一下gdb的用法就行了。
另:
還可以把堆棧錯誤給mp core,如果你覺得有必要的話。

⑶ 如果在linux中遇到down機你怎麼處理(比如資料庫崩潰,後台程序崩潰)

這樣看怎麼個崩潰了,如只是應用崩潰,那需要盡快查清楚原因,恢復數據和應用程序這些東西。
如果是系統崩潰估計只有先重啟,然後在啟動資料庫和應用啥的,看看是否受損,如有受損盡快查找原因,進行恢復操作。
如果是硬體級別的崩潰就比較慘了,只要存儲還健全,那還能通過手段恢復數據啥的,如果是存儲異常,就杯具了,基本上所有的東西都差不多該重裝了。

⑷ Linux 操作系統在什麼情況下崩潰

1.一個死循環不大可能把linux搞崩潰,尤其是到2.4以後,內核都有相應的保護機制,多半情況下這種進程會被殺死的。當然,你可以試試提高進程的優先順序(這種我沒做過,不知道結果,請事先保存好數據,以免不必要的損失)

2.還有,大量地消耗系統內存。這方法也不能成功。
比如:
======================================
#BOF
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

#define ONE_K (1024)

int main ()
{
char *some_memory;
int size_to_allocate = ONE_K;
int megs_obtained = 0;
int ks_obtained = 0;

while (1) {
for (ks_obtained = 0; ks_obtained < 1024; ks_obtained++) {
some_memory = (char*)malloc(size_to_allocate);
if (some_memory == NULL) exit (EXIT_FAILURE);
sprintf(some_memory, "Hello,World");
}
megs_obtained++;
printf("Now allocated %d Megabytes\n", megs_obtained);
}
exit(EXIT_SUCCESS);
}

#EOF
====================
運行之後,
.....
.....
Out of Memory:Killed process 2365
Killed
======================================
系統為了保護自己的安全運行,終止了這個危險的進程。

3.驅動程序出現問題,比如驅動有bug崩潰了,這時間系統就危險了,但現在的社區裡面寫的開源驅動大都能和內核很好地結合,bug也沒抓得差不多了。(關於驅動程序,可以參看Minix作者寫的操作系統原理那本書,作者分析,70%的系統崩潰是由於驅動程序引起的,所以minix採用了微內核設計,只把必要的幾千行代碼放在內核而剩下的都放到了用戶層,他認為這樣做能極大地提高系統的穩定性。關於微內核的優劣,不好評論,反正我了解一點,GNU中的一個項目是做一個叫做Hurd的微內枋系統,這個項目已經有好幾年了,可以去www.gnu.org找相應的文檔。

4.其它。(不知道了)

⑸ 分析linux內核崩潰信息

分析kernel比較關鍵的就是看三點:1) 內核會給出一個崩潰原因的猜測,這里是,CPU 0 Unable to handle kernel paging request at virtual address 000000002) 看pc指針的值,這里是epc == 000000003) 看調用棧Call Trace:[ //可惜後面沒給出來通常是根據指針加上偏移值跟反匯編代碼對照,找到出問題的指令。這個panic的原因比較明顯,應該是引用了空指針,試圖執行0x00000000出的代碼。
熱點內容
android在線支付 發布:2025-03-13 13:50:21 瀏覽:790
瑞影無損圖片壓縮大師 發布:2025-03-13 13:27:33 瀏覽:452
應用怎樣加密 發布:2025-03-13 13:18:10 瀏覽:674
李弘毅訪問 發布:2025-03-13 13:17:30 瀏覽:656
伺服器搭建直播平台源碼 發布:2025-03-13 12:54:38 瀏覽:813
c語言的題 發布:2025-03-13 12:45:01 瀏覽:609
小學試演算法 發布:2025-03-13 12:39:06 瀏覽:999
更改手機伺服器節點有什麼用 發布:2025-03-13 12:39:04 瀏覽:307
python基礎視頻教程下載 發布:2025-03-13 12:37:38 瀏覽:803
筆記本怎麼配置揚聲器 發布:2025-03-13 12:32:03 瀏覽:543