linux之信號

信號:在生活中,我們遇到過不同種類的信號,比如:(交通信號,乃至某個人的表情,動作等帶給你不同的信號)然而,在我們的linux下,我們最熟悉的就是,當遇到一個死循環的程序時,我們第一想到的就是按ctrl+c,此時這個進程立馬終止,這是一種通過鍵盤產生的信號。而說起ctrl+c,就引出了前臺進程和后臺進程。當ctrl+c產生的信號只能發給前臺進程。

用kill -l命令就可以查看信號了;


產生信號的另一種方式是:信號異常觸發系統使該進程終止:

例子:

運行結果:



還有一種方式,通過指令來使該進程終止


然后直接運行./test:



還有一種方式,通過alarm使進程終止

說起alarm給大家舉個例子吧,alarm意思是鬧鐘,在這里也同樣代表著當你執行某個進程時,突然用alarm定時的時間到了,這時鬧鐘發揮了作用,使得你的進程被迫停止,比如:


這是一個統計1秒鐘計數的程序,當一秒鐘到時,就會被SIGALRM信號終止。

運行結果:


下面我們來說一下處理信號的幾種方式吧!

忽略信號;執行默認;執行自定義(信號的捕捉)三種方式。(那么問題來了,什么時候處理呢?答案是適當的時候處理大笑


執行信號的處理動作稱為信號遞達,信號從產生到遞達之間的狀態,稱為信號未決。進程可以選擇阻塞某個信號,被阻塞的信號產生時將保持在未決狀態,直到進程解除對此信號的阻塞,才執行遞達的動作。

阻塞和忽略是不同,只要信號被阻塞就不會遞達,而忽略則是在遞達之后可選的一種處理動作。

信號在內核中是這樣表示的:


block:代表屏蔽狀態字(1表示阻塞,0表示不阻塞)

pending:代表未決(1表示未決,0表示可以遞達)

handler:代表信號的處理方式(默認,忽略,自定義)

每個信號都有兩個標志位分別表示阻塞(block)和未決(pending),還有一個函數指針表示處理動作。信號產生時,內核在進程控制塊中設置該信號的未決標志,直到信號遞達才清除該標志。

上面那張表說明:SIGHUP是沒有阻塞也沒有產生,所以處理動作為默認處理動作

SIGINT的block為1,pending也為1,表示正在阻塞,無法遞達。它的處理動作為忽略,但是在沒有解除阻塞之前不能忽略該信號,很可能在解除阻塞前改變為其他的處理動作。

對于上述的三張表,操作系統中的每個進程運行時都會存在。

SIGQUIT的block為1,pending為0,說明正在被阻塞,解除阻塞后就可以遞達。處理動作為用戶自定義的處理動作。

還有一種現象是,對于解除阻塞之前可能會發送多次信號,這時操作系統該作何處理呢。這里主要是分為普通信號和實時信號,普通信號出現發送多次的情況,會當做是一次信號進行處理。而實時信號發送多次的情況,會將這多個信號存在一個隊列中,分別處理各個信號。我們一般討論的是普通信號,因此只記錄一次,我們將未決和阻塞狀態用同一個數據類型來存儲sigset_t,信號集為sigset_t。還需要注意的一點是,阻塞信號集也叫做當前進程的信號屏蔽字。

說了信號集,我們之前說過這些普通信號是以位圖的形式存放的。每一個bit位表示一種信號是否存在。

對于信號的操作,我們有一組信號集操作函數,如下:


函數sigemptyset初始化set所指向的信號集,使其中所有信號的對應bit清零,表示該信號集不包含任何有效信號。

函數sigfillset初始化set所指向的信號集,使其中所有信號的對應bit置位,表?示 該信號集的有效信號包括系統支

持的所有信號。

在使?用sigset_t類型的變量之前,?一定要調 ?用sigemptyset或sigfillset做初始化,使信號集處于確定的狀態。

做完初始化之后調用sigaddset和sigdelset來添加或者刪除信號。

這四個函數成功返回0,失敗返回-1;

sigismember用來表示某種信號是否出現在有效信號集中。出現返回1,不出現返回0.

*還有函數sigprocmask:(讀取或更改進程的信號屏蔽字)

#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oset);

成功返回0,出錯返回-1

這里的oset為輸出型參數,如果oset為非空,則輸出當前進程的信號屏蔽字,通過oset輸出。如果set為非空,則更改信號屏蔽字,how指示如何更改。如果set和oset都為非空,則將當前進程的信號屏蔽字備份在oset中,然后再通過how參數更改信號屏蔽字。

how主要有三種表示:SIG_BLOCK(包含了我們希望添加的信號屏蔽字),SIG_UNBLOCK(包含了我們希望從信號屏蔽字中阻塞的信號),SIG_SETMASK(設置了當前的信號屏蔽字的值);

*函數sigpending:(讀取當前進程的未決信號集)

#include <signal.h>
int sigpending(sigset_t *set);

set為輸出型參數,將信號通過set輸出

?小栗子:

#include<stdio.h>
#include<signal.h>void PrintSigset(sigset_t *sig)
{int i = 0;for(i = 1; i < 32; i++){if(sigismember(sig,i)){printf("1 ");}else{printf("0 ");}}printf("\n");
}int main()
{sigset_t sigset,osigset;sigemptyset(&sigset);sigemptyset(&osigset);sigaddset(&sigset,SIGINT);sigprocmask(SIG_BLOCK,&sigset,&osigset);while(1){sigpending(&sigset);PrintSigset(&sigset);sleep(1);}return 0;
}
這個程序實現了將2號信號設置為阻塞信號。所以一直無法遞達。

程序運行時,每秒鐘把各信號的未決狀態打印一遍,由于我們阻塞了SIGINT信號,按Ctrl-C將會使SIGINT信號處于未決

狀態,按Ctrl-\和ctrl+z仍然可以終止程序,因為SIGQUIT信號沒有阻塞。

運行結果:


還有一個小栗子,我們將2號信號阻塞之后,5秒后解除阻塞。并打印原來信號的狀態。

#include<stdio.h>
#include<signal.h>void PrintSigset(sigset_t *sig)
{int i = 0;for(i = 1; i < 32; i++){if(sigismember(sig,i)){printf("1 ");}else{printf("0 ");}}printf("\n");
}void handler(int sig)
{printf("pid: %d sig:%d \n",getpid(),sig);
}
int main()
{sigset_t sigset,osigset;sigemptyset(&sigset);sigemptyset(&osigset);sigaddset(&sigset,SIGINT);sigprocmask(SIG_BLOCK,&sigset,&osigset);int count = 0;signal(2,handler);//signal(2,SIG_DFL);while(1){sigpending(&sigset);PrintSigset(&sigset);sleep(1);if(count++ > 5){sigprocmask(SIG_SETMASK,&osigset,NULL);count = 0;}}return 0;
}

運行結果:




本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/382709.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/382709.shtml
英文地址,請注明出處:http://en.pswp.cn/news/382709.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

視頻解析有感,在解析 iqiyi與qq視頻的時候,記錄一些發現

最近對iqiyi與qq視頻解析發現&#xff0c;兩個網站的解析流程&#xff0c;尤其是反解析措施 各有特點&#xff0c;簡單記錄一下 先說iqiyi&#xff0c; 瀏覽器模擬移動端可以拿到視頻的mp4鏈接&#xff0c;這個不多說。 iqiyiPC端瀏覽器獲取 ts過程&#xff1a; a.iqiyi一次性…

C語言atoi函數的用法

#include < stdlib.h > int atoi(const char *nptr);用法&#xff1a;將字符串里的數字字符轉化為整形數。返回整形值。 注意&#xff1a;轉化時跳過前面的空格字符&#xff0c;直到遇上數字或正負符號才開始做轉換&#xff0c;而再遇到非數字或字符串結束時(’/0’)才…

[Linux]繼續探究mysleep函數(競態條件)

之前我們探究過mysleep的簡單用法&#xff0c;我們實現的代碼是這樣的&#xff1a; #include<stdio.h> #include<signal.h>void myhandler(int sig) {}unsigned int mysleep(unsigned int timeout) {struct sigaction act,oact;act.sa_handler myhandler;sigempt…

C語言的atoi和C++的to_string

to_stringint to string將其他型轉換成字符串型atoiascii to integer是把字符串轉換成整型數的一個函數 to_string #include <iostream> // std::cout #include <string> // std::string, std::to_stringint main () {std::string perfect std::to_string…

ubuntu 升級python3.5到python3.7,并升級pip3

1, 下載python3.7.tgz 文件&#xff0c;解壓&#xff0c; 2. 編譯安裝 3. 刪除 /usr/bin 目錄下的 pip3, python3 4. 建立新的軟連接&#xff1a; #添加python3的軟鏈接ln -s /usr/local/python3/bin/python3.7 /usr/bin/python3#添加 pip3 的軟鏈接ln -s /usr/local/python3/b…

[Linux]死鎖

死鎖是指多個進程在運行過程中因爭奪資源而造成的一種僵局&#xff0c;當進程處于這種僵持狀態時&#xff0c;若無外力作用&#xff0c;它們都將無法再向前推進。之前信號量的時候我們知道&#xff0c;如果多個進程等待&#xff0c;主要體現在占有鎖的問題上。死鎖也可以被定義…

Python安裝第三方模塊總結 轉載的

轉自 https://www.jellythink.com/archives/541

[C++]vector創建二維數組

c.resize(n);將c重置為大小為n個元素向量&#xff0c;如果n比原來的元素多&#xff0c;則多出的元素常被初始化為0//節選《面向對象的程序設計》杜茂青 int N5, M6; vector<vector<int> > Matrix(N); for(int i 0; i< Matrix.size(); i){ Matrix[i].resize(M…

[Linux]線程安全和可重入函數

線程安全&#xff1a;一個函數被稱為線程安全的&#xff0c;當且僅當被多個并發進程反復調用時&#xff0c;它會一直產生正確的結果。如果一個函數不是線程安全的&#xff0c;我們就說它是線程不安全的。 重入&#xff1a;函數被不同的控制流程調用,有可能在第一次調用還沒返回…

[Linux]信號量

信號量是一個計數器&#xff0c;用于為多個進程提供對共享數據對象的訪問。 在信號量上只有三種操作可以進行&#xff0c;初始化、遞增和增加&#xff0c;這三種操作都是原子操作。遞減操作可以用于阻塞一個進程&#xff0c;增加操作用于解除阻塞一個進程。 為了獲得共享資源…

Linux VIM 程序中有游離的‘\357’ ‘\274’錯誤

gcc date.cpp -o date -lstdc date.cpp:18:20: 錯誤&#xff1a;程序中有游離的‘\357’date.Showdata()&#xfffd;&#xfffd;&#xfffd;^ date.cpp:18:21: 錯誤&#xff1a;程序中有游離的‘\274’date.Showdata()&#xfffd;&#xfffd;&#xfffd;^ date.cpp:18:22…

[Linux]關于SIGCHLD

之前我們就學過&#xff0c;關于wait和waitpid來處理僵尸進程&#xff0c;父進程等待子進程結束后自己才退出&#xff0c;這樣的方法有倆種方式&#xff0c;一種是父進程死死的等子進程退出&#xff0c;也就是使用阻塞的方式等待子進程退出&#xff0c;另一種方式是通過非阻塞的…

C語言思維導圖

本人能力有限&#xff0c;知識點難免概括不全&#xff0c;如有錯誤歡迎指正

轉載一篇關于curl的文章

轉載一篇關于curl的文章 http://www.360doc.com/content/16/0107/15/18578054_526158476.shtml

[Linux]vi/vim下添加多行注釋和取消注釋

添加注釋&#xff08;Centos&#xff09;&#xff1a; 在命令行模式下按ctrlV進入 visual block模式&#xff08;可視化模式&#xff09; 選中你需要注釋的行&#xff0c;再按大寫的I&#xff0c;輸入//&#xff0c;最后按倆下esc即可。 如果想讓前進tab個位&#xff0c;則可在…

pthread和互斥量條件變量函數意義速查表

數據類型 pthread_t 線程 互斥量和條件變量

[Linux]共享內存

共享內存是UNIX提供的進程間通信手段中速度最快的一種&#xff0c;也是最快的IPC形式。為什么是最快的呢&#xff0c;因為數據不需要在客戶進程和服務器進程之間復制&#xff0c;所以是最快的一種IPC。這是虛存中由多個進程共享的一個公共內存塊。 兩個不同進程A、B共享內存的…

僵尸進程的產生,危害和解決方案

概念 僵死狀態&#xff08;Zombies&#xff09;是一個比較特殊的狀態。 當進程退出并且父進程沒有讀取到子進程退出的返回代碼時就會產生僵尸進程。僵尸進程會以終止狀態保持在進程表中&#xff0c;并且會一直在等待父進程讀取退出狀態代碼。所以&#xff0c;只要子進程退出&…

CString string 轉換

https://www.cnblogs.com/HappyEDay/p/7016162.html

[Linux]gdb調試多進程多線程例程

gdb相信學linux的同學已經比較熟悉了吧&#xff0c;它是linux下代碼調試工具。我們在寫c語言&#xff0c;c的代碼時經常會用到&#xff0c;它有一些常用的調試命令: run&#xff08;r&#xff09;&#xff1a;運行程序&#xff0c;如果有斷點在下一個斷點處停止 start&#xf…