linux中斷軟中斷
1. 請教linux3.x 中中斷注冊中硬體中斷號和軟體中斷號的對應
我也不完全理解,但是比你知道的多點。 Linux中,分內核態和用戶態。 你寫的所有的驅動,都是出於內核態->可以直接使用內核相關資源; 應用層,都是用戶態->無法直接操作底層的東西 -> 想要操作,比如獲得許可權,切換到內核態,然後才能操作。
2. linux 什麼時候用軟中斷
在中斷處理程序不是很緊急的時候適合使用軟中斷,tasklist workqueue threadirq等,分為前半部後半部,前半部緊急響應中斷操作,後半部在處理器空閑是再處理
3. linux中軟中斷(softirq)為什麼不能嵌套
硬中斷能嵌套........................嗯..........這個說法很奇怪................
根據我的理解是硬中斷能被硬中斷搶斷.................不知道你所謂的嵌套何指.
軟中斷都在下半部處理.處理時間即長.涉及資源又多.在這里需要同步的地方非常多.難度也比較高..........軟中斷如果沒記錯的話.是不能被同種類型搶斷.可以被非同類型搶斷.因為同類型多涉及相同資源.如果被同類搶斷的話.上一個佔有的資源未釋放.這一個又一直得不到資源.就會一直被阻塞.造成系統進退不得.所以才禁止同類搶斷.
不過在不同下半部解決方案設計中.限制也不一樣.具體可以自行了解.
不知道你說的可以嵌套指的是什麼東西..................
4. linux系統調用是通過軟中斷實現的嗎
軟中斷是利用硬體中斷的概念,用軟體方式進行模擬,實現宏觀上的非同步執行效果。很多情況下,軟中斷和信號有些類似,同時,軟中斷又是和硬中斷相對應的,硬中斷是外部設備對CPU的中斷,軟中斷通常是硬中斷服務程序對內核的中斷,信號則是由內核(或其他進程)對某個進程的中斷(《Linux內核源代碼情景分析》第三章)。軟中斷是linux系統原「底半處理」的升級,在原有的基礎上發展的新的處理方式,以適應多cpu 、多線程的軟中斷處理。
軟中斷是實現系統API函數調用的手段
函數調用時將返回地址和CPU狀態寄存器內容壓棧,函數執行完畢後出棧返回斷點繼續執行。
軟中斷調用時將返回地址和CPU狀態寄存器內容壓棧,修改特權級,根據中斷號查找中斷向量表,找到ISR中斷服務常式地址,跳轉執行。
5. linux系統的軟中斷的中斷事件有哪些
軟中斷就是信號中斷,能發送信號的事件就能發送中斷,比如鍵盤中斷SIGINT,SIGTSTP,SIGSTOP, 時鍾中斷SIGALRM,浮點中斷等等
6. linux 內核軟中斷 是在中斷狀態嗎
先說說環境
1.硬體:DELL R410
2.網卡:板載1000M BCM5709
2.OS: RHEL 5.5 x86_64
3.KERNEL: 2.6.18-194.el5
所出現的問題
1.網卡毫無徵兆的down掉,而且沒有任何log信息
2.當流量增大時,不到理論上限的1/3時機器出現網路延遲嚴重,伴隨大量的丟包
3.機器的cpu軟中斷不均衡,只有1個cpu處理軟中斷,並且該cpu的軟中斷周期性的達到100%
4.內外網網卡做nat丟包數據量不一致,差別很大,不在同一個數量級
想必第一個問題,大部分使用bcm網卡,rhel 5.3以後得機器都會遇到這種情況,網上的資料比較的多,我也不多啰嗦了,直接升級網卡驅動就可以解決了。第二,三,四其實是同一個問題都是由於網卡中斷過多,cpu處理不過來(准確的說,cpu分配不均衡,導致只有一個cpu處理,處理不過來),引起丟包,那麼為什麼兩個網卡丟包的數量級不一樣呢,下面從原理上進行解釋,既然是做nat多出口,那麼就有大量的路由信息,是一個網路應用,當一個數據包請求nat時,數據包先被網卡驅動的數據接收,網卡收到數據時,觸發中斷。在中斷執行常式中,把skb掛入輸入隊列,並觸發軟中斷。稍後的某個時刻,當軟中斷執行時,再從該隊列中把skb取下來,投遞給上層協議。
如果在這個過程當中cpu沒有及時處理完這個隊列導致網卡的buffer滿了,網卡將直接丟棄該數據包。這里牽涉到2個隊列,一個是tx,一個是rx,它的隊列的大小默認都是255,可以通過ethtool -g eth0(你指定的網卡),為了防止丟包,當時我通過ethtool -G eth0 rx xxx 把它調大了,但是調大以後,還是杯水車薪啊,通過ethtool -S eth0 |grep rx_fw_discards,發現數值還是不停的在增長,也就是說還在不停的丟包,cpu處理不過來,這時候找到網上有人在利用lvs時也遇到這個問題,cpu軟中斷分配不均衡,只有一個cpu處理軟中斷的問題,網上的資料五花八門,有建議使用修改設備中斷方式。即通過修改設置中斷/proc/irq/${網卡中斷號}/smp_affinit這時候,我也修改過,沒有什麼實質的效果,
從官方的bug報告,https://bugzilla.redhat.com/show_bug.cgi?id=520888,其中提到rhel5.6已經修復了這個bug,這其中也提到目前我們的版本可以升級內核到kernel-2.6.18-194.3.1.el5可以解決這個問題。
紅帽子官方修復報告中的說明如下:http://rhn.redhat.com/errata/RHSA-2010-0398.html,我們升級了這個內核算是解決單核處理軟中斷的問題,升級後各個cpu已經能夠平均的分配這個軟中斷,也不丟包了,那麼為什麼cpu處理不過來這個軟中斷呢,數據量並不是特別的大啊,上層應用接到這個數據包後,通過路由協議,找到某個出口給nat出去,找nat出口是需要查找路由表,查詢路由表是一件很耗時的工作,而每一個不同源地址,不同目的地址的數據包都得重新查找一次路由表,導致cpu處理不過來,為了提高路由查詢的效率。Linux內核引用了路由緩存,用於減少對路由表的查詢。Linux的路由緩存是被設計來與協議無關的獨立子系統,查看路由緩存可以通過命令route -Cn,由於路由緩存當中是採用hash演算法進行才找,它的查找速度非常之快,既然是cache就有超時這一概念。系統默認為10分鍾,可以通過這個文件進行查看和修改/proc/sys/net/ipv4/route/secret_interval。而當路由緩存當中未找到或者已經超時的路由信息才開始查找路由表,查詢到的結果保存在路由緩存中。如果路由表越大,那麼查詢的時間就越長,一個新的連接進來後或者是老連接cache超時後,佔用大量的cpu查詢時間,導致cpu周期性的軟中斷出現100%,而兩個網卡丟包的情況來看不均衡也是因為用戶的數據包是經過其中一個網卡進來後查詢路由表耗時過長,cpu處理不過來,導致那塊網卡的隊列滿了,丟包嚴重。當然在路由表變動不大的情況下可以加大cache的時間,修改上述內容後,從我監測的情況來看,扛流量能力得到了大大的提升。
7. linux下 軟中斷處理函數do_softirq中用了local_irq_disable()來屏蔽中斷
中斷屏蔽,確實會導致中斷丟失。但是,中斷控制器本身會保證中斷不被丟失。對於水平觸發中斷,一個中斷發送出去,如果沒有cpu的ack,會一直懸停在那,直到相應為止。一個邊緣觸發的中斷,是設計成可以丟失的中斷,丟失了也無所謂。因為中斷控制器會重發。
對於網路數據中的大量中斷,有NAPI的方式來實現。
8. LINUX軟中斷通信
我驗證下阿...一不小心就fork多了..
剛開始我把kill的參數弄反了,信號和pid位置弄錯了,調了半個小時,很郁悶..
你只是忽略了一點...,我也給忽略了。。。後來才想起來
你按下ctrl+C的時候,另外兩個fork出來的進程,他們也會接到SIGINT。。。就退出了。。所以你要先在子進程裡面忽略這個SIGINT信號,用signal(SIGINT,SIG_IGN)就OK了....
程序如下...
有解釋,你可以自己看看...
#include"stdio.h"
#include"unistd.h"
#include"signal.h"
#include"sys/types.h"
#include"stdlib.h"
int k=0;
pid_t child1=0,child2=0;
void func_main(int sig);
void func_child1(int sig);
void func_child2(int sig);
int main()
{
while((child1=fork())==-1);
if(child1==0)
{
printf("child1 OK\n");
signal(SIGINT,SIG_IGN);
signal(SIGUSR1,func_child1);
sleep(60);
}
else if(child1 >0)
{
while((child2=fork())==-1);
if(child2==0)
{
printf("child 2 OK\n");
signal(SIGINT,SIG_IGN);//你按下ctrl+C,子進程也會接受到ctrl的信號...所以,子進程忽略
//所提子進程要忽略掉這個SIGINT信號
signal(SIGUSR2,func_child2);
sleep(60); //這里為了驗證,如果進程沒退出,40妙之後自動會退出的
//不然就得手動在終端裡面kill掉這個進程了...
//有時候成了僵屍進程需要kill -9 才能殺死
}
else if(child2 >0)
{
signal(SIGINT,func_main);
printf("children forked OK...\n");
wait(0);
printf("child return...\n");
sleep(100);
return 0;
}
}
}
void func_main(int sig)
{
k++;
printf("to send signal\n");
//printf("child1=%d,child2=%d\n",child1,child2);
//if(k==1)
kill(child1,SIGUSR1);
//if(k==2) 加上這句,再按一次ctrl C,子進程2才會退出
就是你想要的效果了
kill(child2,SIGUSR2);
signal(SIGINT,SIG_DFL); //這里恢復ctrl+C的效果
//子進程退出之後,我們再按一次ctrl+C,當前的父進程就會像平常一樣,退出。
}
void func_child1(int sig)
{
printf("child1 is killed by parent!\n");
exit(0);
}
void func_child2(int sig)
{
printf("child2 is killed by parent!\n");
exit(0);
}