日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux系统编程---6(信号的机制,信号4要素,Linu常规信号表,定时器)

發布時間:2023/11/30 linux 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux系统编程---6(信号的机制,信号4要素,Linu常规信号表,定时器) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

信號的概念

信號在我們的生活中隨處可見, 如:古代戰爭中摔杯為號;現代戰爭中的信號彈;體育比賽中使用的信號槍… 他們都有共性:

  • 簡單
  • 不能攜帶大量信息,只能帶一個標志。
  • 滿足某個特設條件才發送。
    Unix 早期版本就提供了信號機制,但不可靠,信號可能丟失。Berkeley 和 AT&T 都對信號模型做了更改,增加 了可靠信號機制。但彼此不兼容。POSIX.1 對可靠信號例程進行了標準化。
  • 信號的機制

    A 給 B 發送信號,B 收到信號之前執行自己的代碼,收到信號后,不管執行到程序的什么位置,都要暫停運行, 去處理信號,處理完畢再繼續執行。與硬件中斷類似——異步模式。但信號是軟件層面上實現的中斷,早期常被稱 為“軟中斷”。

    信號的特質

    由于信號是通過軟件方法實現,其實現手段導致信號有很強的延時性。但對于用戶來說,這個延 遲時間非常短,不易察覺。

    每個進程收到的所有信號,都是由內核負責發送的,內核處理。

    與信號相關的事件和狀態

    產生信號:

  • 按鍵產生,如:Ctrl+c(死循環終止)、Ctrl+z、Ctrl+\
  • 系統調用產生,如:kill、raise、abort
  • 軟件條件產生,如:定時器 alarm
  • 硬件異常產生,如:非法訪問內存(段錯誤)、除 0(浮點數例外)、內存對齊出錯(總線錯誤)
  • 命令產生,如:kill 命令
  • 遞達:

    遞送并且到達進程。產生到遞達是瞬時的

    未決:

    產生和遞達之間的狀態。主要由于阻塞(屏蔽)導致該狀態。

    信號的處理方式:

  • 執行默認動作
  • . 忽略(丟棄)
  • 捕捉(調用戶處理函數) (不讓它執行默認動作)
    Linux 內核的進程控制塊 PCB 是一個結構體,task_struct, 除了包含進程 id,狀態,工作目錄,用戶 id,組 id, 文件描述符表,還包含了信號相關的信息,主要指阻塞信號集和未決信號集。
  • 阻塞信號集(信號屏蔽字):

    描述信號屏蔽狀態,將某些信號加入集合,對他們設置屏蔽,當屏蔽 x 信號后,再收到該信號,該信號 的處理將推后(解除屏蔽后) 阻塞信號集影響未決信號集。

    未決信號集:

    沒有處理掉

  • 信號產生,未決信號集中描述該信號的位立刻翻轉為 1,表信號處于未決狀態。當信號被處理對應位翻 轉回為 0。這一時刻往往非常短暫。
  • 信號產生后由于某些原因(主要是阻塞)不能抵達。這類信號的集合稱之為未決信號集。在屏蔽解除前, 信號一直處于未決狀態。
  • 信號的編號

    可以使用 kill–l 命令查看當前系統可使用的信號有哪些。

    不存在編號為 0 的信號。其中 1-31 號信號稱之為常規信號(也叫普通信號或標準信號),34-64 稱之為實時信 號,驅動編程與硬件相關。名字上區別不大。而前 32 個名字各不相同。

    信號 4 要素

    與變量三要素類似的,每個信號也有其必備 4 要素,分別是:

  • 編號
  • 名稱
  • 事件
  • 默認處理動作
    可通過 man7signal 查看幫助文檔獲取。也可查看/usr/src/linux-headers-3.16.0-30/arch/s390/include/uapi/asm/signal.h


  • 在標準信號中,有一些信號是有三個“Value” ,第一個值通常對 alpha 和 sparc 架構有效,中間值針對 x86、arm 和其他架構,最后一個應用于 mips 架構。一個‘-’表示在對應架構上尚未定義該信號。
    不同的操作系統定義了不同的系統信號。因此有些信號出現在 Unix 系統內,也出現在 Linux 中,而有的信號出 現在 FreeBSD 或 MacOS 中卻沒有出現在 Linux 下。這里我們只研究 Linux 系統中的信號。

    默認動作:

  • Term:終止進程
  • Ign: 忽略信號 (默認即時對該種信號忽略操作)
  • Core:終止進程,生成 Core 文件。(查驗進程死亡原因, 用于 gdb 調試)
  • Stop:停止(暫停)進程
  • Cont:繼續運行進程
    注意從 man7signal 幫助文檔中可看到 :The signals SIGKILL and SIGSTOP cannot be caught, blocked , orignored.
    這里特別強調了 9)SIGKILL 和 19)SIGSTOP 信號,不允許忽略和捕捉,只能執行默認動作。甚至不能將其設置為 阻塞。
    另外需清楚,只有每個信號所對應的事件發生了,該信號才會被遞送(但不一定遞達),不應亂發信號! !
  • Linux 常規信號一覽表

  • IGHUP: 當用戶退出 shell 時,由該 shell 啟動的所有進程將收到這個信號,默認動作為終止進程
  • SIGINT:當用戶按下了<Ctrl+C>組合鍵時,用戶終端向正在運行中的由該終端啟動的程序發出此信號。默認動 作為終止進程。
  • SIGQUIT:當用戶按下<ctrl+>組合鍵時產生該信號,用戶終端向正在運行中的由該終端啟動的程序發出些信 號。默認動作為終止進程。
  • SIGILL:CPU 檢測到某進程執行了非法指令。默認動作為終止進程并產生 core 文件
  • SIGTRAP:該信號由斷點指令或其他 trap 指令產生。默認動作為終止里程 并產生 core 文件。
  • SIGABRT: 調用 abort 函數時產生該信號。默認動作為終止進程并產生 core 文件。
  • SIGBUS:非法訪問內存地址,包括內存對齊出錯,默認動作為終止進程并產生 core 文件。
  • SIGFPE:在發生致命的運算錯誤時發出。不僅包括浮點運算錯誤,還包括溢出及除數為 0 等所有的算法錯誤。 默認動作為終止進程并產生 core 文件。
  • SIGKILL:無條件終止進程。本信號不能被忽略,處理和阻塞。默認動作為終止進程。它向系統管理員提供了 可以殺死任何進程的方法。
  • SIGUSE1:用戶定義 的信號。即程序員可以在程序中定義并使用該信號。默認動作為終止進程。
  • SIGSEGV:指示進程進行了無效內存訪問。默認動作為終止進程并產生 core 文件。
  • SIGUSR2:另外一個用戶自定義信號,程序員可以在程序中定義并使用該信號。默認動作為終止進程。
  • SIGPIPE:Brokenpipe 向一個沒有讀端的管道寫數據。默認動作為終止進程。
  • SIGALRM: 定時器超時,超時的時間 由系統調用 alarm 設置。默認動作為終止進程。
  • SIGTERM:程序結束信號,與 SIGKILL 不同的是,該信號可以被阻塞和終止。通常用來要示程序正常退出。 執行 shell 命令 Kill 時,缺省產生這個信號。默認動作為終止進程
  • SIGSTKFLT:Linux 早期版本出現的信號,現仍保留向后兼容。默認動作為終止進程。
  • SIGCHLD:子進程結束時,父進程會收到這個信號。默認動作為忽略這個信號。
  • SIGCONT:如果進程已停止,則使其繼續運行。默認動作為繼續/忽略。
  • SIGSTOP:停止進程的執行。信號不能被忽略,處理和阻塞。默認動作為暫停進程。
  • SIGTSTP:停止終端交互進程的運行。按下<ctrl+z>組合鍵時發出這個信號。默認動作為暫停進程。
  • SIGTTIN:后臺進程讀終端控制臺。默認動作為暫停進程。
  • SIGTTOU: 該信號類似于 SIGTTIN,在后臺進程要向終端輸出數據時發生。默認動作為暫停進程。
  • SIGURG:套接字上有緊急數據時,向當前正在運行的進程發出些信號,報告有緊急數據到達。如網絡帶外 數據到達,默認動作為忽略該信號。
  • SIGXCPU:進程執行時間超過了分配給該進程的 CPU 時間 ,系統產生該信號并發送給該進程。默認動作為 終止進程。
  • SIGXFSZ:超過文件的最大長度設置。默認動作為終止進程。
  • SIGVTALRM:虛擬時鐘超時時產生該信號。類似于 SIGALRM,但是該信號只計算該進程占用 CPU 的使用時 間。默認動作為終止進程。
  • SGIPROF:類似于 SIGVTALRM,它不公包括該進程占用 CPU 時間還包括執行系統調用時間。默認動作為終止 進程。
  • SIGWINCH:窗口變化大小時發出。默認動作為忽略該信號。
  • SIGIO:此信號向進程指示發出了一個異步 IO 事件。默認動作為忽略。
  • SIGPWR:關機。默認動作為終止進程。
  • SIGSYS:無效的系統調用。默認動作為終止進程并產生 core 文件。
  • (34)SIGRTMIN ~ (64)SIGRTMAX:LINUX 的實時信號,它們沒有固定的含義(可以由用戶自定義)。所有的實時 信號的默認動作都為終止進程。
  • 信號的產生

    終端按鍵產生信號

  • Ctrl+c → 2)SIGINT(終止/中斷) “INT”----Interrupt
  • Ctrl+z → 20)SIGTSTP(暫停/停止) “T”----Terminal 終端。
  • Ctrl+\ → 3)SIGQUIT(退出)
  • 硬件異常產生信號

  • 除 0 操作 → 8)SIGFPE(浮點數例外) “F”-----float 浮點數。
  • 非法訪問內存 → 11)SIGSEGV(段錯誤)
  • 總線錯誤 → 7)SIGBUS
  • kill 函數/命令產生信號

    kill 命令產生信號:kill-SIGKILL pid
    kill 函數:給指定進程發送指定信號(不一定殺死)
    int kill (pid_tpid,int sig); 成功:0;失敗:-1(ID 非法,信號非法,普通用戶殺 init 進程等權級問題),設置 errno sig:不推薦直接使用數字,應使用宏名,因為不同操作系統信號編號可能不同,但名稱一致。

  • pid>0: 發送信號給指定的進程。
  • pid=0: 發送信號給 與 調用 kill 函數進程屬于同一進程組的所有進程。
  • pid<0: 取|pid|發給對應進程組。
  • pid=-1:發送給進程有權限發送的系統中所有進程。
  • 循環創建 5 個子進程,殺死第三個進程
    #include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<signal.h>/** 循環創建 5 個子進程 */#define N 5 int main() {int i;pid_t pid,q;for(i=0;i<N;i++){pid = fork();if(pid == 0)break;if(i==2)q=pid;}if(i<5){while(1){printf("I am child %d,getpid= %d\n",i,getpid());sleep(1);} }else{sleep(1);kill(q,SIGKILL);while(1);} return 0; }



    殺死第一個cat,后面的都被殺死,因為第一個cat是管道的寫端,如果第一個cat被殺,也就沒有寫入,所以后面的cat也就讀不到數據

    進程組

    :每個進程都屬于一個進程組,進程組是一個或多個進程集合,他們相互關聯,共同完成一個實體任務, 每個進程組都有一個進程組長,默認進程組 ID 與進程組長 ID 相同。

    權限保護

    super 用戶(root)可以發送信號給任意用戶,普通用戶是不能向系統用戶發送信號的。 kill-9(root 用 戶的 pid) 是不可以的。同樣,普通用戶也不能向其他普通用戶發送信號,終止其進程。 只能向自己創建的進程發 送信號。普通用戶基本規則是:發送者實際或有效用戶 ID== 接收者實際或有效用戶 ID

    raise 和 abort 函數

    raise 函數:給當前進程發送指定信號(自己給自己發) raise(signo)==kill(getpid(),signo); int raise(int sig); 成功:0,失敗非 0 值
    abort 函數:給自己發送異常終止信號 6)SIGABRT 信號,終止并產生 core 文件 void abort(void); 該函數無返回

    軟件條件產生信號

    alarm 函數

    設置定時器(鬧鐘)。在指定 seconds 后,內核會給當前進程發送 14)SIGALRM 信號。進程收到該信號,默認動 作終止。
    每個進程都有且只有唯一個定時器。
    unsigned int alarm (unsigned int seconds); 返回 0 或剩余的秒數,無失敗。
    常用:取消定時器 alarm(0),返回舊鬧鐘余下秒數。 例:alarm(5) → 3sec → alarm(4) → 5sec → alarm(5) → alarm(0) (取消鬧鐘)
    定時,自然定時法,與進程狀態無關(自然定時法)!就緒、運行、掛起(阻塞、暫停)、終止、僵尸…無論進程處于何種狀態, alarm 都計時。

    編寫程序,測試你使用的計算機 1 秒鐘能數多少個數。
    #include<stdio.h> #include<unistd.h>int main() {int i;alarm(1);//1s后發信號for(i=0;;i++) //死循環看在鬧鐘的1s時間內跑多少下 printf("%d\n",i);return 0; }

    使用 time 命令查看程序執行的時間

    實際執行時間 = 系統時間 + 用戶時間 + 等待時間(文件I/O消耗很大)

    setitimer 函數

    設置定時器(鬧鐘)。 可代替 alarm 函數。精度微秒 us,可以實現周期定時。

    struct itimerval {struct timeval it_interval; /* next value */struct timeval it_value; /* current value */};struct timeval {time_t tv_sec; /* seconds */suseconds_t tv_usec; /* microseconds */};

    int setitimer (int which,const struct itimerval * new_value, struct itimerval *old_value); 成功:0;失敗:-1,設置 errno

    參數:

    which:指定定時方式

  • 自然定時:ITIMER_REAL → 14)SIGLARM 計算自然時間
  • 虛擬空間計時(用戶空間):ITIMER_VIRTUAL → 26)SIGVTALRM 只計算進程占用 cpu 的時間
  • 運行時計時(用戶+內核):ITIMER_PROF → 27)SIGPROF 計算占用 cpu 及執行系統調用的時間
  • 使用 setitimer 函數實現 alarm 函數,計算1是內計算機計算次數
    #include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<sys/time.h> /* struct itimerval{struct timeval{it_value.tv_sec;it_value.tv_usec;}it_value;struct timeval{it_value.tv_sec;it_value.tv_usec;}it_interval;}it,oldit; */unsigned int my_alarm(unsigned int sec) {struct itimerval it, oldit;int ret;it.it_value.tv_sec=sec;it.it_value.tv_usec=0;it.it_interval.tv_sec=0;it.it_interval.tv_usec=0;ret= setitimer(ITIMER_REAL,&it,&oldit);if(ret == -1){perror("setitimer");exit(1);} return oldit.it_value.tv_sec; }int main() {int i;my_alarm(1); //alarm(sec)for(i=0;;i++)printf("%d\n",i);return 0; }
    結合 manpage 編寫程序,測試 it_interval、it_value 這兩個參數的作用。

    void (*signal (int signum,void ( *sighandler_t)(int)))(int);

    #include<stdio.h> #include<sys/time.h> #include<signal.h>void myfunc(int signo) {printf("hello world\n"); }int main(void) {struct itimerval it,oldit;signal(SIGALRM,myfunc); //注冊SIGALRM信號的捕捉處理函數//sighandler_t tml=signal(SIGALRM,myfunc);it.it_value.tv_sec=5;//定時5秒中it.it_value.tv_usec=0;//0微秒it.it_interval.tv_sec=3;//第一個和第二個之間間隔時間3秒it.it_interval.tv_usec=0;if(setitimer(ITIMER_REAL,&it,&oldit) == -1){perror("setitimer error");return -1; } while(1);return 0; }

    注意

  • it_inter :用來設定兩次定時任務之間間隔的時間。
  • it_value:定時的時長 兩個參數都設置為 0,即清 0 操作。
  • 總結

    以上是生活随笔為你收集整理的Linux系统编程---6(信号的机制,信号4要素,Linu常规信号表,定时器)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。