青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆-19  評(píng)論-21  文章-0  trackbacks-0
此文只簡(jiǎn)單分析發(fā)送信號(hào)給用戶(hù)程序后,用戶(hù)堆棧和內(nèi)核堆棧的變化。沒(méi)有分析實(shí)時(shí)信號(hào),當(dāng)然整個(gè)過(guò)程基本一致。很多參考了<情景分析>,所以有些代碼和現(xiàn)在的內(nèi)核可能不同,比如RESTORE_ALL,但大體的機(jī)制是類(lèi)似的。

1. 一個(gè)信號(hào)小例子

hex@Gentoo ~/signal $ cat sigint.c
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

void sig_int(int signo)
{
    printf("hello\n");
}

int main()
{
    if(signal(SIGINT, sig_int) == SIG_ERR){
        printf("can't catch SIGINT\n");
        exit(-1);
    }

    for(;;)
        ;

    return 0;
}

2. 用戶(hù)堆棧里發(fā)生的故事

2.1 編譯運(yùn)行該程序,并設(shè)置斷點(diǎn)在sig_int函數(shù)開(kāi)頭(0x80482e8),并設(shè)置SIGINT信號(hào)的處理方式
hex@Gentoo ~/signal $ gdb ./sigint
(gdb) b *0x80482e8
Breakpoint 1 at 0x80482e8: file sigint.c, line 6.
(gdb) handle SIGINT noprint pass
SIGINT is used by the debugger.
Are you sure you want to change it? (y or n) y
Signal        Stop    Print    Pass to program    Description
SIGINT        No    No    Yes        Interrupt
(gdb) r
Starting program: /home/gj/signal/sigint

2.2 向該程序發(fā)送信號(hào): kill -INT 此程序的pid號(hào)
hex@Gentoo ~/signal $ kill -INT 4639

2.3 該程序收到信號(hào)后停在斷點(diǎn)處
Breakpoint 1, sig_int (signo=2) at sigint.c:6
6    {
(gdb) i r esp
esp            0xbfffe7ec    0xbfffe7ec
(gdb) x/40a 0xbfffe7ec
0xbfffe7ec:    0xb7fff400    0x2    0x33    0x0
0xbfffe7fc:    0x7b    0x7b    0x8048930 <__libc_csu_init>    0x80488f0 <__libc_csu_fini>
0xbfffe80c:    0xbfffed58    0xbfffed40    0x0    0x0
0xbfffe81c:    0xbfffec18    0x0    0x0    0x0
0xbfffe82c:    0x8048336 <main+58>    0x73    0x213    0xbfffed40
0xbfffe83c:    0x7b    0xbfffead0    0x0    0x0
0xbfffe84c:    0x0    0x0    0x0    0x0
0xbfffe85c:    0x0    0x0    0x0    0x0
0xbfffe86c:    0x0    0x0    0x0    0x0
0xbfffe87c:    0x0    0x0    0x0    0x0
棧上的內(nèi)容為信號(hào)棧sigframe:
根據(jù)此結(jié)構(gòu)可以知道:
1). 返回地址0xb7fff400,它指向vdso里的sigreturn
(gdb) x/10i 0xb7fff400
   0xb7fff400 <__kernel_sigreturn>:    pop    %eax
   0xb7fff401 <__kernel_sigreturn+1>:    mov    $0x77,%eax
   0xb7fff406 <__kernel_sigreturn+6>:    int    $0x80
這個(gè)地址根據(jù)內(nèi)核的不同而不同,我的內(nèi)核版本是2.6.38。
2). 信號(hào)處理程序完成后,會(huì)回到 eip = 0x8048336 的地址繼續(xù)執(zhí)行。


2.4 執(zhí)行完sig_int函數(shù)后,進(jìn)入了__kernel_sigreturn,接著回到了代碼0x8048336處,一切恢復(fù)了正常。
(gdb) x/5i $pc
=> 0x8048336 <main+58>:    jmp    0x8048336 <main+58>
(gdb) i r esp
esp            0xbfffed40    0xbfffed40

在用戶(hù)層我們能看到的只有上面這么多信息了,可能有一個(gè)地方不能理解:在上面過(guò)程c中 從0xbfffe7ec起那一塊棧上的內(nèi)容從哪來(lái)的?(正常情況下堆棧esp應(yīng)該一直指向在過(guò)程d中顯示的esp值0xbfffed40)

現(xiàn)在來(lái)看看在上面這些現(xiàn)象之下,內(nèi)核的堆棧發(fā)生了怎樣的變化。

3. 內(nèi)核堆棧里發(fā)生的故事
3.1 發(fā)信號(hào)時(shí)
在 2.2 里當(dāng)執(zhí)行kill -INT 4639后,pid為4639的程序(也就是我們運(yùn)行的 ./sigint)會(huì)收到一個(gè)信號(hào),但是信號(hào)實(shí)際都是在內(nèi)核里實(shí)現(xiàn)的。每個(gè)進(jìn)程(這里只講進(jìn)程的情況,線(xiàn)程類(lèi)似,線(xiàn)程有一個(gè)tid)都有一個(gè)pid,與此pid對(duì)應(yīng)有一個(gè)結(jié)構(gòu) task_struct ,在task_struct里有一個(gè)變量 struct sigpending pending,當(dāng)該進(jìn)程收到信號(hào)時(shí),并不會(huì)立即作出反應(yīng),只是讓內(nèi)核把這個(gè)信號(hào)記在了此變量里(它里面是一個(gè)鏈表結(jié)構(gòu))。當(dāng)然,此時(shí)與內(nèi)核堆棧還沒(méi)有多大關(guān)系。

3.2 檢測(cè)信號(hào)
  如果只記錄了信號(hào),但沒(méi)有相應(yīng)反應(yīng),那有什么用啊。一個(gè)進(jìn)程在什么 情況下會(huì)檢測(cè)信號(hào)的存在呢?在<情景分析>里說(shuō)到了:“在中斷機(jī)制中,處理器的硬件在每條指令結(jié)束時(shí)都要檢測(cè)是否有中斷請(qǐng)求的存在。信號(hào)機(jī)制是純軟件的,當(dāng)然不能依靠硬件來(lái)檢測(cè)信號(hào)的到來(lái)。同時(shí),要在每條指令結(jié)束時(shí)都來(lái)檢測(cè)顯然是不現(xiàn)實(shí)的,甚至是不可能的。所以對(duì)信號(hào)的檢測(cè)機(jī)制是:每當(dāng)從系統(tǒng)調(diào)用,中斷處理或異常處理返回到用戶(hù)空間的前夕;還有就是當(dāng)進(jìn)程被從睡眠中喚醒(必定是在系統(tǒng)調(diào)用中)的時(shí)候,此時(shí)若發(fā)現(xiàn)有信號(hào)在等待就要提前從系統(tǒng)調(diào)用返回。總而言之,不管是正常返回還是提前返回,在返回到用戶(hù)空間的前夕總是要檢測(cè)信號(hào)的存在并作出反應(yīng)。”

  因此,對(duì)收到的信號(hào)做出反應(yīng)的時(shí)間是 從內(nèi)核返回用戶(hù)空間的前夕,那么有那些情況會(huì)讓程序進(jìn)入內(nèi)核呢?答案是中斷,異常和系統(tǒng)調(diào)用。簡(jiǎn)單了解一下它們發(fā)生時(shí)內(nèi)核堆棧的變化。
  //-----中斷,異常,系統(tǒng)調(diào)用 : 開(kāi)始
   1)在用戶(hù)空間發(fā)生中斷時(shí),CPU會(huì)自動(dòng)在內(nèi)核空間保存用戶(hù)堆棧的SS, 用戶(hù)堆棧的ESP, EFLAGS, 用戶(hù)空間的CS, EIP, 中斷號(hào) - 256
   | 用戶(hù)堆棧的SS | 用戶(hù)堆棧的ESP | EFLAGS | 用戶(hù)空間的CS | EIP | 中斷號(hào) - 256
   進(jìn)入內(nèi)核后,會(huì)進(jìn)行一個(gè)SAVE_ALL,這樣內(nèi)核棧上的內(nèi)容為:
   | 用戶(hù)堆棧的SS | 用戶(hù)堆棧的ESP | EFLAGS | 用戶(hù)空間的CS | EIP | 中斷號(hào) - 256 | ES | DS | EAX | EBP | EDI | ESI | EDX | ECX | EBX

   好了,一切都處理完時(shí),內(nèi)核jmp到RESTORE_ALL(它是一個(gè)宏,例:在x86_32體系結(jié)構(gòu)下,/usr/src/kernel/arch/286/kernel/entry_32.S文件里包含該宏的定義)

   RESTORE做的工作,從它的代碼里就可以看出來(lái)了:   
   首先把棧上的 ES | DS | EAX | EBP | EDI | ESI | EDX | ECX | EBX pop到對(duì)應(yīng)的寄存器里
   然后將esp + 4 把 “中斷號(hào) - 256” pop掉
   此時(shí)內(nèi)核棧上的內(nèi)容為:
   | 用戶(hù)堆棧的SS | 用戶(hù)堆棧的ESP | EFLAGS | 用戶(hù)空間的CS | EIP
   最后執(zhí)行iret指令,此時(shí)CPU會(huì)從內(nèi)核棧上取出SS, ESP, ELFGAS, CS, EIP,然后接著運(yùn)行。

   2) 在用戶(hù)空間發(fā)生異常時(shí),CPU自動(dòng)保存在內(nèi)核棧的內(nèi)容為:
   | 用戶(hù)堆棧的SS | 用戶(hù)堆棧的ESP | EFLAGS | 用戶(hù)空間的CS | EIP | 出錯(cuò)代碼 error_code
   (注:CPU只是在進(jìn)入異常時(shí)才知道是否應(yīng)該把出錯(cuò)代碼壓入堆棧(為什么?),而從異常處理通過(guò)iret指令返回時(shí)已經(jīng)時(shí)過(guò)境遷,CPU已經(jīng)無(wú)從知當(dāng)初發(fā)生異常的原因,因此不會(huì)自動(dòng)跳過(guò)這一項(xiàng),而要靠相應(yīng)的異常處程序?qū)Χ褩<右哉{(diào)整,使得在CPU開(kāi)始執(zhí)行iret指令時(shí)堆棧頂部是返回地址)

   進(jìn)入內(nèi)核后,沒(méi)有進(jìn)行SAVE_ALL,而是進(jìn)入相應(yīng)的異常處理函數(shù)(這個(gè)函數(shù)是包裝后的,真正的處理函數(shù)在后面)(在此函數(shù)里會(huì)把真正的處理函數(shù)的地址push到棧上),然后jmp到各種異常處理所共用的程序入口error_code,它會(huì)像SAVE_ALL那樣保存相應(yīng)的寄存器(沒(méi)有保存ES),此時(shí)內(nèi)核空間上的內(nèi)容為:
   | 用戶(hù)堆棧的SS | 用戶(hù)堆棧的ESP | EFLAGS | 用戶(hù)空間的CS | EIP | 出錯(cuò)代碼 error_code | 相應(yīng)異常處理函數(shù)入口 | DS | EAX | EBP | EDI | ESI | EDX | ECX | EBX
   (注:如果沒(méi)有出錯(cuò)代碼,則此值為0)

   最后結(jié)束時(shí)與中斷類(lèi)似(RESTORE_ALL)。

   3) 發(fā)生系統(tǒng)調(diào)用時(shí),CPU自動(dòng)保存在內(nèi)核棧的內(nèi)容為:
   | 用戶(hù)堆棧的SS | 用戶(hù)堆棧的ESP | EFLAGS | 用戶(hù)空間的CS | EIP
   為了與中斷和異常的棧一致,在進(jìn)入系統(tǒng)調(diào)用入口(ENTRY(system_call))后會(huì)首先push %eax,然后進(jìn)行SAVE_ALL,此時(shí)內(nèi)核棧上的內(nèi)容為
   | 用戶(hù)堆棧的SS | 用戶(hù)堆棧的ESP | EFLAGS | 用戶(hù)空間的CS | EIP | EAX | ES | DS | EAX | EBP | EDI | ESI | EDX | ECX | EBX
 
   最后結(jié)束時(shí)與中斷類(lèi)似(RESTORE_ALL)。
   //-----中斷,異常,系統(tǒng)調(diào)用 : 結(jié)束

   中斷,異常,系統(tǒng)調(diào)用這部分有一點(diǎn)遺漏的地方:檢測(cè)信號(hào)的時(shí)機(jī)就是緊挨著RESTORE_ALL之前發(fā)生的。

3.3 對(duì)檢測(cè)到的信號(hào)做出反應(yīng)
  如果檢測(cè)到有要處理的信號(hào)時(shí),就要開(kāi)始做一些準(zhǔn)備工作了,此時(shí)內(nèi)核里的內(nèi)容為(進(jìn)入內(nèi)核現(xiàn)場(chǎng)時(shí)的內(nèi)容)
  | 用戶(hù)堆棧的SS1 | 用戶(hù)堆棧的ESP1 | EFLAGS1 | 用戶(hù)空間的CS1 | EIP1 | ? | ES1 | DS1 | EAX1 | EBP1 | EDI1 | ESI1 | EDX1 | ECX1 | EBX1
  (注:?的值有三個(gè)選擇:中斷號(hào) - 256/出錯(cuò)代碼 error_code/出錯(cuò)代碼 error_code)
  假設(shè)將要處理的信號(hào)對(duì)應(yīng)的信號(hào)處理程序是用戶(hù)自己設(shè)置的,即本文中SIGINT對(duì)應(yīng)的信號(hào)處理程序sig_int。
  現(xiàn)在要做的事情是讓cpu去執(zhí)行信號(hào)處理程序sig_int,但是執(zhí)行前需要做好準(zhǔn)備工作:
  3.3.1  setup_frame
  在用戶(hù)空間設(shè)置好信號(hào)棧(struct sigframe)(假設(shè)設(shè)置好棧后esp的值為sigframe_esp,在本文中其值為0xbfffe7ec),即在2.3里看到的棧內(nèi)容。
  注:struct sigframe里至少包含以下內(nèi)容:
  用戶(hù)堆棧的SS1, 用戶(hù)堆棧的ESP1, EFLAGS1, 用戶(hù)空間的CS1, EIP1, ES1, DS1, EAX1, EBP1, EDI1, ESI1, EDX1, ECX1, EBX1

  3.3.2 設(shè)置即將運(yùn)行的eip的值為信號(hào)處理函數(shù)sig_int的地址(為0x80482e8),并設(shè)置用戶(hù)ESP的值為sigframe_esp(為0xbfffe7ec),這是通過(guò)修改內(nèi)核棧里的EIP和ESP的值實(shí)現(xiàn)的,因?yàn)樵趶南到y(tǒng)調(diào)用里iret時(shí),會(huì)從內(nèi)核棧里取EIP,ESP。
  這時(shí)內(nèi)核棧的內(nèi)核為:
  | 用戶(hù)堆棧的SS1 | 0xbfffe7ec | EFLAGS1 | 用戶(hù)空間的CS1 | 0x80482e8 | ? | ES1 | DS1 | EAX1 | EBP1 | EDI1 | ESI1 | EDX1 | ECX1 | EBX1
 
  最后,進(jìn)行RESTORE_ALL,內(nèi)核棧上的內(nèi)容為:
  | 用戶(hù)堆棧的SS1 | 0xbfffe7ec | EFLAGS1 | 用戶(hù)空間的CS1 | 0x80482e8
 
  RESTORE_ALL里執(zhí)行完iret后,寄存器內(nèi)容為: EIP為0x80482e8(即sig_int),esp為0xbfffe7ec 。 于是用戶(hù)空間到了步驟 2.3

3.4 信號(hào)處理程序完成以后
  2.3 -> 2.4,進(jìn)入了sig_return系統(tǒng)調(diào)用,在sig_return里,內(nèi)核棧的內(nèi)容為(每個(gè)名字后面加一個(gè)2以便與前面的1區(qū)分)
  | 用戶(hù)堆棧的SS2 | 用戶(hù)堆棧的ESP2 | EFLAGS2 | 用戶(hù)空間的CS2 | EIP2 | ? | ES2 | DS2 | EAX2 | EBP2 | EDI2 | ESI2 | EDX2 | ECX2 | EBX2
  sig_return要做的主要工作就是根據(jù)用戶(hù)棧里sigframe的值修改內(nèi)核棧里的內(nèi)容,使內(nèi)核棧變?yōu)?
  | 用戶(hù)堆棧的SS1 | 用戶(hù)堆棧的ESP1 | EFLAGS1 | 用戶(hù)空間的CS1 | EIP1 | ? | ES1 | DS1 | EAX1 | EBP1 | EDI1 | ESI1 | EDX1 | ECX1 | EBX1
                                                  
  至此內(nèi)核棧里的內(nèi)容和進(jìn)行信號(hào)處理前一樣了。經(jīng)過(guò)RESTORE_ALL后,用戶(hù)堆棧里的內(nèi)容也和以前一樣(主要指ESP的值一樣)。

  "kill -INT 4639" 只是一段小插曲。程序從原處開(kāi)始運(yùn)行。
posted on 2011-07-26 18:27 hex108 閱讀(4080) 評(píng)論(0)  編輯 收藏 引用 所屬分類(lèi): Kernel
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲欧美日韩精品久久亚洲区| 欧美日韩另类综合| 欧美国产精品| 美女国内精品自产拍在线播放| 久久精品九九| 麻豆免费精品视频| 亚洲福利久久| 亚洲精品一区中文| 亚洲欧美999| 久久国内精品自在自线400部| 欧美在线视频网站| 欧美91精品| 国产精品狼人久久影院观看方式| 国产日韩av一区二区| 亚洲欧洲另类| 亚洲美女在线一区| 亚洲一品av免费观看| 久久国产精品久久w女人spa| 欧美不卡一卡二卡免费版| 亚洲韩国日本中文字幕| 宅男噜噜噜66国产日韩在线观看| 性欧美大战久久久久久久免费观看 | 欧美制服丝袜| 美女主播精品视频一二三四| 欧美日韩视频一区二区| 国产亚洲女人久久久久毛片| 在线精品视频一区二区| 9l视频自拍蝌蚪9l视频成人| 国产精品视频观看| 亚洲欧洲日产国产综合网| 亚洲精品中文字幕在线观看| 一区二区三区欧美激情| 欧美一区久久| 午夜视频在线观看一区二区三区| 久久精品道一区二区三区| 快播亚洲色图| 99精品视频免费观看视频| 亚洲欧美www| 久久嫩草精品久久久精品| 欧美极品aⅴ影院| 国产精品嫩草99a| 一区免费观看| 亚洲电影第1页| 欧美日韩精品欧美日韩精品一| 国产自产女人91一区在线观看| 亚洲电影激情视频网站| 亚洲一区二区三区高清| 玖玖综合伊人| 亚洲一区bb| 蜜桃视频一区| 国产亚洲精品高潮| 一区二区三区四区五区精品视频 | 亚洲欧美日韩精品一区二区| 亚洲午夜女主播在线直播| 亚洲欧美日韩视频一区| 亚洲一区二区3| 国产欧美精品在线| 制服丝袜激情欧洲亚洲| 男女av一区三区二区色多| 一二三区精品| 欧美精品福利| 亚洲国产精品123| 久久婷婷色综合| 亚洲欧美综合| 国产精品美女诱惑| 久久九九国产| 午夜精品一区二区三区电影天堂 | 1024成人| 欧美在线视频导航| 日韩午夜黄色| 欧美欧美在线| 亚洲国产精品v| 亚洲一区二区在线免费观看| 麻豆精品视频在线观看视频| av成人免费| 欧美人在线观看| 日韩亚洲视频| 亚洲电影av| 久久亚洲欧洲| 亚洲成人影音| 欧美大片在线看| 麻豆精品视频在线观看| 1000部精品久久久久久久久| 免费不卡亚洲欧美| 久久这里只有| 亚洲精品一区二| 亚洲欧洲精品一区二区| 欧美大片网址| 一区二区久久| 久久久精品欧美丰满| 欧美三级网页| 亚洲主播在线| 亚洲欧洲99久久| 韩国精品主播一区二区在线观看| 久久久91精品国产| 久久女同互慰一区二区三区| 91久久久久久久久久久久久| 亚洲国产精品999| 欧美视频第二页| 国产综合自拍| 午夜精品久久久久久久白皮肤| 欧美一区=区| 亚洲国内高清视频| 999亚洲国产精| 国产精品欧美日韩一区二区| 久久精品国产久精国产一老狼| 午夜亚洲一区| 亚洲人成网站色ww在线| 亚洲国产精品一区制服丝袜| 欧美成人一区二区三区在线观看| 亚洲视频axxx| 午夜精品在线看| 国产一区99| 亚洲国产婷婷香蕉久久久久久99| 欧美韩日一区二区三区| 亚洲国产精品传媒在线观看| 午夜一区不卡| 一区二区欧美在线| 欧美专区18| 一本一本久久a久久精品牛牛影视| 在线亚洲成人| 亚洲精品日韩欧美| 久久国产色av| 亚洲激情av在线| 国产精品免费观看视频| 免费成人性网站| 国产精品a级| 中文精品视频一区二区在线观看| 国内外成人免费激情在线视频 | 久久久精品性| 亚洲社区在线观看| 久久久精品久久久久| 午夜国产精品视频| 午夜精品视频| 久久国产精品久久久久久久久久| 老司机久久99久久精品播放免费| 亚洲视频一区| 欧美精品一区二区三区高清aⅴ| 久久精彩视频| 国产精品s色| 亚洲成人在线网站| 韩国精品主播一区二区在线观看| 中国亚洲黄色| 在线视频亚洲| 欧美激情免费观看| 免费观看日韩av| 激情综合中文娱乐网| 亚洲欧美日韩综合国产aⅴ| 国产一区二区三区在线免费观看 | 欧美粗暴jizz性欧美20| 久久亚洲精品一区| 国产精品一区免费观看| 欧美一级大片在线观看| 国产精品嫩草影院av蜜臀| av不卡在线观看| 9人人澡人人爽人人精品| 欧美人与性动交cc0o| 亚洲精品乱码久久久久久黑人| 亚洲国产日韩一区二区| 亚洲主播在线| 免费视频久久| 亚洲欧洲精品一区二区三区不卡| 蜜臀av性久久久久蜜臀aⅴ四虎| 久色婷婷小香蕉久久| 1024亚洲| 欧美巨乳在线观看| 亚洲精品一区二区三区樱花| 亚洲国产清纯| 欧美aⅴ一区二区三区视频| 亚洲国产精品女人久久久| 日韩午夜视频在线观看| 欧美性久久久| 欧美在线free| 欧美va天堂| 欧美日韩在线不卡| 亚洲女同精品视频| 久久深夜福利免费观看| 悠悠资源网亚洲青| 欧美成人激情在线| 亚洲免费观看在线视频| 亚洲欧美国产日韩中文字幕| 国产精品一区二区三区久久| 欧美一区二区三区在线看| 亚洲免费视频网站| 影音先锋亚洲精品| 亚洲欧美一区二区精品久久久| 国产麻豆成人精品| 欧美在线|欧美| 亚洲精品乱码久久久久久蜜桃91| 亚洲国产精品高清久久久| 欧美韩日高清| 午夜精品久久久久久久久| 亚洲黄色天堂| 欧美在线视频一区| 亚洲国产精选| 国产精品视频1区| 欧美激情bt| 亚洲男人的天堂在线观看| 欧美激情精品久久久六区热门| 99精品久久免费看蜜臀剧情介绍|