日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

《UNIX环境高级编程》笔记 第十章-信号

發(fā)布時(shí)間:2023/12/16 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《UNIX环境高级编程》笔记 第十章-信号 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1. 信號(hào)概念

信號(hào)是軟件中斷,提供了一種處理異步事件的方法。

Unix早期版本提供的是不可靠信號(hào),信號(hào)可能丟失。之后增加了可靠信號(hào)機(jī)制

每個(gè)信號(hào)都有一個(gè)名字,以3個(gè)字符SIG開頭。如SIGABRT是終止信號(hào),進(jìn)程調(diào)用abort函數(shù)產(chǎn)生這種信號(hào)。

  • SIGABRT信號(hào):

    void abort(void);

    abort()首先解除了對(duì)SIGABRT(6)信號(hào)的阻止和忽略,然后為調(diào)用進(jìn)程發(fā)送該信號(hào)(就像調(diào)用了 raise(SIGABRT)一樣)。 導(dǎo)致進(jìn)程的非正常終止,除非SIGABRT 信號(hào)被捕獲,并且信號(hào)處理函數(shù)沒有返回(調(diào)用exit、_exit、 _Exit、longjmp或siglongjmp使信號(hào)處理函數(shù)沒有返回)。

    如果abort()函數(shù)導(dǎo)致進(jìn)程終止,則關(guān)閉和刷新所有打開的文件流。

Linux支持63種信號(hào),不存在編號(hào)為0的信號(hào)(即為空信號(hào)),kill函數(shù)對(duì)信號(hào)編號(hào)0有特殊應(yīng)用。1 ~ 31的信號(hào)為傳統(tǒng)UNIX支持的信號(hào),是不可靠信號(hào)(非實(shí)時(shí)的),編號(hào)為32 ~ 63的信號(hào)是后來擴(kuò)充的,稱做可靠信號(hào)(實(shí)時(shí)信號(hào))。不可靠信號(hào)和可靠信號(hào)的區(qū)別在于前者不支持排隊(duì),可能會(huì)造成信號(hào)丟失,而后者不會(huì)。

1.1 產(chǎn)生信號(hào)條件

  • 當(dāng)用戶按某些終端鍵時(shí),引發(fā)終端產(chǎn)生的信號(hào)。如在終端上按delete或Ctrl+C鍵,通常產(chǎn)生中斷信號(hào)SIGINT。
  • 硬件產(chǎn)生異常信號(hào):除0、無效的內(nèi)存引用等。因?yàn)檫@些條件通常由硬件檢測到,并且通知內(nèi)核。然后內(nèi)核為該進(jìn)程產(chǎn)生適當(dāng)信號(hào)。
  • 進(jìn)程調(diào)用kill(2)函數(shù)將任意信號(hào)發(fā)送給另一個(gè)進(jìn)程或進(jìn)程組:接收信號(hào)進(jìn)程和發(fā)送信號(hào)進(jìn)程的所有者必須相同,或發(fā)送方必須是超級(jí)用戶root
  • 用kill(1)命令將信號(hào)(默認(rèn)是SIGTERM)發(fā)送給進(jìn)程
  • 當(dāng)檢測到某種軟件條件發(fā)生時(shí)將產(chǎn)生信號(hào)通知相關(guān)進(jìn)程。如SIGURG、SIGPIPE、SIGALRM(進(jìn)程設(shè)置的定時(shí)器已經(jīng)超時(shí))等

1.2 對(duì)信號(hào)的處理方式

  • 忽略此信號(hào)

    除了兩種信號(hào)SIGKILL和SIGSTOP絕對(duì)不能忽略以外,大多數(shù)信號(hào)都可使用這種方式處理。

    SIGKILL和SIGSTOP不能被忽略的原因是,它們向內(nèi)核和超級(jí)用戶提供了使進(jìn)程終止或停止的可靠方法(可以理解為終止、停止進(jìn)程的終極方法)。

    并且如果忽略某些由硬件異常(如除0、非法內(nèi)存引用)產(chǎn)生的信號(hào),會(huì)發(fā)生未定義行為。

  • 捕捉該信號(hào)

    通知內(nèi)核在某種信號(hào)發(fā)生時(shí),調(diào)用一個(gè)用戶函數(shù)。同樣SIGKILL和SIGSTOP不能被捕捉

  • 執(zhí)行系統(tǒng)默認(rèn)動(dòng)作

    對(duì)大多數(shù)信號(hào)的系統(tǒng)默認(rèn)動(dòng)作是終止該進(jìn)程

    Linux對(duì)各種信號(hào)的默認(rèn)動(dòng)作:

    注意“終止+core”表示在進(jìn)程當(dāng)前工作目錄的core文件中復(fù)制了該進(jìn)程內(nèi)存映像(默認(rèn)文件名為core,這種行為即coredump),大多數(shù)Unix系統(tǒng)調(diào)試程序(如gdb)都使用core文件檢查進(jìn)程終止時(shí)的狀態(tài)。

    注意"硬件故障"對(duì)應(yīng)于具體定義的硬件故障,需要通過對(duì)應(yīng)操作系統(tǒng)手冊(cè)查看這些信號(hào)對(duì)應(yīng)于哪些錯(cuò)誤

Core Dump

當(dāng)程序運(yùn)行的過程中異常終止或崩潰,操作系統(tǒng)會(huì)將程序當(dāng)時(shí)的內(nèi)存狀態(tài)記錄下來,保存在一個(gè)文件中,這種行為就叫做Core Dump(中文有的翻譯成“核心轉(zhuǎn)儲(chǔ)”)。我們可以認(rèn)為 core dump 是“內(nèi)存快照”,但實(shí)際上,除了內(nèi)存信息之外,還有些關(guān)鍵的程序運(yùn)行狀態(tài)也會(huì)同時(shí) dump 下來,例如寄存器信息(包括程序指針、棧指針等)、內(nèi)存管理信息、其他處理器和操作系統(tǒng)狀態(tài)和信息。core dump 對(duì)于編程人員診斷和調(diào)試程序是非常有幫助的,因?yàn)閷?duì)于有些程序錯(cuò)誤是很難重現(xiàn)的,例如指針異常,而 core dump 文件可以再現(xiàn)程序出錯(cuò)時(shí)的情景。

如果沒有進(jìn)行core dump 的相關(guān)設(shè)置,默認(rèn)是不開啟的。可以通過ulimit -c查看是否開啟。如果輸出為0,則沒有開啟,需要執(zhí)行ulimit -c unlimited開啟core dump功能。

不產(chǎn)生core文件的條件:

  • ulimit -c查看core文件有沒有限制大小。如果是0則說明禁止了core文件產(chǎn)生
  • 程序設(shè)置了用戶id(即調(diào)用setuid),但當(dāng)前用戶并非該程序文件的所有者
  • 程序設(shè)置了組id(即調(diào)用setgid),但當(dāng)前用戶并非該程序文件的組所有者
  • 用戶沒有當(dāng)前目錄或指定core文件產(chǎn)生目錄的寫權(quán)限
  • 文件已存在,用戶對(duì)該文件沒有寫權(quán)限
  • core文件太大,磁盤空間不足

2. 各種信號(hào)詳細(xì)信息

  • SIGABRT

    調(diào)用abort函數(shù)產(chǎn)生此信號(hào),進(jìn)程異常終止。

  • SIGALRM

    調(diào)用alarm、setitimer函數(shù)設(shè)置的定時(shí)器、間隔時(shí)間超時(shí)產(chǎn)生此信號(hào)。

  • SIGBUS

    表示發(fā)生了一個(gè)具體定義的硬件故障。當(dāng)出現(xiàn)某種類型內(nèi)存故障時(shí),常產(chǎn)生此種信號(hào)

  • SIGCHLD

    子進(jìn)程終止或停止時(shí),SIGCHLD信號(hào)發(fā)送給父進(jìn)程。系統(tǒng)默認(rèn)會(huì)忽略此信號(hào)。如果父進(jìn)程希望得知子進(jìn)程的這種狀態(tài)改變,那么通常在信號(hào)捕捉函數(shù)中調(diào)用wait等函數(shù)獲取子進(jìn)程pid及終止?fàn)顟B(tài)。

  • SIGCONT

    用于作業(yè)控制。如果收到此信號(hào)的進(jìn)程處于停止?fàn)顟B(tài),則系統(tǒng)默認(rèn)動(dòng)作是該進(jìn)程繼續(xù)運(yùn)行;否則忽略此信號(hào)

  • SIGEMT

    表示發(fā)生了一個(gè)具體定義的硬件故障。

  • SIGFPE

    算術(shù)運(yùn)算異常,如除0、浮點(diǎn)溢出等

  • SIGHUP:掛斷信號(hào)

    • 終端接口檢測到一個(gè)連接斷開,則將此信號(hào)送給與該終端相關(guān)的控制進(jìn)程(會(huì)話首進(jìn)程)。

    • session首進(jìn)程退出時(shí),該信號(hào)被發(fā)送到該session中的前臺(tái)進(jìn)程組和后臺(tái)進(jìn)程組中的每一個(gè)進(jìn)程

    • 若進(jìn)程的退出,導(dǎo)致一個(gè)進(jìn)程組變成了孤兒進(jìn)程組,新的孤兒進(jìn)程組中處于停止(stopped)狀態(tài)的每一個(gè)進(jìn)程都會(huì)收到掛斷(SIGHUP)信號(hào),接著又收到繼續(xù)(SIGCONT)信號(hào)。

    系統(tǒng)對(duì)SIGHUP信號(hào)的默認(rèn)處理是終止收到該信號(hào)的進(jìn)程。所以若程序中沒有捕捉該信號(hào),當(dāng)收到該信號(hào)時(shí),進(jìn)程就會(huì)退出。

  • SIGILL

    進(jìn)程執(zhí)行一條非法硬件指令

  • SIGINT:中斷信號(hào)

    用戶按中斷鍵(delete或Ctrl+C),產(chǎn)生此信號(hào)發(fā)送至前臺(tái)進(jìn)程組中的每一個(gè)進(jìn)程。當(dāng)一個(gè)進(jìn)程失控或者在終端產(chǎn)生大量不需要輸出時(shí),常通過此命令終止它。

  • SIGIO

    指示發(fā)生一個(gè)異步I/O事件。Linux中定義SIGIO與SIGPOLL有相同的值,默認(rèn)行為是終止該進(jìn)程。

    #define SIGIO SIGPOLL
  • SIGIOT

    表示發(fā)生了一個(gè)具體定義的硬件故障。Linux中定義SIGIOT與SIGABRT有相同值

    #define SIGIOT SIGABRT
  • SIGKILL:

    這是兩個(gè)不能被阻塞、捕捉或忽略的信號(hào)中的一個(gè),向內(nèi)核和超級(jí)用戶提供了使進(jìn)程終止的可靠方法

  • SIGPIPE

    管道讀進(jìn)程已經(jīng)終止后,寫進(jìn)程寫入管道產(chǎn)生此信號(hào)

    當(dāng)類型為SOCK_STREAM的socket已不再連接時(shí),進(jìn)程寫入該套接字也產(chǎn)生此信號(hào)。

  • SIGPOLL

    當(dāng)在一個(gè)可輪詢?cè)O(shè)備上發(fā)生一個(gè)特定事件時(shí)產(chǎn)生此信號(hào)(如當(dāng)系統(tǒng)發(fā)現(xiàn)有東西需要你讀的時(shí)候,就發(fā)個(gè)SIGPOLL信號(hào)來通知)。在未來可能將此信號(hào)移除。

  • SIGPROF

    setitimer函數(shù)設(shè)置的梗概統(tǒng)計(jì)間隔定時(shí)器超時(shí)產(chǎn)生此信號(hào)。在未來可能將此信號(hào)移除

  • SIGPWR

    電源故障信號(hào)。主要用于具有不間斷電源的系統(tǒng)。如果電源失效,系統(tǒng)依靠蓄電池繼續(xù)運(yùn)行。但是如果蓄電池也將不能工作,此時(shí)發(fā)送SIGPWR信號(hào)。通常是接到蓄電池電壓過低信息的進(jìn)程將SIGPWR發(fā)送給init進(jìn)程,然后由init處理停機(jī)操作。

    Linux對(duì)SIGPWR的默認(rèn)動(dòng)作是終止相關(guān)進(jìn)程。

  • SIGQUIT:退出信號(hào)

    用戶在終端上按退出鍵(Ctrl+\)產(chǎn)生此信號(hào),并發(fā)送給前臺(tái)進(jìn)程組的所有進(jìn)程。磁信號(hào)不僅終止前臺(tái)進(jìn)程組,還產(chǎn)生一個(gè)core文件。

  • SIGSEGV

    進(jìn)程進(jìn)行了一次無效的內(nèi)存引用(比如訪問了一個(gè)未經(jīng)初始化的指針),或發(fā)生段錯(cuò)誤

  • SIGSTOP

    作業(yè)控制信號(hào),它停止一個(gè)進(jìn)程。同SIGKILL,該信號(hào)不能被阻塞、忽略和捕獲

  • SIGSYS

    指示一個(gè)無效的系統(tǒng)調(diào)用

  • SIGTERM

    是kill命令發(fā)出的默認(rèn)信號(hào)(系統(tǒng)默認(rèn)終止信號(hào))。相比于SIGKILL,SIGTERM可以被捕獲或忽略,因此允許讓程序有機(jī)會(huì)在退出之前做好清理工作,從而優(yōu)雅地終止。

  • SIGTRAP

    表示發(fā)生了一個(gè)具體定義的硬件故障。通常使用此信號(hào)將控制轉(zhuǎn)移至調(diào)試程序

  • SIGTSTP

    交互停止信號(hào)。當(dāng)用戶在終端按掛起鍵(Ctrl+Z)時(shí),將該信號(hào)發(fā)送到前臺(tái)進(jìn)程組中的所有進(jìn)程。 SIGTSTP與SIGSTOP都是使進(jìn)程暫停(都使用SIGCONT讓進(jìn)程重新激活)。唯一的區(qū)別是SIGSTOP不可以捕獲和忽略,而SIGTSTP可以。

  • SIGTTIN

    當(dāng)一個(gè)后臺(tái)進(jìn)程組中的進(jìn)程試圖讀控制終端時(shí)收到此信號(hào),并使該進(jìn)程暫停。注意,如果讀進(jìn)程屬于孤兒進(jìn)程組,那么read控制終端操作返回出錯(cuò),不產(chǎn)生此信號(hào),errno設(shè)置為EIO。

  • SIGTTOU

    如果禁止后臺(tái)作業(yè)向控制終端寫,此時(shí)當(dāng)一個(gè)后臺(tái)進(jìn)程組進(jìn)程試圖寫控制終端時(shí)收到此信號(hào),并使該進(jìn)程暫停。注意,如果寫進(jìn)程屬于孤兒進(jìn)程組,則寫操作返回出錯(cuò),不產(chǎn)生此信號(hào),errno設(shè)置為EIO。

    除此之外,tcsetattr、tcsendbreak、tcdrain、tcflush、tcflow以及tcsetpgrp也能產(chǎn)生SIGTTOU信號(hào)。

  • SIGURG

    通知進(jìn)程發(fā)生一個(gè)緊急情況(用于socket編程)。在網(wǎng)絡(luò)連接上接到帶外的數(shù)據(jù)時(shí),可選擇地產(chǎn)生此信號(hào)。

    帶外數(shù)據(jù):
    帶外數(shù)據(jù)用于迅速告知對(duì)方本端發(fā)生的重要的事件。它比普通的數(shù)據(jù)(帶內(nèi)數(shù)據(jù))擁有更高的優(yōu)先級(jí),不論發(fā)送緩沖區(qū)中是否有排隊(duì)等待發(fā)送的數(shù)據(jù),它總是被立即發(fā)送。帶外數(shù)據(jù)的傳輸可以使用一條獨(dú)立的傳輸層連接,也可以映射到傳輸普通數(shù)據(jù)的連接中。

  • SIGUSR1

    用戶定義的信號(hào)

  • SIGUSR2

    另一個(gè)用戶定義的信號(hào),與SIGUSR類似

  • SIGVTALRM

    當(dāng)一個(gè)由setitimer函數(shù)設(shè)置的虛擬間隔時(shí)間超時(shí)產(chǎn)生此信號(hào)

  • SIGWINCH

    內(nèi)核維護(hù)與每個(gè)終端或偽終端相關(guān)聯(lián)窗口的大小。進(jìn)程可以用ioctl得到或設(shè)置窗口大小。如果用ioctl設(shè)置窗口大小命令更改了窗口大小,則內(nèi)核將該信號(hào)發(fā)送至前臺(tái)進(jìn)程組

  • SIGXCPU

    如果進(jìn)程超過其軟CPU時(shí)間限制,產(chǎn)生此信號(hào)。

  • SIGXFSZ

    如果進(jìn)程超過其軟文件長度限制,產(chǎn)生此信號(hào)。

3. signal函數(shù)

設(shè)置調(diào)用進(jìn)程收到指定信號(hào)時(shí)的動(dòng)作(忽略、使用系統(tǒng)默認(rèn)動(dòng)作或捕獲)

typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler);
  • signum參數(shù):信號(hào)名,如SIGABRT

  • handler參數(shù):

    • SIG_IGN:忽略此信號(hào)(不能用于SIGKILL和SIGSTOP)

      #define SIG_IGN ((__sighandler_t) 1) /* Ignore signal. */
    • SIG_DFL:系統(tǒng)默認(rèn)動(dòng)作

      #define SIG_DFL ((__sighandler_t) 0) /* Default action. */
    • 指定函數(shù)地址(不能用于SIGKILL和SIGSTOP):在信號(hào)發(fā)生時(shí),調(diào)用該函數(shù)(該函數(shù)有一個(gè)int形參,即為該信號(hào)編號(hào))。稱這個(gè)操作是捕捉該信號(hào),稱此函數(shù)為信號(hào)處理程序或信號(hào)捕捉函數(shù)。

  • 返回值:返回之前的信號(hào)處理程序的地址,當(dāng)發(fā)生錯(cuò)誤時(shí)返回 SIG_ERR

    #define SIG_ERR ((__sighandler_t) -1) /* Error return. */

signal函數(shù)的一些特點(diǎn):

  • 注意,exec一個(gè)程序后,通常所有信號(hào)的處理都是忽略或者使用系統(tǒng)默認(rèn)操作。如果調(diào)用exec前對(duì)某個(gè)信號(hào)忽略,則exec后仍為忽略;但是如果調(diào)用exec前對(duì)某個(gè)信號(hào)捕獲,則exec后對(duì)該信號(hào)更改為使用默認(rèn)操作(因?yàn)樾盘?hào)捕捉函數(shù)的地址在exec的新程序中毫無意義)。

  • 當(dāng)fork時(shí),子進(jìn)程繼承父進(jìn)程的信號(hào)處理方式,因?yàn)樽舆M(jìn)程復(fù)刻父進(jìn)程內(nèi)存映像,因此信號(hào)捕捉函數(shù)地址在子進(jìn)程中有效

  • signal函數(shù)的一個(gè)缺陷

    不改變信號(hào)的處理方式就不能確定信號(hào)之前的處理方式(根據(jù)signal返回值知道之前對(duì)于指定信號(hào)的處理方式)。因此可以使用sigaction函數(shù)確定一個(gè)信號(hào)的處理方式,而無需改變它

4. 不可靠信號(hào)

https://blog.csdn.net/u013074465/article/details/45978755

在早期UNIX中,信號(hào)是不可靠的。意為信號(hào)可能會(huì)丟失,一個(gè)信號(hào)發(fā)生了但是進(jìn)程可能一直不知道。同時(shí)不具備阻塞信號(hào)的能力(不要忽略該信號(hào),在其發(fā)生時(shí)記住它,然后在進(jìn)程做好準(zhǔn)備時(shí)再通知它)。

不可靠信號(hào)的主要問題:

  • 進(jìn)程每次處理信號(hào)后,就將對(duì)信號(hào)的響應(yīng)設(shè)置為默認(rèn)動(dòng)作。在某些情況下,將導(dǎo)致對(duì)信號(hào)的錯(cuò)誤處理;因此,用戶如果不希望這樣的操作,那么就要在信號(hào)處理函數(shù)結(jié)尾再一次調(diào)用signal(),重新安裝該信號(hào)。
  • 信號(hào)可能丟失,如果在進(jìn)程對(duì)某個(gè)信號(hào)進(jìn)行處理時(shí),這個(gè)信號(hào)發(fā)生多次,對(duì)后到來的這類信號(hào)不排隊(duì),那么僅傳送該信號(hào)一次,即發(fā)生了信號(hào)丟失。
    因此,早期unix下的不可靠信號(hào)主要指的是進(jìn)程可能對(duì)信號(hào)做出錯(cuò)誤的反應(yīng)以及信號(hào)可能丟失。

Linux支持不可靠信號(hào),但是對(duì)不可靠信號(hào)機(jī)制做了改進(jìn):在調(diào)用完信號(hào)處理函數(shù)后,不必重新調(diào)用該信號(hào)的安裝函數(shù)(信號(hào)安裝函數(shù)是在可靠機(jī)制上的實(shí)現(xiàn))。因此,Linux下的不可靠信號(hào)問題主要指的是信號(hào)可能丟失

5. 中斷的系統(tǒng)調(diào)用

系統(tǒng)調(diào)用分類:

將系統(tǒng)調(diào)用分為兩類 -> 低速系統(tǒng)調(diào)用/其他系統(tǒng)調(diào)用

低速系統(tǒng)調(diào)用是可能會(huì)使進(jìn)程永遠(yuǎn)阻塞的一類系統(tǒng)調(diào)用:

  • 如果某些類型文件(如讀管道、終端設(shè)備、網(wǎng)絡(luò)設(shè)備)數(shù)據(jù)不存在,則讀操作可能會(huì)使調(diào)用者永遠(yuǎn)阻塞
  • 如果這些數(shù)據(jù)不能被相同類型文件立即接受,則寫操作可能會(huì)使調(diào)用者永遠(yuǎn)阻塞。
  • 在某種條件發(fā)生之前打開某些類型文件,可能發(fā)生阻塞
  • pause函數(shù)(它使進(jìn)程掛起直到收到一個(gè)信號(hào))和wait函數(shù)
  • 某些ioctl操作
  • 某些進(jìn)程間通信函數(shù)

在早期UNIX中,如果進(jìn)程正在執(zhí)行低速系統(tǒng)調(diào)用而阻塞期間捕捉到一個(gè)信號(hào),則該系統(tǒng)調(diào)用就被中斷不再執(zhí)行。該系統(tǒng)調(diào)用返回出錯(cuò),其errno設(shè)置為EINTR(系統(tǒng)調(diào)用被中斷)。可以理解為一個(gè)信號(hào)發(fā)生了,進(jìn)程捕捉到它,這意味著已經(jīng)發(fā)生了某種事情,所以是個(gè)好機(jī)會(huì)應(yīng)當(dāng)喚醒阻塞的系統(tǒng)調(diào)用。

對(duì)于處理已經(jīng)read/write部分?jǐn)?shù)據(jù)量的相應(yīng)系統(tǒng)調(diào)用,此時(shí)被信號(hào)中斷,有兩種方式(例如read系統(tǒng)調(diào)用已經(jīng)接收并傳送數(shù)據(jù)至應(yīng)用程序緩沖區(qū),但尚未接收到應(yīng)用程序請(qǐng)求的全部數(shù)據(jù)):

  • 認(rèn)為系統(tǒng)調(diào)用失敗,errno設(shè)置為EINTR
  • (現(xiàn)在使用這一種):允許該系統(tǒng)調(diào)用成功返回,返回值是已讀寫的數(shù)據(jù)量。

當(dāng)被信號(hào)中斷時(shí),下列系統(tǒng)調(diào)用支持自動(dòng)重啟動(dòng)

ioctl、read、readv、write、writev、wait和waitpid

有些應(yīng)用程序不希望這些函數(shù)被中斷后自動(dòng)重啟動(dòng),因此進(jìn)程可以設(shè)置對(duì)每個(gè)信號(hào)禁用此功能。(sigaction函數(shù)中只有中斷信號(hào)的SA_RESTART標(biāo)志有效,才自動(dòng)重啟動(dòng)系統(tǒng)調(diào)用)在Linux中,當(dāng)信號(hào)處理程序是用signal函數(shù)注冊(cè)時(shí),被中斷的系統(tǒng)調(diào)用會(huì)自動(dòng)重啟動(dòng)

注意,除了低速系統(tǒng)調(diào)用,信號(hào)也可以中斷類似sleep這樣的函數(shù):調(diào)用sleep函數(shù)的線程休眠seconds秒如果中間有一個(gè)未被忽略的信號(hào)到達(dá)則終止休眠

6. 可重入函數(shù)

  • 如果進(jìn)程正在執(zhí)行malloc,在其堆中分配另外的存儲(chǔ)空間,而此時(shí)由于捕捉到信號(hào)而插入執(zhí)行該信號(hào)處理程序,其中又調(diào)用malloc會(huì)發(fā)生什么?

    可能會(huì)對(duì)進(jìn)程造成破壞。因?yàn)閙alloc通常為它所分配的存儲(chǔ)區(qū)維護(hù)一個(gè)鏈表,而插入執(zhí)行信號(hào)處理程序時(shí)進(jìn)程可能正在更改此鏈表。

  • **如果進(jìn)程正在執(zhí)行g(shù)etpwnam這種將其結(jié)果存放在靜態(tài)存儲(chǔ)單元中的函數(shù),其間插入執(zhí)行信號(hào)處理程序,它又調(diào)用這樣的函數(shù)(如信號(hào)處理函數(shù)內(nèi)部又調(diào)用getpwnam)**會(huì)發(fā)生什么?

    返回給正常調(diào)用者的信息可能會(huì)被返回給信號(hào)處理程序的信息覆蓋

可重入函數(shù):

在信號(hào)處理程序中保證調(diào)用安全的函數(shù),這些函數(shù)是可重入的并被稱為是異步信號(hào)安全的(即為在函數(shù)A執(zhí)行期間中斷執(zhí)行信號(hào)處理程序,在信號(hào)處理程序中可能再次調(diào)用函數(shù)A,但是不會(huì)造成問題)。這種函數(shù)除了可重入外(信號(hào)處理程序中再次調(diào)用被信號(hào)中斷的函數(shù)),在執(zhí)行信號(hào)處理操作期間會(huì)阻塞任何會(huì)引起不一致的信號(hào)發(fā)送

下列函數(shù)都是異步信號(hào)安全即可重入的:

沒有列入上表的函數(shù)大多是不可重入的,不可重入函數(shù)通常有以下特點(diǎn)

  • 它們使用靜態(tài)數(shù)據(jù)結(jié)構(gòu),重入可能導(dǎo)致結(jié)果被覆蓋
  • 它們調(diào)用malloc或free
  • 它們是標(biāo)準(zhǔn)I/O函數(shù)。標(biāo)準(zhǔn)I/O庫的很多實(shí)現(xiàn)都不以可重入方式而是使用全局?jǐn)?shù)據(jù)結(jié)構(gòu)

并且要注意,對(duì)于errno,因?yàn)樾盘?hào)處理程序可能會(huì)修改errno原先值,因此應(yīng)當(dāng)在調(diào)用前保存errno,在調(diào)用后恢復(fù)errno

如果應(yīng)用程序要做更新全局?jǐn)?shù)據(jù)結(jié)構(gòu)這樣的事情,而同時(shí)要捕捉某些信號(hào),而這些信號(hào)的處理程序又會(huì)引起執(zhí)行siglongjmp,則在更新這種數(shù)據(jù)結(jié)構(gòu)時(shí)要阻塞此類信號(hào)。(因?yàn)榭赡軐?dǎo)致這些全局?jǐn)?shù)據(jù)結(jié)構(gòu)是部分更新的)

綜上所述,在信號(hào)處理函數(shù)中調(diào)用一個(gè)非可重入函數(shù),其結(jié)果不可預(yù)知。因此在信號(hào)處理函數(shù)中不能調(diào)用非可重入函數(shù)

7. 多線程中的信號(hào)處理

使用了多線程后,便有些疑問:

  • 信號(hào)發(fā)生時(shí),哪個(gè)線程會(huì)收到
  • 是不是每個(gè)線程都有自己的mask及action
  • 每個(gè)線程能按自己的方式處理信號(hào)么
  • 對(duì)于以上問題,結(jié)論是:

    • 如果是異常產(chǎn)生的信號(hào)(比如程序錯(cuò)誤,像SIGPIPE、SIGEGV這些),則只有產(chǎn)生異常的線程收到并處理
    • 如果是用pthread_kill產(chǎn)生的內(nèi)部信號(hào),則只有pthread_kill參數(shù)中指定的目標(biāo)線程收到并處理
    • 如果是外部使用kill命令產(chǎn)生的信號(hào),通常是SIGINT、SIGHUP等job control信號(hào),則會(huì)遍歷所有線程,直到找到一個(gè)不阻塞該信號(hào)的線程,然后調(diào)用它來處理。(一般從主線程找起),注意只有一個(gè)線程能收到
    • 其次,每個(gè)線程都有自己獨(dú)立的signal mask,但所有線程共享進(jìn)程的signal action。這意味著,你可以在線程中調(diào)用pthread_sigmask(不是sigmask)來決定本線程阻塞哪些信號(hào)。但你不能調(diào)用sigaction來指定單個(gè)線程的信號(hào)處理方式。如果在某個(gè)線程中調(diào)用了sigaction處理某個(gè)信號(hào),那么這個(gè)進(jìn)程中的未阻塞這個(gè)信號(hào)的線程在收到這個(gè)信號(hào)都會(huì)按同一種方式處理這個(gè)信號(hào)。另外,注意子線程的mask是會(huì)從主線程繼承而來的

    8. 可靠信號(hào)

    8.1 三種信號(hào)狀態(tài)

    **信號(hào)產(chǎn)生:**generation

    當(dāng)造成信號(hào)的事件發(fā)生時(shí),為進(jìn)程產(chǎn)生一個(gè)信號(hào)(或向一個(gè)進(jìn)程發(fā)送一個(gè)信號(hào))。

    這些造成信號(hào)的事件可以是硬件異常(如除0)、軟件條件(如alarm定時(shí)器超時(shí))、終端產(chǎn)生的信號(hào)或調(diào)用kill函數(shù)。

    當(dāng)一個(gè)信號(hào)產(chǎn)生時(shí),內(nèi)核通常在進(jìn)程中以某種形式設(shè)置一個(gè)標(biāo)志。

    **信號(hào)遞送:**delivery

    指信號(hào)發(fā)送給進(jìn)程之后,對(duì)該信號(hào)進(jìn)行了處理(無論是忽略、捕獲還是使用系統(tǒng)默認(rèn)操作)

    **信號(hào)未決:**pending

    在信號(hào)產(chǎn)生和遞送的時(shí)間間隔內(nèi)稱為未決

    8.2 阻塞信號(hào)遞送:

    進(jìn)程可以選擇對(duì)指定信號(hào)“阻塞信號(hào)遞送”。如果為進(jìn)程產(chǎn)生了一個(gè)阻塞的信號(hào),并且對(duì)該信號(hào)的動(dòng)作是系統(tǒng)默認(rèn)或捕捉,則此信號(hào)保持為未決的。直到該進(jìn)程解除對(duì)此信號(hào)的阻塞,或者將對(duì)此信號(hào)的動(dòng)作更改為忽略,內(nèi)核才會(huì)遞送一個(gè)原來被阻塞的信號(hào)給進(jìn)程(而不是解除阻塞后再產(chǎn)生的信號(hào))。

    如果在進(jìn)程解除對(duì)某個(gè)信號(hào)的阻塞之前這種信號(hào)發(fā)生了多次,允許系統(tǒng)能夠遞送該信號(hào)一次或多次。如果遞送該信號(hào)多次,則稱這些信號(hào)進(jìn)行了排隊(duì)

    8.3 信號(hào)屏蔽字:

    每個(gè)進(jìn)程都有信號(hào)屏蔽字(signal mask),它規(guī)定當(dāng)前要阻塞遞送到該進(jìn)程的信號(hào)集。對(duì)于每一種可能的信號(hào),該屏蔽字中都有一位與之對(duì)應(yīng)。如果該位已設(shè)置,則它對(duì)應(yīng)的信號(hào)是被阻塞的。

    注意,在信號(hào)處理函數(shù)被調(diào)用時(shí),操作系統(tǒng)建立的新信號(hào)屏蔽字包含正被遞送的信號(hào)(即觸發(fā)本次捕獲的信號(hào)),信號(hào)處理函數(shù)返回時(shí)再恢復(fù)信號(hào)屏蔽字。因此保證在處理一個(gè)給定信號(hào)時(shí),如果該信號(hào)再次發(fā)生,那么它將被阻塞到前一個(gè)信號(hào)的處理結(jié)束為止

    9. kill和raise函數(shù)

    kill函數(shù)將信號(hào)發(fā)送給進(jìn)程或進(jìn)程組,raise函數(shù)向進(jìn)程自身發(fā)送信號(hào)

    int kill(pid_t pid, int sig); int raise(int sig);

    kill的pid參數(shù):

    • pid > 0 :將信號(hào)發(fā)送給指定進(jìn)程
    • pid == 0 : 將信號(hào)發(fā)送給與發(fā)送進(jìn)程屬于同一進(jìn)程組的所有進(jìn)程,并且發(fā)送進(jìn)程具有權(quán)限向這些進(jìn)程發(fā)送信號(hào)
    • pid < 0 : 將信號(hào)發(fā)送給進(jìn)程組ID等于pid絕對(duì)值的所有進(jìn)程,并且發(fā)送進(jìn)程具有權(quán)限向這些進(jìn)程發(fā)送信號(hào)
    • pid == -1 : 將信號(hào)發(fā)送給有權(quán)限向它們發(fā)送的所有進(jìn)程。除了進(jìn)程1(init)

    如果sig==0,則說明是空信號(hào),kill仍然執(zhí)行正常的錯(cuò)誤檢查但是不發(fā)送信號(hào)。常被用來確定一個(gè)特定進(jìn)程是否存在。如果向一個(gè)不存在的進(jìn)程發(fā)送空信號(hào),kill函數(shù)返回-1。

    發(fā)送信號(hào)的權(quán)限問題:

    • 超級(jí)用戶可以把信號(hào)發(fā)送給任一進(jìn)程
    • 非超級(jí)用戶,則要求發(fā)送的實(shí)際用戶ID或有效用戶ID等于接受者的實(shí)際用戶ID或有效用戶ID。
    • 但是有一個(gè)特例:對(duì)于SIGCONT信號(hào),則進(jìn)程可以將它發(fā)送給屬于同一會(huì)話的任一進(jìn)程

    如果調(diào)用kill為調(diào)用進(jìn)程產(chǎn)生信號(hào),并且如果該信號(hào)是不被阻塞的,那么在kill函數(shù)返回之前,該信號(hào)或者其他某個(gè)未決、未阻塞信號(hào)就被遞送給了該進(jìn)程

    10. alarm和pause函數(shù)

    alarm函數(shù)設(shè)置一個(gè)定時(shí)器(秒數(shù)),將來某個(gè)時(shí)刻定時(shí)器超時(shí)產(chǎn)生SIGALRM信號(hào)。如果忽略或不捕捉該信號(hào),默認(rèn)動(dòng)作是終止該進(jìn)程

    unsigned int alarm(unsigned int seconds);
    • 注意,每個(gè)進(jìn)程只能有一個(gè)鬧鐘時(shí)間,因此調(diào)用alarm會(huì)覆蓋之前的alarm。即如果在調(diào)用alarm時(shí)上一次為該進(jìn)程注冊(cè)的alarm還沒有超時(shí),則該鬧鐘時(shí)間的余留值用作本次調(diào)用的返回值,并且以前注冊(cè)的鬧鐘時(shí)間被新值替代

    • 如果要捕獲SIGALRM,必須在alarm調(diào)用前安裝信號(hào)捕獲程序。

    pause函數(shù)是一個(gè)慢速系統(tǒng)調(diào)用,使調(diào)用進(jìn)程掛起直到捕捉到一個(gè)信號(hào)

    int pause(void);

    只有執(zhí)行了信號(hào)處理程序并從其返回時(shí),pause才返回。此時(shí)pause返回-1,errno設(shè)置為EINTR

    • 注意,在信號(hào)處理函數(shù)中使用longjmp函數(shù)一定要小心,因?yàn)槿绻撔盘?hào)中斷了其他信號(hào)處理函數(shù),那么longjmp將會(huì)提早終止這些信號(hào)處理函數(shù)。

    11. 信號(hào)集

    使用sigset_t以包含一個(gè)信號(hào)集,該數(shù)據(jù)類型能夠表示多個(gè)信號(hào)的集合,該數(shù)據(jù)類型會(huì)被sigprocmask等函數(shù)使用

    int sigemptyset(sigset_t *set); int sigfillset(sigset_t *set); int sigaddset(sigset_t *set, int signum); int sigdelset(sigset_t *set, int signum); int sigismember(const sigset_t *set, int signum);
    • sigemptyset:

      初始化set指向的信號(hào)集,清除其中所有信號(hào)

    • sigfillset:

      初始化set指向的信號(hào)集,使其置位所有信號(hào)

    • 注意,所有應(yīng)用程序在使用信號(hào)集前,都要對(duì)該信號(hào)集數(shù)據(jù)結(jié)構(gòu)調(diào)用sigemptyset或者sigfillset

    • sigaddset:

      在set指向的信號(hào)集中添加指定信號(hào)signum

    • sigdelset:

      在set指向的信號(hào)集中刪除指定信號(hào)signum

    • sigismember:

      判斷set信號(hào)集中是否有信號(hào)signum

    12. sigprocmask函數(shù)

    信號(hào)屏蔽字:

    阻塞而不能遞送給該進(jìn)程的信號(hào)集。可以通過sigprocmask函數(shù)檢測、更改進(jìn)程的信號(hào)屏蔽字

    int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
    • 若oldset非空,那么進(jìn)程之前的信號(hào)屏蔽字通過oldset返回。

    • 若set非空,則how指示如何根據(jù)set修改當(dāng)前信號(hào)屏蔽字

    • how參數(shù):

      • SIG_BLOCK:阻塞信號(hào),即之前的信號(hào)集和set做按位或操作,即并集。set包含了希望被阻塞的信號(hào)
      • SIG_UNBLOCK:解除信號(hào)阻塞,即和set的補(bǔ)集求交集。set包含了希望被解除阻塞的信號(hào)
      • SIG_SETMASK:賦值信號(hào)屏蔽字
    • 在調(diào)用該函數(shù)后如果有任何未決的、不再阻塞的信號(hào),則在函數(shù)返回之前,至少將其中之一遞送給該進(jìn)程

    13. sigpending函數(shù)(未決的信號(hào))

    sigpending函數(shù)返回一個(gè)信號(hào)集,以指示當(dāng)前處于未決狀態(tài)的信號(hào)(即已經(jīng)產(chǎn)生但是由于被阻塞而不能遞送的信號(hào))

    int sigpending(sigset_t *set);

    14. sigaction函數(shù)(信號(hào)action動(dòng)作)

    檢查、修改指定信號(hào)的處理動(dòng)作。此函數(shù)用于取代UNIX早期版本使用的signal函數(shù)

    int sigaction(int signo, const struct sigaction *act, struct sigaction *oldact);

    若act指針非空,則表示要修改其動(dòng)作。如果oldact非空,則通過該參數(shù)返回指定信號(hào)的上一個(gè)動(dòng)作

    struct sigaction {void (*sa_handler)(int);void (*sa_sigaction)(int, siginfo_t *, void *);sigset_t sa_mask;int sa_flags;void (*sa_restorer)(void); };
    • sa_handler:信號(hào)捕捉函數(shù)地址,可以是 SIG_DFL 表示默認(rèn)動(dòng)作,SIG_IGN 表示忽略此信號(hào)

    • sa_mask:

      一個(gè)信號(hào)集,在調(diào)用該信號(hào)捕捉函數(shù)之前,這一信號(hào)集要加到進(jìn)程的信號(hào)屏蔽字中。僅當(dāng)從信號(hào)捕捉函數(shù)返回時(shí)再將進(jìn)程的信號(hào)屏蔽字恢復(fù)為原來值

      注意,在信號(hào)處理函數(shù)被調(diào)用時(shí),操作系統(tǒng)建立的新信號(hào)屏蔽字包含正被遞送的信號(hào)(即觸發(fā)本次捕獲的信號(hào)),信號(hào)處理函數(shù)返回時(shí)再恢復(fù)信號(hào)屏蔽字。因此保證在處理一個(gè)給定信號(hào)時(shí),如果該信號(hào)再次發(fā)生,那么它將被阻塞到前一個(gè)信號(hào)的處理結(jié)束為止

    • sa_flags:

      對(duì)指定信號(hào)進(jìn)行處理的各個(gè)選項(xiàng)

      • SA_INTERRUPT:由此信號(hào)中斷的系統(tǒng)調(diào)用不自動(dòng)重啟動(dòng)
      • SA_NOCLDSTOP:如果 signo 是 SIGCHLD,則在子進(jìn)程停止時(shí)不產(chǎn)生此信號(hào);在子進(jìn)程終止時(shí)仍產(chǎn)生此信號(hào)
      • SA_NOCLDWAIT:如果 signo 是 SIGCHLD,則調(diào)用進(jìn)程的子進(jìn)程終止時(shí)不會(huì)變成僵尸進(jìn)程(不會(huì)發(fā)出SIGCHLD信號(hào))
      • SA_NODEFER:當(dāng)捕捉到此信號(hào)時(shí),在執(zhí)行其信號(hào)捕捉函數(shù)時(shí),系統(tǒng)不自動(dòng)阻塞此信號(hào)(除非sa_mask中包含此信號(hào))。
      • SA_RESETHAND:在進(jìn)入信號(hào)處理程序時(shí),將該信號(hào)處理方式設(shè)置為SIG_DFL,并清除SA_SIGINFO標(biāo)志
      • SA_RESTART:由此信號(hào)中斷的系統(tǒng)調(diào)用自動(dòng)重啟動(dòng)
      • SA_SIGINFO:此選項(xiàng)對(duì)信號(hào)處理程序提供了附加信息,即使用sa_sigaction信號(hào)處理程序而不是sa_handler
    • sa_sigaction:

      一個(gè)替代的信號(hào)處理程序。當(dāng)該信號(hào)使用了SA_SIGINFO標(biāo)志時(shí),使用該信號(hào)處理程序。由于sa_handler和sa_sigaction的實(shí)現(xiàn)可能共用同一存儲(chǔ)區(qū),因此這兩個(gè)字段只能有一個(gè)。

      之前信號(hào)處理函數(shù)是以下形式:

      void handler(int signo);

      若設(shè)置了SA_SIGINFO標(biāo)志,則信號(hào)處理函數(shù)是以下形式

      void handler(int signo, siginfo_t *info, void *context);
      • 其中第二個(gè)參數(shù)siginfo_t結(jié)構(gòu)體包含了信號(hào)產(chǎn)生原因的有關(guān)信息,這樣在信號(hào)處理函數(shù)中我們就可以通過第二個(gè)參數(shù)知道更多具體與該信號(hào)相關(guān)的信息。其應(yīng)該至少包含以下字段

        siginfo_t {int si_signo; /* Signal number */int si_errno; /* An errno value */int si_code; /* 發(fā)出信號(hào)具體原因 */pid_t si_pid; /* Sending process ID */uid_t si_uid; /* Real user ID of sending process */int si_status; /* Exit value or signal */sigval_t si_value; /* Signal value */void *si_addr; /* Memory location which caused fault */... }

        其中si_code即為信號(hào)發(fā)生具體原因:

    • 第三個(gè)參數(shù)context可以被強(qiáng)制類型轉(zhuǎn)換為ucontext_t類型,該結(jié)構(gòu)體標(biāo)識(shí)信號(hào)傳遞時(shí)進(jìn)程上下文,該ucontext_t結(jié)構(gòu)至少包含以下字段

      typedef struct ucontext_t{struct ucontext_t *uc_link;stack_t uc_stack;mcontext_t uc_mcontext;sigset_t uc_sigmask;...} ucontext_t;
      • uc_link:為當(dāng)前context執(zhí)行結(jié)束之后要執(zhí)行的下一個(gè)context,若uc_link為空,執(zhí)行完當(dāng)前context之后退出程序。
      • uc_sigmask : 執(zhí)行當(dāng)前上下文過程中需要阻塞的信號(hào)列表,即信號(hào)屏蔽字
      • uc_stack : 為當(dāng)前context運(yùn)行的棧信息。
      • uc_mcontext : 保存具體的程序執(zhí)行上下文,如PC值,堆棧指針以及寄存器值等信息。它的實(shí)現(xiàn)依賴于底層,是平臺(tái)硬件相關(guān)的。此實(shí)現(xiàn)不透明

    注意,對(duì)于支持實(shí)時(shí)信號(hào)擴(kuò)展的系統(tǒng),用SA_SIGINFO標(biāo)志建立的信號(hào)處理程序?qū)⒃斐尚盘?hào)可靠排隊(duì)

    • 注意,相較于signal(被指定信號(hào)中斷的系統(tǒng)調(diào)用默認(rèn)自動(dòng)重啟動(dòng)),如果信號(hào)處理程序使用sigaction指定,那么被該信號(hào)中斷的系統(tǒng)調(diào)用默認(rèn)不重新啟動(dòng)(可以通過SA_RESTART標(biāo)志重啟動(dòng)被中斷的系統(tǒng)調(diào)用)

    15. sigsetjmp和siglongjmp函數(shù)

    系統(tǒng)在進(jìn)入信號(hào)處理程序時(shí),會(huì)將該信號(hào)自動(dòng)加入到信號(hào)屏蔽字中,這阻止了后來產(chǎn)生的這種信號(hào)中斷該信號(hào)處理程序,然后再信號(hào)處理程序返回時(shí)恢復(fù)信號(hào)屏蔽字。

    但是如果在信號(hào)處理函數(shù)中使用longjmp非局部轉(zhuǎn)移到setjmp處,會(huì)導(dǎo)致信號(hào)屏蔽字無法恢復(fù)。解決方案是調(diào)用sigsetjmp和siglongjmp而不是使用setjmp和longjmp

    int sigsetjmp(sigjmp_buf env, int savesigs); void siglongjmp(sigjmp_buf env, int val);

    這兩個(gè)函數(shù)和setjmp和longjmp的唯一區(qū)別是sigsetjmp增加了參數(shù)savesigs。如果該參數(shù)非0,則在env參數(shù)中保存進(jìn)程的當(dāng)前信號(hào)屏蔽字,此時(shí)在信號(hào)處理函數(shù)中調(diào)用siglongjmp進(jìn)行非局部跳轉(zhuǎn)到sigsetjmp,會(huì)導(dǎo)致恢復(fù)保存的信號(hào)屏蔽字

    sig_atomic_t類型:

    當(dāng)把變量聲明為該類型會(huì)保證該變量在使用或賦值時(shí), 無論是在32位還是64位的機(jī)器上都能保證操作是原子的, 它會(huì)根據(jù)機(jī)器的類型自動(dòng)適應(yīng)
    在處理信號(hào)(signal)的時(shí)候,有時(shí)對(duì)于一些變量的訪問希望不會(huì)被中斷,無論是硬件中斷還是軟件中斷,這就要求訪問或改變這些變量需要在計(jì)算機(jī)的一條指令內(nèi)完成。通常情況下,int類型的變量通常是原子訪問的,也可以認(rèn)為 sig_atomic_t就是int類型的數(shù)據(jù),因?yàn)閷?duì)這些變量要求一條指令完成,所以sig_atomic_t不可能是結(jié)構(gòu)體,只會(huì)是數(shù)字類型。

    sig_atomic_t類型總是用volatile修飾,因?yàn)樵撟兞靠偸怯蓛蓚€(gè)不同的控制線程-main函數(shù)和異步執(zhí)行的信號(hào)處理程序訪問,因此必須保證每次需要存儲(chǔ)或讀取這個(gè)變量的時(shí)候,都會(huì)直接從變量地址中讀取數(shù)據(jù)如果沒有volatile關(guān)鍵字,則編譯器可能優(yōu)化讀取和存儲(chǔ),可能暫時(shí)使用寄存器中的值,導(dǎo)致將出現(xiàn)不一致的現(xiàn)象

    如這樣使用:

    volatile sig_atomic_t flag;

    16. sigsuspend函數(shù)

    考慮sigprocmask函數(shù)中提出的一點(diǎn):如果在調(diào)用該函數(shù)后如果有任何未決的、不再阻塞的信號(hào),則在函數(shù)返回之前,至少將其中之一遞送給該進(jìn)程

    那么如果針對(duì)下面代碼則會(huì)出現(xiàn)問題:

    sigprocmask(SIG_SETMASK,&oldmask,NULL); pause();

    如果sigprocmask解除了某個(gè)信號(hào)阻塞,而在此期間的確該信號(hào)被阻塞了,由上所述,那么就好像該信號(hào)發(fā)生在sigprocmask和pause函數(shù)之間。(或者在sigprocmask和pause函數(shù)之間的確有某個(gè)未阻塞的信號(hào)被遞送了),那么將會(huì)導(dǎo)致pause函數(shù)一直阻塞下去,即sigprocmask和pause函數(shù)之間的這個(gè)時(shí)間窗口中的信號(hào)丟失了。

    針對(duì)此問題,需要在一個(gè)原子操作中解除信號(hào)阻塞并使進(jìn)程休眠。

    因此可以使用sigsuspend函數(shù),該函數(shù)在一個(gè)原子操作中先恢復(fù)信號(hào)屏蔽字,然后使進(jìn)程休眠

    int sigsuspend(const sigset_t *mask);

    進(jìn)程的信號(hào)屏蔽字設(shè)置為mask,在捕捉到一個(gè)信號(hào)或發(fā)生了一個(gè)會(huì)終止該進(jìn)程的信號(hào)之前,該進(jìn)程被掛起。如果捕捉到一個(gè)信號(hào)并且從該信號(hào)處理程序返回,則sigsuspend返回,并且恢復(fù)信號(hào)屏蔽字為sigsuspend之前的值(并且返回-1,errno設(shè)為EINTR)。

    17. abort函數(shù)

    使進(jìn)程異常終止

    void abort(void);

    此函數(shù)將SIGABRT信號(hào)發(fā)送給調(diào)用進(jìn)程raise(SIGABRT),不應(yīng)忽略此信號(hào)。

    • 注意,若捕獲此信號(hào)并且由相應(yīng)信號(hào)處理函數(shù)返回,abort仍不會(huì)返回到其調(diào)用者。如果捕捉到此信號(hào),那么信號(hào)處理程序不能返回的唯一方法是調(diào)用exit _exit _Exit longjmp或siglongjmp。即abort導(dǎo)致進(jìn)程的非正常終止,除非SIGABRT 信號(hào)被捕獲,并且信號(hào)處理函數(shù)沒有返回(使用了longjmp等函數(shù)使信號(hào)處理函數(shù)沒有返回)。

    • 并且abort不理會(huì)進(jìn)程對(duì)此信號(hào)的阻塞或忽略

    • 進(jìn)程捕獲abort調(diào)用信號(hào)處理程序的意圖:

      在進(jìn)程終止之前執(zhí)行所需的清理操作。如果進(jìn)程并不在信號(hào)處理程序中終止自己,則當(dāng)信號(hào)處理函數(shù)返回時(shí),abort終止該進(jìn)程

    • 如果abort要終止進(jìn)程,則它對(duì)所有打開標(biāo)準(zhǔn)I/O流的效果應(yīng)當(dāng)與進(jìn)程終止前對(duì)每個(gè)流調(diào)用fclose相同。

    18. system函數(shù)

    • system函數(shù)阻塞SIGCHLD:

      正在執(zhí)行system函數(shù)時(shí),應(yīng)當(dāng)阻塞對(duì)父進(jìn)程遞送SIGCHLD信號(hào)。否則,當(dāng)system創(chuàng)建的子進(jìn)程結(jié)束時(shí),system的調(diào)用者可能錯(cuò)誤的認(rèn)為它自己的一個(gè)子進(jìn)程結(jié)束了,然后在SIGCHLD信號(hào)處理程序中通過wait函數(shù)獲取子進(jìn)程終止?fàn)顟B(tài)。由于該子進(jìn)程終止?fàn)顟B(tài)已被獲取過了,因此就阻止了system函數(shù)獲取子進(jìn)程的終止?fàn)顟B(tài)并將其作為返回值

    • system函數(shù)忽略SIGINT和SIGQUIT

      由之前的知識(shí)可知,當(dāng)在終端鍵入Ctrl+C會(huì)將SIGINT發(fā)送給前臺(tái)進(jìn)程組、在終端鍵入Ctrl+\會(huì)將SIGQUIT發(fā)送給前臺(tái)進(jìn)程組。但是在system期間這兩個(gè)信號(hào)應(yīng)該只發(fā)送給正在運(yùn)行的程序:即system函數(shù)中創(chuàng)建的子進(jìn)程因?yàn)橛蓅ystem執(zhí)行的命令可能是交互式命令(如ed編輯器),以及system函數(shù)的調(diào)用者在system執(zhí)行期間放棄了控制,等待該命令程序執(zhí)行結(jié)束,所以system調(diào)用者就不應(yīng)該接收這兩個(gè)終端產(chǎn)生的信號(hào)。這也是為何規(guī)定system的調(diào)用者在等待命令完成時(shí)應(yīng)當(dāng)忽略這兩個(gè)信號(hào)。

    19. sleep、nanosleep、clock_nanosleep函數(shù)

    19.1 sleep

    sleep函數(shù)使調(diào)用進(jìn)程被掛起直到滿足以下條件:

    • 已經(jīng)超過參數(shù)指定的秒數(shù)
    • 進(jìn)程捕捉到一個(gè)信號(hào)并從信號(hào)處理程序返回

    該函數(shù)返回未休眠剩余的秒數(shù)

    unsigned int sleep(unsigned int seconds);

    注意,sleep可以由alarm函數(shù)實(shí)現(xiàn),但是可能造成sleep和alarm函數(shù)互相影響。比如先alarm(10),然后再sleep(3),那么對(duì)SIGALRM信號(hào)的產(chǎn)生情況造成影響。

    因此Linux使用nanosleep實(shí)現(xiàn)sleep。因?yàn)閚anosleep不涉及產(chǎn)生任何信號(hào),即與鬧鐘定時(shí)器相互獨(dú)立,所以該實(shí)現(xiàn)的sleep函數(shù)不會(huì)與其他時(shí)間相關(guān)函數(shù)如alarm產(chǎn)生交互影響

    19.2 nanosleep

    int nanosleep(const struct timespec *req, struct timespec *rem);struct timespec {time_t tv_sec; /* seconds */long tv_nsec; /* nanoseconds [0 .. 999999999] */};

    該函數(shù)與sleep類似,但是提供納秒級(jí)別精度。

    該函數(shù)掛起進(jìn)程,直到要求的時(shí)間超時(shí)或者某個(gè)信號(hào)中斷該函數(shù)。req參數(shù)指定進(jìn)程休眠時(shí)間,rem函數(shù)返回未休眠的剩余時(shí)間

    nanosleep函數(shù)并不涉及產(chǎn)生任何信號(hào),所以不用擔(dān)心與其他函數(shù)的交互。

    19.3 clock_nanosleep

    該函數(shù)制定了基于特定時(shí)鐘的延遲時(shí)間來掛起線程

    int clock_nanosleep(clockid_t clock_id, int flags,nconst struct timespec *request, struct timespec *remain);
    • clock_id:延遲時(shí)間基于的時(shí)鐘

      • CLOCK_REALTIME:系統(tǒng)實(shí)時(shí)時(shí)間,即從1970年開始的時(shí)間
      • CLOCK_MONOTONIC:從系統(tǒng)啟動(dòng)這一刻起開始計(jì)時(shí),不受系統(tǒng)時(shí)間被用戶改變的影響
      • CLOCK_PROCESS_CPUTIME_ID:本進(jìn)程到當(dāng)前代碼的CPU時(shí)間
      • CLOCK_THREAD_CPUTIME_ID:本線程到當(dāng)前代碼的CPU時(shí)間
    • flags:控制時(shí)間是絕對(duì)還是相對(duì)的

      0:相對(duì)的,即希望休眠的時(shí)間長度

      TIMER_ABSTIME:絕對(duì)的,即希望休眠到時(shí)鐘到達(dá)某個(gè)特定的時(shí)間

    • request和remain:和nanosleep一致。使用絕對(duì)時(shí)間時(shí),remain參數(shù)無用

    調(diào)用clock_nanosleep(CLOCK_REALTIME,0,req,rem)相當(dāng)于nanosleep(req,rem)

    20. sigqueue函數(shù):信號(hào)排隊(duì)

    如果支持信號(hào)實(shí)時(shí)擴(kuò)展,那么就支持信號(hào)排隊(duì)。如果要使用排隊(duì)信號(hào),則必須遵循以下條件

    • 使用sigaction函數(shù)安裝信號(hào)處理程序時(shí)指定SA_SIGINFO標(biāo)志。如果沒有此標(biāo)志,信號(hào)會(huì)阻塞延遲,但是是否進(jìn)入隊(duì)列取決于具體實(shí)現(xiàn)
    • 在sigaction結(jié)構(gòu)的sa_sigaction成員中(不是sa_handler)提供信號(hào)處理程序。實(shí)現(xiàn)可能允許用戶使用sa_handler字段,但是不能獲取sigqueue函數(shù)發(fā)出的額外信息
    • 使用sigqueue發(fā)出信號(hào)
    int sigqueue(pid_t pid, int sig, const union sigval value);

    該函數(shù)只把信號(hào)發(fā)給單個(gè)進(jìn)程。可以通過value參數(shù)向信號(hào)處理程序傳遞整數(shù)和指針值。除此之外,sigqueue和kill類似

    注意,信號(hào)不能被無限次排隊(duì)。到達(dá)相應(yīng)限制后,sigqueue會(huì)失敗,errno設(shè)置為EAGAIN。

    在支持實(shí)時(shí)信號(hào)擴(kuò)展的Linux之中,sigqueue只能用于實(shí)時(shí)信號(hào)(SIGRTMIN~SIGRTMAN之間的信號(hào),包括這兩個(gè)限制值),這些實(shí)時(shí)信號(hào)默認(rèn)操作是終止進(jìn)程。對(duì)于非實(shí)時(shí)信號(hào)(1-31信號(hào)),不支持信號(hào)排隊(duì)

    21. 作業(yè)控制信號(hào)

    以下六個(gè)信號(hào)與作業(yè)控制有關(guān):

    • SIGCHLD:子進(jìn)程停止或終止
    • SIGCONT:如果進(jìn)程已停止,則使其繼續(xù)運(yùn)行
    • SIGSTOP:停止信號(hào)(不能被捕捉或忽略)
    • SIGTSTP:交互式停止信號(hào)
    • SIGTTIN:后臺(tái)進(jìn)程組成員讀控制終端
    • SIGTTOU:后臺(tái)進(jìn)程組成員寫控制終端

    當(dāng)一個(gè)進(jìn)程產(chǎn)生4種停止信號(hào)(SIGTSTP、SIGSTOP、SIGTTIN、SIGTTOU),對(duì)進(jìn)程的任一未決SIGCONT信號(hào)丟棄

    當(dāng)對(duì)一個(gè)進(jìn)程產(chǎn)生SIGCONT信號(hào)時(shí),對(duì)同一進(jìn)程的任一未決停止信號(hào)被丟棄

    22. 信號(hào)名和編號(hào)

    通過數(shù)組sys_siglist獲取信號(hào)編號(hào)和信號(hào)名間的映射

    extern const char *const sys_siglist[_NSIG];//其中數(shù)組下標(biāo)即為信號(hào)編號(hào)

    使用psignal函數(shù)打印與信號(hào)編號(hào)對(duì)應(yīng)的字符串

    void psignal(int sig, const char *msg);

    該函數(shù)類似于perror,通常是在stderr打印出msg參數(shù),后面跟一個(gè)冒號(hào)一個(gè)空格,然后打印出該信號(hào)的說明。

    如果在sigaction信號(hào)處理程序中有siginfo_t結(jié)構(gòu),也可以通過siginfo_t結(jié)構(gòu),使用psiginfo函數(shù)打印出信號(hào)編號(hào)更多的信息

    void psiginfo(const siginfo_t *pinfo, const char *msg);

    使用strsignal獲取與信號(hào)相關(guān)字符串(而不是寫入到文件中),類似于strerror

    char *strsignal(int sig);

    示例:

    int main(int argc, char* argv[]) {cout << "sys_list數(shù)組 : " << sys_siglist[SIGCHLD] << endl;psignal(SIGCHLD,"psignal函數(shù) ");cout << "strsignal函數(shù) : " << strsignal(SIGCHLD) << endl; } /*打印: sys_list數(shù)組 : Child exited psignal函數(shù) : Child exited strsignal函數(shù) : Child exited */

    ist``獲取信號(hào)編號(hào)和信號(hào)名間的映射

    extern const char *const sys_siglist[_NSIG];//其中數(shù)組下標(biāo)即為信號(hào)編號(hào)

    使用psignal函數(shù)打印與信號(hào)編號(hào)對(duì)應(yīng)的字符串

    void psignal(int sig, const char *msg);

    該函數(shù)類似于perror,通常是在stderr打印出msg參數(shù),后面跟一個(gè)冒號(hào)一個(gè)空格,然后打印出該信號(hào)的說明。

    如果在sigaction信號(hào)處理程序中有siginfo_t結(jié)構(gòu),也可以通過siginfo_t結(jié)構(gòu),使用psiginfo函數(shù)打印出信號(hào)編號(hào)更多的信息

    void psiginfo(const siginfo_t *pinfo, const char *msg);

    使用strsignal獲取與信號(hào)相關(guān)字符串(而不是寫入到文件中),類似于strerror

    char *strsignal(int sig);

    示例:

    int main(int argc, char* argv[]) {cout << "sys_list數(shù)組 : " << sys_siglist[SIGCHLD] << endl;psignal(SIGCHLD,"psignal函數(shù) ");cout << "strsignal函數(shù) : " << strsignal(SIGCHLD) << endl; } /*打印: sys_list數(shù)組 : Child exited psignal函數(shù) : Child exited strsignal函數(shù) : Child exited */

    總結(jié)

    以上是生活随笔為你收集整理的《UNIX环境高级编程》笔记 第十章-信号的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    久久曰视频 | 十八岁以下禁止观看的1000个网站 | 中日韩在线视频 | a特级毛片 | 成年人免费看片 | 天天射综合网站 | 99在线精品视频观看 | 亚洲最大激情中文字幕 | 黄色一级大片在线免费看产 | 日本视频久久久 | 国产午夜精品在线 | 久久精品9| 在线观看免费高清视频大全追剧 | 97福利社 | 亚洲一级性 | 在线观看视频精品 | 久二影院 | 国产福利一区二区在线 | 亚洲理论在线观看 | 亚洲精品2区 | 欧美亚洲国产精品久久高清浪潮 | 综合久久久久久久久 | 成人一级影视 | 99精品在线视频播放 | 亚洲乱码久久久 | 狠狠久久婷婷 | japanesexxxxfreehd乱熟 | 色婷婷激情电影 | 黄色成人91 | 亚洲美女在线国产 | 999ZYZ玖玖资源站永久 | 亚洲免费观看视频 | 在线视频区 | 精品国产伦一区二区三区观看体验 | 精品日本视频 | 色婷婷午夜 | 五月婷婷伊人网 | 久久久久欧美精品 | 久久免费福利视频 | 亚洲女在线 | 日韩一级片大全 | 成人久久18免费网站图片 | 99精品久久只有精品 | 在线看日韩 | 久久成人国产精品免费软件 | 久久久久国产一区二区三区四区 | av视屏在线播放 | 日韩二区在线 | 高清一区二区 | 三三级黄色片之日韩 | 亚洲三级黄色 | 欧美日韩久久 | 免费精品人在线二线三线 | 欧美精品一二三 | 国产色黄网站 | 色99久久| 欧美韩日精品 | 中文资源在线播放 | 欧美少妇xxxxxx | 久久精久久精 | 久草在线高清视频 | www.国产视频 | 最近更新好看的中文字幕 | 色全色在线资源网 | 91看成人 | 99久久精品免费看国产四区 | 91视频91自拍 | 99久久精品国产系列 | 成人免费观看视频网站 | 中文字幕av在线电影 | 狠色在线| 久操97 | 美女啪啪图片 | 夜夜狠狠| 日本公妇在线观看高清 | 欧美极品在线播放 | 欧美一区二区三区在线视频观看 | 亚洲第一区在线观看 | 九色视频自拍 | 91精品久久久久久综合五月天 | 99视屏| 五月婷婷中文字幕 | 国产精品久久久久永久免费看 | 久久成人精品视频 | 国产在线观看二区 | 欧洲色吧 | 国产99久久精品一区二区永久免费 | 午夜精品视频一区 | 99欧美视频 | 一级黄色片网站 | 色婷丁香 | 人人搞人人干 | 天天要夜夜操 | 亚洲免费a | 日韩在线中文字幕视频 | 精品一二区 | 伊人婷婷在线 | 久久国产影视 | 国产成本人视频在线观看 | 国产一级精品在线观看 | 麻豆一精品传二传媒短视频 | 日韩www在线| 91在线91拍拍在线91 | 日韩免费观看av | 国产成人亚洲在线观看 | 男女激情麻豆 | 久久少妇 | 麻豆视频免费版 | 婷婷av网站 | 91豆花在线| 美女视频黄色免费 | 国产精品美女久久久久久久久久久 | 国偷自产中文字幕亚洲手机在线 | 欧美日韩在线精品一区二区 | 国产不卡一区二区视频 | 国产91学生| 亚洲黄色小说网 | www.夜夜爱 | 国产女人免费看a级丨片 | 婷婷av网站| www日韩视频 | 国产黄色理论片 | 国产精品网红直播 | 色综合久久66 | 亚洲精品五月天 | 五月婷婷色综合 | 精品特级毛片 | 国产午夜视频在线观看 | 国产精品999久久久 久产久精国产品 | 欧美精品一区二区三区四区在线 | 免费男女羞羞的视频网站中文字幕 | 亚洲黄色av网址 | 天堂av网站| 国产一区二区中文字幕 | 91精品视频观看 | 国产精品短视频 | 最近中文字幕高清字幕免费mv | 操久久网 | 国产一区在线播放 | 日韩欧美精品免费 | 国产日韩欧美在线看 | 精品久久久久久久久中文字幕 | 日韩免费电影一区二区 | 国产精品久久一区二区三区不卡 | 亚洲国产精品成人精品 | 久久视频这里有久久精品视频11 | 久久精品成人热国产成 | 国产精品一区二区免费 | 在线免费高清视频 | 91成人小视频 | 欧洲精品在线视频 | 久操综合| 激情av综合 | 久热香蕉视频 | 免费视频国产 | 最近中文字幕国语免费av | 久久精品视频99 | 在线国产91 | 九九免费在线观看 | 色综合久久88色综合天天6 | 国产精品乱码一区二三区 | 66av99精品福利视频在线 | 久久久久日本精品一区二区三区 | 亚州av一区| 97精品国自产拍在线观看 | 日韩av免费在线看 | 99视频| 久久久精品免费看 | 欧美在线视频免费 | 国产精品正在播放 | 亚洲黄色网络 | 婷婷色伊人 | 久久乐九色婷婷综合色狠狠182 | 成人网在线免费视频 | 在线日本看片免费人成视久网 | 最近高清中文字幕 | 日日麻批40分钟视频免费观看 | 伊人色综合久久天天 | 在线久热 | 97超级碰碰碰碰久久久久 | 天堂中文在线播放 | 久久久久久久久久久免费av | 欧美久久久久久久久久久久久 | 天天干天天插伊人网 | 麻豆你懂的| 免费高清男女打扑克视频 | 国产精品免费久久久久久 | 亚洲1区在线 | 国产黄色精品网站 | 日韩理论片中文字幕 | 日韩激情av在线 | 在线看国产日韩 | 久久久资源 | 免费国产在线精品 | 欧美一级高清片 | 国产小视频在线 | 黄色福利网 | 欧美在线你懂的 | 在线只有精品 | 国产精品不卡在线观看 | 日韩乱码中文字幕 | 午夜久久影视 | 国产黄色片在线免费观看 | 91看片淫黄大片一级在线观看 | 免费看色网站 | 激情图片qvod | 亚洲综合一区二区精品导航 | 亚洲精品在线国产 | 久久精品视 | 欧美色一色 | 娇妻呻吟一区二区三区 | 国产91精品欧美 | 中文字幕精品一区二区精品 | 欧洲高潮三级做爰 | 亚洲男人天堂2018 | 91成人网在线 | 亚洲乱码中文字幕综合 | 久久精品www人人爽人人 | 色综合久久久久网 | 婷婷视频导航 | 国产视频2021 | 日韩在线无| 久久国产一区二区三区 | 在线国产一区 | 在线播放一区二区三区 | 国产精品嫩草69影院 | 日韩电影在线观看一区二区 | 久久久久免费电影 | 特黄特色特刺激视频免费播放 | 国产最新在线视频 | 手机av在线免费观看 | 欧美日韩国产在线一区 | 国产精品24小时在线观看 | 天天综合网久久综合网 | 日韩精品高清不卡 | 二区中文字幕 | 人人澡人人澡人人 | 国产精品99久久免费黑人 | 欧美一级视频免费看 | 天天操天天射天天操 | av在线不卡观看 | 久久精品国产美女 | 久久久免费精品国产一区二区 | 91九色蝌蚪视频 | 久久视频精品在线 | 狠狠色丁香九九婷婷综合五月 | 五月天婷婷狠狠 | 国产麻豆精品久久 | 中文字幕高清免费日韩视频在线 | 丁香婷婷深情五月亚洲 | 国产精品久久久久久久免费观看 | 四虎欧美 | 不卡国产视频 | 久久免费av电影 | 成人免费网视频 | 一区二区三区免费在线观看视频 | 最近2019中文免费高清视频观看www99 | 色网站在线免费观看 | 国产黄色免费看 | 国产99久久精品 | 伊人午夜 | 欧美久久成人 | 精品国自产在线观看 | 欧美日韩一区二区三区在线免费观看 | 在线观看黄色 | 91视频高清完整版 | 日韩成人邪恶影片 | 亚洲精品国偷拍自产在线观看蜜桃 | 三级黄色免费片 | 亚洲不卡123| 黄色大片免费网站 | 免费在线成人av电影 | 久久草草影视免费网 | 国产精品成人aaaaa网站 | 91看片一区二区三区 | 麻豆视频免费入口 | 午夜精品一区二区三区四区 | 亚洲一区黄色 | 日韩欧美高清一区二区三区 | 色综合久久五月 | 免费看黄的 | 久久人人做 | 久久久久亚洲国产 | 亚洲精品美女视频 | 亚洲另类人人澡 | 国产永久免费高清在线观看视频 | 天天射天天射天天 | 国产精品96久久久久久吹潮 | 在线观看免费高清视频大全追剧 | 日韩精品视频在线观看免费 | 国产黄色a | 911国产 | x99av成人免费 | 最近中文字幕完整高清 | 在线色视频小说 | 91av在线视频免费观看 | 人人爽人人澡 | 日韩视频免费播放 | 国产美女搞久久 | 中文字幕在线观看网站 | 国产精品99久久久精品 | 国产超碰在线 | 亚洲精品乱码久久久久久久久久 | 51久久夜色精品国产麻豆 | 免费日韩电影 | 免费看的黄网站软件 | 久久免费电影网 | 在线韩国电影免费观影完整版 | 国产 一区二区三区 在线 | 色综合久久88色综合天天 | 福利二区视频 | 亚洲五月| 亚洲专区欧美 | av高清不卡 | 天天射天天爱天天干 | 在线观看久久 | 五月开心六月伊人色婷婷 | 免费网址在线播放 | 久久久久国产精品免费网站 | 五月天丁香视频 | 日韩首页| 日韩精品一区二区在线视频 | 伊人狠狠干 | 国产一级片网站 | 中文字幕有码在线观看 | 中文字字幕在线 | 欧美另类视频 | 91av片 | 亚洲激情 在线 | 国产精品久久久久影院日本 | 婷婷色中文字幕 | 国产美女精品视频免费观看 | 免费在线观看毛片网站 | 日本一区二区免费在线观看 | 一区二区三区视频网站 | 91av电影在线观看 | 国产精品99久久久久人中文网介绍 | 日韩精品不卡在线观看 | 久久欧美在线电影 | 国产精品第54页 | 免费福利片2019潦草影视午夜 | 欧美婷婷色 | 久久久久免费精品视频 | 亚洲黄色成人网 | 国产精成人品免费观看 | 在线精品视频免费播放 | 免费观看av| 美女网站视频免费黄 | 99久久毛片| 亚洲精品国产精品乱码不99热 | 黄色一级大片免费看 | 国产视频 亚洲精品 | 人人爽久久久噜噜噜电影 | 九色视频网站 | 青青久草在线视频 | 久久亚洲欧美日韩精品专区 | 99综合影院在线 | 色哟哟国产精品 | 国产黄色片一级三级 | 麻豆成人网 | 在线天堂中文在线资源网 | 国产伦精品一区二区三区… | 人人澡人人爱 | 99综合影院在线 | 中文字幕亚洲精品在线观看 | 久久精品二区 | 黄色在线成人 | 丁五月婷婷 | 久久精品8 | 91中文字幕永久在线 | 99爱精品视频 | 国产免费一区二区三区网站免费 | 国产成人免费高清 | 成人精品影视 | 亚洲精品久久久蜜桃直播 | 91成品视频| www.99热精品| 国产精品99久久久久久久久 | 日日夜夜艹 | 亚洲人人射 | 97色狠狠 | 91日韩精品一区 | 久久99精品波多结衣一区 | 久久久久久久av麻豆果冻 | 国产成人91 | 亚洲精品乱码久久久久 | 免费a v网站 | 免费进去里的视频 | 999毛片| 99热只有精品在线观看 | 欧美在线free | 午夜视频在线观看网站 | 久久婷婷网 | 一二三区av | 草久久久久久久 | 久久影院精品 | 国产在线观看,日本 | 天天色草| 久久久久国产免费免费 | 久久精品国产亚洲aⅴ | 成人久久久久 | 免费亚洲视频在线观看 | 久久久久久久久久久久亚洲 | 免费视频99| 免费看的国产视频网站 | 天天操天天射天天插 | 日本mv大片欧洲mv大片 | 天堂在线一区 | 日韩av网址在线 | 97超碰人人模人人人爽人人爱 | 黄色av成人在线 | 欧美精品中文字幕亚洲专区 | 91av在线免费观看 | 精品国自产在线观看 | 国产精品久久久久免费观看 | 在线观看国产亚洲 | 国产视频亚洲 | 国产精品日韩在线 | 9热精品| 欧美va天堂va视频va在线 | 在线精品播放 | 婷婷四房综合激情五月 | 欧美激情视频一区二区三区免费 | 国产一区免费视频 | 久久精品福利 | 91视频链接 | 国产视频中文字幕在线观看 | www日韩在线观看 | 最近更新中文字幕 | 日韩专区中文字幕 | 99热99re6国产在线播放 | 免费人成网 | 啪啪免费观看网站 | 91超在线 | 成人在线免费视频 | 黄色影院在线免费观看 | 日韩av三区 | 欧美日韩国产在线一区 | 91一区一区三区 | 亚洲午夜久久久综合37日本 | 国产高清免费在线观看 | 国产精品久久久久影院日本 | av官网| 国产中文字幕91 | 亚洲精品视频在 | 在线中文字幕一区二区 | 狠狠操夜夜操 | 热久久99这里有精品 | 人人草人| 在线 影视 一区 | 久久综合久久综合久久综合 | 日日夜夜中文字幕 | 欧美一级日韩三级 | 久久男人视频 | 国内外成人在线视频 | 久久y| 91av在线视频免费观看 | 成年人免费av | 亚洲最大的av网站 | 四虎影视欧美 | 韩日成人av | 亚洲美女免费精品视频在线观看 | 国产精品久久久久久久久久久久午夜 | 久久国产精品99久久久久久进口 | 久久只精品99品免费久23小说 | 激情av五月婷婷 | 成人动漫精品一区二区 | 91视频在线免费下载 | 五月天久久久久 | 免费国产ww | 精品国产乱码久久久久 | av动态图片 | 爱射综合 | 中文字幕一二 | 婷婷在线网 | 欧美一级看片 | 色黄久久久久久 | 玖玖视频免费在线 | 成人一级片视频 | 国产小视频免费观看 | 精品视频免费观看 | 2024国产精品视频 | wwwwww色 | 国产精品美乳一区二区免费 | 国产91影视 | 国产成人久久精品亚洲 | 日韩久久久久久久久 | 国产自产高清不卡 | 久久精品免费播放 | 国产精品女主播一区二区三区 | 国产日韩在线播放 | 成人在线免费观看网站 | 97精品国产91久久久久久 | 欧美日韩一二三四区 | 黄色成人av网址 | 狠狠躁夜夜躁人人爽视频 | 精品久久久久久国产偷窥 | 亚洲高清不卡av | av一本久道久久波多野结衣 | 国产视频亚洲精品 | 国产视频亚洲 | 国产高清视频网 | 久久久免费观看 | 亚洲乱码国产乱码精品天美传媒 | 一级黄色片在线播放 | 韩日av一区二区 | 97久久精品午夜一区二区 | 精品国产精品久久一区免费式 | 欧美a级片免费看 | 最近2019好看的中文字幕免费 | 九九视频免费观看视频精品 | 日日夜夜天天久久 | 在线国产日韩 | 911在线| 亚洲a在线观看 | 国内精品久久久久久久久久久久 | 欧美作爱视频 | 欧美成人影音 | 成人午夜电影网站 | 天天综合色 | 91在线视频观看免费 | 亚洲精品综合欧美二区变态 | 在线观看中文字幕一区二区 | 色.com| 久久99国产精品久久99 | 看全黄大色黄大片 | 日韩国产精品毛片 | 亚洲国产97在线精品一区 | 婷婷丁香激情综合 | 国产在线一线 | 欧美日韩啪啪 | 激情综合色综合久久综合 | 插插插色综合 | 狠狠的干 | 亚洲国产日韩欧美 | 麻豆你懂的 | 久久久久久美女 | 91久久人澡人人添人人爽欧美 | 久久久久久久国产精品影院 | 人人精久 | 国产色拍拍拍拍在线精品 | 国产aaa大片| 久草手机视频 | 色婷丁香 | 韩国av免费在线观看 | 国产精品久久久久久吹潮天美传媒 | 毛片随便看 | 手机在线看片日韩 | 亚洲欧美乱综合图片区小说区 | 国产专区视频在线观看 | 五月天丁香视频 | 婷婷激情五月综合 | 麻豆高清免费国产一区 | 四虎在线视频免费观看 | 激情综合五月天 | 中文在线最新版天堂 | 成人欧美一区二区三区黑人麻豆 | 999成人免费视频 | 91精品国产三级a在线观看 | 亚洲理论片在线观看 | 国产免费观看高清完整版 | 午夜精品成人一区二区三区 | 五月天综合色激情 | 激情综合网在线观看 | 国产一卡二卡在线 | 成人在线播放视频 | 91精品在线播放 | 在线视频精品播放 | 亚洲少妇久久 | 免费中文字幕在线观看 | 精品久久免费看 | 成人免费在线视频 | www国产亚洲精品久久麻豆 | 久久免费a | 久久国产精品系列 | 日韩一区二区三区视频在线 | 久久成人国产精品入口 | 91免费的视频在线播放 | 欧美性色综合网 | 免费在线一区二区 | 欧美视屏一区二区 | 亚洲狠狠婷婷综合久久久 | 国产福利91精品张津瑜 | 中文字幕视频在线播放 | 色免费在线 | 精品色综合 | 国产免费二区 | 亚洲精品66 | 天天玩天天干天天操 | av导航福利| 天天干天天操天天 | 91黄色成人| 国产视频精品久久 | 制服丝袜在线 | 日日夜夜天天射 | 天天操天天操天天操天天操天天操天天操 | 亚洲国产片 | 500部大龄熟乱视频 欧美日本三级 | 国产精品成久久久久三级 | 91片网| 国产精品久久久久久久毛片 | 麻豆一区在线观看 | 日本色小说视频 | 国产精品中文字幕在线 | 久久国产精品久久久 | 国产亚洲无 | 看片一区二区三区 | 黄污网| 欧美爽爽爽 | 精品一区久久 | 国产视频在线观看一区二区 | 一区二区高清在线 | 精品中文字幕在线播放 | 在线观看免费色 | 国产欧美精品一区aⅴ影院 99视频国产精品免费观看 | 国内精品久久久久久久影视简单 | 国产精品一区二区久久精品爱微奶 | 国内精品美女在线观看 | 这里只有精品视频在线 | 丁香婷婷激情 | 婷婷.com| 精品一区二区三区电影 | 天天综合天天做 | 色视频在线免费 | 激情开心色 | 婷婷在线视频 | 国产精品毛片完整版 | 成年人视频免费在线 | 视频精品一区二区三区 | 玖玖在线看 | 亚洲视频一级 | 少妇av片 | 亚洲精品在线二区 | 色黄久久久久久 | 免费观看www7722午夜电影 | 久久99热这里只有精品国产 | 九九免费在线观看 | 免费色视频网址 | 一级黄色a视频 | 在线视频麻豆 | 久久国内精品 | 久久精品成人 | 日日夜夜精品免费观看 | 亚洲乱码精品久久久久 | 激情综合站 | 91精品国产91热久久久做人人 | 国产一级一级国产 | www.久久色.com| 国产视频中文字幕 | 日韩无在线 | 国产99免费视频 | 成人毛片在线观看视频 | 久久精品国产精品 | 五月激情婷婷丁香 | 亚洲精品网站 | 国产中文字幕av | 日韩电影在线观看中文字幕 | 久久不卡电影 | 日韩精品免费在线观看 | www.亚洲精品在线 | 伊人宗合网 | 奇米网8888 | 中文字幕亚洲在线观看 | 国产精久久久 | 久久av观看 | 99在线观看视频网站 | 丝袜+亚洲+另类+欧美+变态 | 黄色三级视频片 | 国产色综合天天综合网 | 99精品免费久久久久久日本 | 久久黄色美女 | 久久一本综合 | 在线播放一区二区三区 | 狠狠色丁香久久婷婷综合_中 | 丁香六月中文字幕 | 日韩网| 亚洲黄色av一区 | 成年人在线免费视频观看 | 中文在线免费视频 | 国产女教师精品久久av | 国产亚洲精品成人av久久ww | 中文字幕无吗 | 天天色天天射天天综合网 | 国产黄在线 | 免费一区在线 | 午夜免费福利片 | 成人国产一区二区 | 成人av在线看 | 日韩免费看视频 | 91九色视频国产 | 久久精品亚洲一区二区三区观看模式 | 久色网 | 国产亚洲aⅴaaaaaa毛片 | 在线观看av免费观看 | 午夜精品一区二区三区在线 | 成人性生交大片免费看中文网站 | 亚洲欧美婷婷六月色综合 | 中文字幕在线视频免费播放 | 四虎视频 | 成人在线中文字幕 | 美女黄久久| 91亚洲综合 | 韩国av免费观看 | 日韩精品最新在线观看 | 国产在线观看高清视频 | 狠狠的日日 | 亚洲日本va中文字幕 | 2024av在线播放 | 天天操夜夜操夜夜操 | 在线看一级片 | 精品久久毛片 | 欧美日韩视频在线观看一区二区 | 天天干夜夜爱 | 欧美狠狠操 | 91在线观看高清 | 狠狠色丁香婷婷综合最新地址 | 成人av在线观 | 91久久久国产精品 | 日韩一级成人av | 婷婷干五月 | 天堂av在线网 | 伊人久久影视 | 国产一区二区播放 | 婷婷综合 | 黄色成人免费电影 | 丁香婷婷激情国产高清秒播 | 人人爽人人片 | 天天玩天天干天天操 | 欧美日韩免费在线视频 | 九九免费在线看完整版 | 久久精品久久国产 | 国产精品6| 婷婷激情综合五月天 | 91视频在线自拍 | 国产三级精品在线 | 欧美成人日韩 | 97国产大学生情侣酒店的特点 | 中文在线最新版天堂 | 日韩一二三在线 | 五月婷婷狠狠 | 亚洲色图激情文学 | 亚洲少妇xxxx | 一区二区毛片 | 中文字幕a∨在线乱码免费看 | 亚洲人av免费网站 | 精油按摩av | 国产91精品高清一区二区三区 | 国产99久久久国产精品免费二区 | 成人av网站在线播放 | 操操日| 手机成人av在线 | 国产一级性生活 | 9999激情| 亚洲一区网 | 9在线观看免费高清完整版 玖玖爱免费视频 | 日韩一区二区三区在线看 | 久久色中文字幕 | 青草视频在线播放 | 成人av资源网站 | 久久久精品 一区二区三区 国产99视频在线观看 | 97超碰人人干 | 黄色中文字幕在线 | 青青河边草免费观看 | 日韩av一区二区三区四区 | 亚洲精品影视在线观看 | 91久久精品日日躁夜夜躁国产 | 草久视频在线 | 国产视频一 | 99国产视频在线 | 亚洲丁香日韩 | 综合久久久久 | 亚洲精品一区中文字幕乱码 | 在线日韩中文 | 在线看国产一区 | 久久这里只有精品23 | 91精品国产三级a在线观看 | 9ⅰ精品久久久久久久久中文字幕 | 国内精品久久久久影院男同志 | 国产精品久久一区二区无卡 | 亚洲精品国产精品国自产观看 | 九草视频在线观看 | 久草在线视频资源 | 久久成人国产精品免费软件 | 亚洲va韩国va欧美va精四季 | 亚欧日韩成人h片 | 欧美日韩一区二区三区不卡 | 国产一区二区在线看 | 亚洲精品播放 | 国产综合精品一区二区三区 | 亚洲天堂视频在线 | 九九九国产 | 国产免费成人 | 精品国产免费久久 | 日韩免费电影网站 | 福利在线看片 | 激情视频91| 国产精品一区二区你懂的 | 日韩网站在线播放 | 日韩一区正在播放 | 91精品中文字幕 | 777视频在线观看 | 精品国产欧美一区二区 | 精品国产视频一区 | 在线电影日韩 | 国产成人精品综合久久久久99 | 久久亚洲婷婷 | 丁香视频全集免费观看 | 欧美日韩在线视频免费 | 亚州av网站 | 久久人人爽人人片 | 高清在线一区 | 亚洲人成精品久久久久 | 黄色午夜网站 | 国产伦精品一区二区三区四区视频 | 伊人婷婷网 | 中文字幕亚洲在线观看 | 中文不卡视频在线 | 日韩成人av在线 | 天天草天天干天天 | 日韩大陆欧美高清视频区 | 国产精品成人久久久 | 国产明星视频三级a三级点| 中文字幕在线观看av | 九九色综合 | 亚洲成人国产精品 | 尤物九九久久国产精品的分类 | 久久婷婷国产 | 麻豆系列在线观看 | 操夜夜操 | 精品久久久久久久久中文字幕 | 17videosex性欧美 | 天堂va在线观看 | 亚洲干视频在线观看 | 久久久18| 亚洲精品乱码久久久久v最新版 | 久久刺激视频 | 在线国产视频观看 | 久久久一本精品99久久精品 | 一区二区视频在线播放 | 国产美女免费视频 | 中文在线8新资源库 | 99热只有精品在线观看 | 日韩极品视频在线观看 | 黄色www | av亚洲产国偷v产偷v自拍小说 | 国产分类视频 | 狠狠干网址 | 亚洲美女视频在线观看 | 久久一区二区三区国产精品 | 日韩v欧美v日本v亚洲v国产v | 国产夫妻性生活自拍 | 久久激情视频免费观看 | 日本xxxxav | 日日射天天射 | 一级淫片a | 久久日本视频 | 欧美午夜理伦三级在线观看 | 天天玩天天操天天射 | 欧美成人黄色片 | 99久久这里只有精品 | 欧美久久久久久久久久久久久 | 欧美日韩一区二区三区视频 | 欧美日韩三级 | 日日夜夜狠狠操 | 日韩av看片 | 婷婷av电影| 91在线精品播放 | 久久久久国产一区二区三区四区 | 久久综合色播五月 | 成人黄色一级视频 | 深夜成人av| 精品在线观看一区二区 | 91精品国产入口 | 中文日韩在线视频 | av电影在线不卡 | 91视频网址入口 | 国精产品永久999 | 最近中文字幕免费 | 韩国av免费观看 | 国产精品97| 久久久久久久久久久久久久av | 91av在线播放 | 午夜 久久 tv | wwwwwww黄| www.香蕉视频在线观看 | 成人国产网站 | 在线 欧美 日韩 | 国产美女久久 | 99精品在线看 | 黄色网址中文字幕 | 五月天激情视频在线观看 | 视频二区在线 | 免费在线观看av网站 | 日韩午夜电影 | 成人一级片视频 | 日韩精品一区电影 | 国产五月天婷婷 | 日韩精品极品视频 | 一区二区三区视频网站 | 国产精品一区二区视频 | 国产一区二区影院 | 91成年人网站 | 日韩综合色 | 亚洲欧美日韩国产精品一区午夜 | 国产成人精品久久亚洲高清不卡 | 天堂va欧美va亚洲va老司机 | 日韩久久久久久久久久久久 | 国产视频1区2区 | www国产亚洲精品久久麻豆 | 99视频这里有精品 | 九九爱免费视频 | 久久精品2 | 色爱成人网 | 欧洲精品一区二区 | 日韩精品视频免费看 | 色综合欧洲 | 国产视频一 | av丝袜在线 | 91麻豆网站 | 麻豆手机在线 | 亚洲第一色 | 日本精品一二区 | 99久久久成人国产精品 | 国产精品亚州 | 99久久婷婷国产 | 精品嫩模福利一区二区蜜臀 | 国产精品九九久久久久久久 | 午夜少妇一区二区三区 | 日韩中字在线 | 亚洲精品国产精品乱码在线观看 | www.888.av | 国产精品一区二区免费视频 | av丝袜在线 | 久久久久99精品国产片 | 日日操日日插 | 国产精品成久久久久 | 夜夜高潮夜夜爽国产伦精品 | 国产亚州av | 国内精品久久久 | 精品在线你懂的 | 九九热精 | 中文字幕日韩一区二区三区不卡 | 国产精品 亚洲精品 | www好男人 | 久久精品中文字幕一区二区三区 | 最近高清中文字幕 | 日本在线观看视频一区 | 午夜视频播放 | 久久免费播放视频 | 日韩国产高清在线 | 天天综合网久久 | 久久99国产精品视频 | www狠狠操 | 99免费在线视频观看 | 日韩中文在线观看 | 中文字幕在线播放一区二区 | 色诱亚洲精品久久久久久 | 欧美嫩草影院 | 亚洲欧美精品一区 | 日本久久91| 九九涩涩av台湾日本热热 | 亚洲最大成人网4388xx | 中文字幕影片免费在线观看 | 国产精品你懂的在线观看 | 夜夜骑日日 | av在线免费播放网站 | 国产99久久 | 国产精品永久免费在线 | 一区二区三区在线观看免费视频 | 国产成人精品综合久久久 | 久久免费播放 | 成人91av| 久久精品a | 日韩黄色中文字幕 | 日韩在线视频一区 | 在线观看视频一区二区三区 | 国产成视频在线观看 | 99热播精品 | 午夜精品一区二区三区免费 | 国产麻豆剧传媒免费观看 | 久久久视屏 | 久久免费看片 | 91视频免费视频 | 色999视频 | 99在线热播精品免费99热 | 日本午夜在线观看 | 久久99国产精品二区护士 | 亚洲丁香久久久 | 亚洲少妇激情 | 69av在线视频| 97视频在线免费播放 | 人人爽人人爽人人爽 | 日韩综合在线观看 | 一区二区三区免费在线观看视频 | 国内精品视频在线播放 | av资源免费观看 | 亚洲一区二区视频在线播放 | 午夜精品久久久久久久99无限制 |