• <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>
            隨筆 - 1  文章 - 0  trackbacks - 0
            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            常用鏈接

            留言簿(1)

            隨筆分類

            隨筆檔案

            搜索

            •  

            最新評論

            信號是傳送給進程的一種事件通知,生成信號的事件有三大類:

            1.       程序錯誤:除零,非法內(nèi)存訪問

            2.       外部信號:終端Ctrl-C產(chǎn)生SGINT信號,定時器到期產(chǎn)生SIGALRM…

            3.       顯示請求:kill函數(shù)允許進程發(fā)送任何信號給其他進程或進程組。

            信號生成既可以是同步的(信號與程序中的某個具體操作相關(guān)并在那個操作同時產(chǎn)生),也可以是異步的。通常程序錯誤生成信號為同步的,進程顯式請求給自己的信號也是同步的。

            外部事件總是異步的,來自其他進程的顯示請求也是異步的。

            信號發(fā)生時,我們可以告訴unix內(nèi)核采取下面三種動作中的任一種:

            1.       忽略信號:大部分信號可被忽略,除SIGSTOPSIGKILL信號外(這是超級用戶殺掉或停掉任意進程的手段)。

            2.       捕獲信號:注冊信號處理函數(shù),它對產(chǎn)生的特定信號做處理。

            3.       讓信號默認動作起作用:unix內(nèi)核定義的默認動作,有5種情況:

            a)         流產(chǎn)abort:終止進程并產(chǎn)生core文件。

            b)        終止stop:終止進程但不生成core文件。

            c)         忽略:忽略信號。

            d)        掛起suspend:掛起進程。

            e)         繼續(xù)continue:若進程是掛起的,則resume進程,否則忽略此信號。

            任意時刻,進程可以為信號指定動作。

            信號處理涉及兩個過程,生成與交付。

            信號生成出現(xiàn)在事件發(fā)生時,此時內(nèi)核檢查接收進程的相關(guān)數(shù)據(jù)結(jié)構(gòu),此結(jié)構(gòu)中記錄了信號的布局,懸掛信號集和處理動作。如果信號是要被忽略的,內(nèi)核不做任何動作就返回。否則,將此信號加入懸掛信號集合中。(懸掛信號集合通常用位串表示,每位對應(yīng)一個信號,內(nèi)核無法記錄同一信號的多個實例)。

                   如果進程處于可中斷的睡眠狀態(tài),并且該信號非阻塞,內(nèi)核喚醒進程。被喚醒進程一旦運行則在返回用戶態(tài)前優(yōu)先處理懸掛信號,當有懸掛信號并且非阻塞時,內(nèi)核查看是否有處理句柄,如果沒有注冊句柄,則采取默認動作(通常為終止進程)。如果有句柄,則將此信號加入阻塞信號屏蔽中。

                   最后內(nèi)核安排進程返回到用戶態(tài)并執(zhí)行信號句柄,同時保證句柄執(zhí)行完時,進程從被中斷處代碼執(zhí)行。

                   由異步事件產(chǎn)生的信號可能在任一條指令后發(fā)生,當信號句柄完成時,進程從中斷之處起執(zhí)行。如果信號是在進程處于系統(tǒng)調(diào)用期間到達的,內(nèi)核通常abort此系統(tǒng)調(diào)用并返回錯誤碼EINTR

                   進程可以有選擇的阻塞信號交付,當一個被阻塞的信號生成時,如果進程指定的動作為默認或者捕獲,則此信號一直懸掛于該進程直到對此信號的阻塞放開,或者信號動作改為忽略。 系統(tǒng)對阻塞信號的判定是在信號交付時而非生成時,這樣可以允許進程在信號被交付前改變信號動作。

                   每個進程有一個阻塞信號屏蔽,它定義當前被阻塞交付的那些信號。可認為它是一個位串,每位對應(yīng)一個信號。如果某信號對應(yīng)的位被設(shè)置,則該信號當前阻塞,進程可調(diào)用

            sigprocmask函數(shù)來檢查或設(shè)置屏蔽。


             

            程序錯誤類信號:默認動作使進程流產(chǎn),產(chǎn)生core文件。

            SIGABRT   調(diào)用abort函數(shù)生成的信號。

            SIGFPE      浮點計算錯誤。

            SIGILL      非法指令錯誤。

            SIGBUS/SIGSEGV 硬件錯誤-非法地址訪問。

            SIGEMT    硬件錯誤

            SIGSYS:       非法系統(tǒng)調(diào)用。

            SIGTRAP   硬件錯誤(通常為斷點指令)。

             

            程序終止類信號:默認動作使進程終止,我們通常要處理這類信號,做一些清理工作,句柄函數(shù)應(yīng)在結(jié)束時為此信號指定默認動作,然后再次生成該信號,使得程序終止。

            SIGHUP:終端斷開連接時,生成此信號給控制進程。

            SIGINTCtrl-CDelete按下時,由終端驅(qū)動生成,并發(fā)送給前臺進程組中的所有進程。

            SIGKILL:使程序立即終止,不能被捕獲或忽略,也不能被阻塞。

            SIGQUITCtrl-\,SIGINT,并且產(chǎn)生core

            SIGTERM:該信號使程序終止,但是可以阻塞、捕獲、忽略。

             

            鬧鐘類信號:通知定時器到期,默認動作是終止程序,但通常會設(shè)置句柄。

            SIGALRMalarm/setitimer函數(shù)設(shè)置定時到期后,會產(chǎn)生此信號。

            SIGPROF

            SIGVTALRM

             

            I/O類信號:通知進程在描述字上發(fā)生了感興趣事件,支持信號驅(qū)動IO

            SIGIO fd準備執(zhí)行輸入輸出時發(fā)送此信號。

            SIGPOLL:異步I/O信號。

            SIGURG:網(wǎng)絡(luò)收到帶外數(shù)據(jù)時可選擇生成此信號。

             

            作業(yè)控制類信號:

            SIGCHLD   進程終止或停止時會向其父進程發(fā)送該信號,默認動作為忽略。

            SIGCONT:     使停止的進程恢復(fù)運行。

            SIGSTOP:      停止進程。

            SIGTSTP/SIGTTIN/SIGTTOU:

             

            操作錯誤類信號:默認動作終止程序。

            SIGPIPE    管道破裂。

            SIGXCPU/SIGXFSZ

             

            signal函數(shù):

            void (* signal(int sig, void (*func)(int)))(int);

            sig指明是哪一種信號。

            func指明動作:SIG_DFL SIG_IGN,或者信號句柄地址。

            當信號發(fā)生時,如果func指向信號句柄,系統(tǒng)在將控制轉(zhuǎn)往句柄前,先將該信號動作置為DFL,或者阻塞該信號直到句柄完成。

            Signal函數(shù)返回值指向前一次有效動作指針:SIG_DFL,SIG_IGN,或信號地址,這提供了恢復(fù)信號動作的機制。 如果signal調(diào)用出錯,返回SIG_ERR并設(shè)置errno

             

            進程初啟時的信號動作:

            fork:繼承父進程的動作

            exec:所有信號動作要么是忽略要么是默認。

             

            不可靠信號:

            早期版本Unix中使用signal,每當信號交付時,其動作總是由系統(tǒng)重置為默認動作,因此為了使信號句柄執(zhí)行期間,仍能對同一信號后續(xù)做反應(yīng),需要再次調(diào)用signal

            Catch_Signal(){

                   // 如果第二次信號剛好在此時發(fā)生,將導(dǎo)致進程終止core掉。

                   signal(SIGQUIT,Catch_Signal);

            }

            Main(){                   

                   signal(SIGQUIT, Catch_Signal);

                  

            }

            使用signal的另一個問題是,對于信號,進程要么忽略,要么捕獲,無法在一段時間內(nèi)阻塞信號(推遲信號的交付),為了克服signal兼容性問題,現(xiàn)代unix均實現(xiàn)了POSIX定義的sigaction函數(shù),該函數(shù)采用一個sigaction結(jié)構(gòu),除定義信號交付時要采取的動作外,還包含其他一些動作控制信息。

            sigaction還允許調(diào)用進程檢測或指定與特定信號相關(guān)的動作。

            int sigaction(int sig, const struct sigaction* act, struct sigaction* oact);

            sig指定信號-SIGKILLSIGSTOP

            如果actNULL,則不改變信號動作,只查詢當前動作。

            成功返回0,失敗則不安裝新信號動作,返回-1,設(shè)置errno

            struct sigaction{

                   void *sa_handler(int);                        // signal的第二參數(shù)func          

                   void (*sa_sigaction)(int, siginfo_t*, void*); // 僅當flags設(shè)置SA_SIGINFO起作用。

                   sigset_t sa_mask;    // 指明信號執(zhí)行期間要阻塞的一組信號,除此之外導(dǎo)致信號句柄執(zhí)

            行的信號也自動阻塞,除非指定了SA_NODEFER。信號句柄正常返回時,屏蔽恢復(fù)到原先狀態(tài)。          

                   int sa_flags;           //

            }

            sa_flags是一個位串,可以通過或運算生成。可設(shè)置下列標志:

            SA_NOCLDSTOP: 只對CHLD信號起作用,子進程暫停時不發(fā)信號給父進程。

            SA_RESTART: 信號句柄返回時,自動恢復(fù)被該信號中斷的系統(tǒng)調(diào)用。否則該系統(tǒng)調(diào)用將中斷返回-1,并設(shè)置errnoEINTR

            SA_ONSTACK:

            SA_RESETHAND:信號句柄入口,系統(tǒng)將重置信號動作為SIG_DFL.

            SA_NODEFER:句柄執(zhí)行期間,不自動阻塞該信號。

            SA_NOCLDWAIT:只對CHLD起作用,調(diào)用進程的所有子進程在終止時不會成為Zombe。這種情況下,父進程無需要wait子進程,并且子進程終止也不向父進程發(fā)SIGCHLD信號。

            如果父進程調(diào)用wait,將阻塞到所有子進程終止,并返回-1errno設(shè)為ECHILD.

            SA_SIGINFO:如果未設(shè)置此標志,則信號句柄原型為:

             void func(int signo);

            如果設(shè)置此標志,則句柄原型為:

            void func(int signo, singinfo_t* info, void* context);

            Info- 解釋信號生成的原因。

            Context-信號被交付時所中斷進程的上下文。

            一旦用sigaction為特定信號建立了動作,該動作就一直保持,直到另一次調(diào)用sigaction,或者調(diào)用exec,或者因設(shè)置了SA_RESETHAND導(dǎo)致系統(tǒng)自動改變動作為默認為止。

             

            除了外部中斷產(chǎn)生信號外,程序可以顯式的調(diào)用raise函數(shù)給他自己發(fā)送信號,或調(diào)用kill向自己或其他進程發(fā)送信號。

             

            阻塞信號意味著保持該信號并推遲它的交付,可以防止程序中的關(guān)鍵代碼被信號中斷。

            信號集操作:

            int sigemptyset(sigset_t* set); // 清空信號集

            int sigfillset(sigset_t* set);   // 包含所有信號集

            sigaddset/sigdelset/sigismember;

            sigprocmask用來檢測或改變調(diào)用進程的信號屏蔽。

            int sigprocmask(int how, const sigset_t* set, sigset_t* oset);

            How: SIGBLOCK SIG_UNBLOCK   SIG_SETMASK

            如果調(diào)用sigprocmask放開某個信號而導(dǎo)致任何懸掛信號被解除阻塞,則函數(shù)返回前,這些信號中至少有一個被交付。

            檢查懸掛信號:int sigpending(sigset_t* set);

            等待信號:int pause(void);

            懸掛調(diào)用進程直到有一個信號到達。僅當句柄執(zhí)行并返回時,pause函數(shù)才返回:此時返回-1,并設(shè)置errnoEINTR。所有其他情況下pause不返回。

             

            如果多個相同信號在信號句柄運行前發(fā)給了進程,則句柄只被運行一次。換句話說,默認情況下unix信號是非排隊的,只有當實現(xiàn)支持實時信號并且sa_flags設(shè)置SA_SIGINFO時,由sigqueue生成的后續(xù)信號才排隊。

             

            I/O執(zhí)行期間,有可能到達信號,此時有兩種情況:重新開始系統(tǒng)調(diào)用還是返回失敗.

            早期unix特征為,進程執(zhí)行慢系統(tǒng)調(diào)用期間捕獲信號時,該調(diào)用被中斷并設(shè)置errnoEINTR。現(xiàn)代unix增加了sa_flags選項SA_RESTART可對單個信號要求自動恢復(fù)被中斷的系統(tǒng)調(diào)用。

            原則如下:如果進程阻塞于慢系統(tǒng)調(diào)用,并且進程捕獲信號且該信號句柄返回,系統(tǒng)調(diào)用可能返回EINTR 雖然有些unix能自動恢復(fù)系統(tǒng)調(diào)用,但是為了兼容性,我們必須準備慢系統(tǒng)調(diào)用返回EINTR,當檢測到EINTR,要么重新開始系統(tǒng)調(diào)用,要么做其他處理。

            Again

                   if (n=read(fd,buff, BUFSIZE) < 0) {

                          if (errno ==EINTR)

                                 goto Again;

                          else

                                 …}

            posted @ 2008-06-30 09:19 powervv 閱讀(3384) | 評論 (0)編輯 收藏
            僅列出標題  
            日韩欧美亚洲综合久久| 99久久99久久精品国产| 2021国内久久精品| 久久久亚洲欧洲日产国码二区| www.久久热.com| 亚洲欧美久久久久9999 | 久久久久久a亚洲欧洲aⅴ| 国产亚洲综合久久系列| 国内精品久久久久久久影视麻豆| 亚洲精品成人网久久久久久| 久久天堂AV综合合色蜜桃网 | 热RE99久久精品国产66热| 久久中文字幕人妻熟av女| 久久青草国产精品一区| 免费无码国产欧美久久18| 97久久精品人人做人人爽| 久久综合给合久久国产免费| 久久97久久97精品免视看| 国产国产成人精品久久| 中文字幕日本人妻久久久免费| 99久久无码一区人妻| 一本一本久久a久久综合精品蜜桃 一本一道久久综合狠狠老 | 精品久久久久久中文字幕| 2021国内久久精品| 日本加勒比久久精品| 国产精品九九久久免费视频| 91久久精品91久久性色| 综合久久国产九一剧情麻豆| 久久综合九色综合网站| 久久天天躁狠狠躁夜夜不卡| 青青热久久综合网伊人| 99久久婷婷免费国产综合精品| 国产69精品久久久久9999APGF| 亚洲日韩欧美一区久久久久我| 久久人妻少妇嫩草AV无码蜜桃| 丁香久久婷婷国产午夜视频| 色综合久久久久| 久久精品国产黑森林| 久久久久这里只有精品 | 波多野结衣久久精品| 久久午夜无码鲁丝片秋霞 |