1. 信號在內核中的表示
創(chuàng)新互聯(lián)建站成都網(wǎng)站建設按需定制設計,是成都網(wǎng)站營銷推廣公司,為成都軟裝設計提供網(wǎng)站建設服務,有成熟的網(wǎng)站定制合作流程,提供網(wǎng)站定制設計服務:原型圖制作、網(wǎng)站創(chuàng)意設計、前端HTML5制作、后臺程序開發(fā)等。成都網(wǎng)站建設熱線:13518219792
我們知道了信號產(chǎn)生的各種原因,而實際執(zhí)行信號處理的動作,叫做信號遞達(Delivery)。信號從產(chǎn)生到遞達之間的狀態(tài),稱為信號未決(Pending)。進程可以選擇阻塞(Block)某個信號。被阻塞的信號產(chǎn)生時將保持在未決狀態(tài),直到進程解除對此信號的阻塞,才執(zhí)行遞達的動作。
注意,阻塞和忽略是不同的,只要信號被阻塞就不會遞達,而忽略是在遞達之后可選的一種處理動作。
每個信號都有兩個標志位分別表示阻塞和未決,,還有一個函數(shù)指針表示處理動作,信號產(chǎn)生時,內核在進程控制塊中設置該信號的未決標志,直到信號遞達才清除該標志。
SIGHUP信號未阻塞也未產(chǎn)生過,當它遞達時執(zhí)行默認處理動作。
SIGINT信號產(chǎn)生過,但正在被阻塞,所以暫時不能遞達。雖然它的處理動作是忽略,但在沒有解除阻塞之前不能忽略這個信號,因為進程仍有機會改變處理動作之后再解除阻塞。
SIGQUIT信號未產(chǎn)生過,一旦產(chǎn)生SIGQUIT信號將被阻塞,它的處理動作是用戶自定義函數(shù)sighandler。
如果在進程解除對某信號的阻塞之前這種信號產(chǎn)生過多次,將如何處理?
POSIX.1允許系統(tǒng)遞送該信號一次或多次。Linux是這樣實現(xiàn)的:常規(guī)信號在遞達之前產(chǎn)生多次只計一次,而實時信號在遞達之前產(chǎn)生多次可以依次放在一個隊列里。
從上圖來看,每個信號只有一個bit的未決標志,非0即1,不記錄該信號產(chǎn)生了多少次,阻塞標志也是這樣表示的。因此,未決和阻塞標志可以用相同的數(shù)據(jù)類型sigset_t來存儲,sigset_t稱為信號集,這個類型可以表示每個信號的“有效”或“無效”狀態(tài),在阻塞信號集中“有效”和“無效”的含義是該信號是否被阻塞,而在未決信
號集中“有效”和“無效”的含義是該信號是否處于未決狀態(tài)。
2. 信號集操作函數(shù)
sigset_t類型對于每種信號用一個bit表示“有效”或“無效”狀態(tài),至于這個類型內部如何存儲這些bit則依賴于系統(tǒng)實現(xiàn),從使用者的角度是不必關心的,使用者只能調用以下函數(shù)來操作sigset_t變量,而不應該對它的內部數(shù)據(jù)做任何解釋,比如用printf直接打印sigset_t變量是沒有意義的。
#include signal.h
int sigemptyset(sigset_t *set); ----- 初始化set指向的信號集,使其中所有信號的對應bit清零,表示該信號集不包含任何有效信號.
int sigfillset(sigset_t *set); ---- 初始化set所指向的信號集,使其中所有信號的對應bit置位,表示該信號集的有效信號包括系統(tǒng)支持的所有信號。
int sigaddset(sigset_t *set, int signo);
int sigdelset(sigset_t *set, int signo);
int sigismember(const sigset_t *set, int signo);
注意,在使用sigset_t類型的變量之前,一定要調用sigemptyset或sigfillset做初始化,使信號集處于確定的狀態(tài)。
3. sigprocmask
調用函數(shù)sigprocmask可以讀取或更改進程的信號屏蔽字。
如果oset是非空指針,則讀取進程的當前信號屏蔽字通過oset參數(shù)傳出。如果set是非空指針,則更改進程的信號屏蔽字,參數(shù)how指示如何更改。如果oset和set都是非空指針,則先將原來的信號屏蔽字備份到oset里,然后根據(jù)set和how參數(shù)更改信號屏蔽字。假設當前的信號屏蔽字為mask,下表說明了how參數(shù)的可選值。
1. 設置socket
int oldOption = fcntl(sockfd, F_GETFL);
int newOption = oldOption | O_NONBLOCK;
//設置sockfd非阻塞
fcntl(sockfd, F_SETFL, newOption);12345
2. 執(zhí)行connect
如果返回0,表示連接成功,這種情況一般在本機上連接時會出現(xiàn)(否則怎么可能那么快)
否則,查看error是否等于EINPROGRESS(表明正在進行連接中),如果不等于,則連接失敗
int ret = connect(sockfd, (struct sockaddr*)addr, sizeof(addr));
if(ret == 0)
{
//連接成功
fcntl(sockfd, F_SETFL, oldOption);
return sockfd;
}
else if(errno != EINPROGRESS)
{
//連接沒有立即返回,此時errno若不是EINPROGRESS,表明錯誤
perror("connect error != EINPROGRESS");
return -1;
}12345678910111213141516
3. 使用select,如果沒用過select可以去看看
用select對socket的讀寫進行監(jiān)聽
那么監(jiān)聽結果有四種可能
1. 可寫(當連接成功后,sockfd就會處于可寫狀態(tài),此時表示連接成功)
2. 可讀可寫(在出錯后,sockfd會處于可讀可寫狀態(tài),但有一種特殊情況見第三條)
3. 可讀可寫(我們可以想象,在我們connect執(zhí)行完到select開始監(jiān)聽的這段時間內,
如果連接已經(jīng)成功,并且服務端發(fā)送了數(shù)據(jù),那么此時sockfd就是可讀可寫的,
因此我們需要對這種情況特殊判斷)
說白了,在可讀可寫時,我們需要甄別此時是否已經(jīng)連接成功,我們采用這種方案:
再次執(zhí)行connect,然后查看error是否等于EISCONN(表示已經(jīng)連接到該套接字)。
4. 錯誤
if(FD_ISSET(sockfd, writeFds))
{
//可讀可寫有兩種可能,一是連接錯誤,二是在連接后服務端已有數(shù)據(jù)傳來
if(FD_ISSET(sockfd, readFds))
{
if(connect(sockfd, (struct sockaddr*)addr, sizeof(addr)) != 0)
{
int error=0;
socklen_t length = sizeof(errno);
//調用getsockopt來獲取并清除sockfd上的錯誤.
if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, error, length) 0)
{
printf("get socket option failed\n");
close(sockfd);
return -1;
}
if(error != EISCONN)
{
perror("connect error != EISCONN");
close(sockfd);
return -1;
}
}
}
//此時已排除所有錯誤可能,表明連接成功
fcntl(sockfd, F_SETFL, oldOption);
return sockfd;
}12345678910111213141516171819202122232425262728293031323334353637383940
4. 恢復socket
因為我們只是需要將連接操作變?yōu)榉亲枞?,并不包括讀寫等,所以我們吃醋要將socket重新設置。
fcntl(sockfd, F_SETFL, oldOption);關于Linux命令的介紹,看看《linux就該這么學》,具體關于這一章地址3w(dot)linuxprobe/chapter-02(dot)html
不知題主的read是指socket的read還是文件的read。 默認情況下,socket的read是阻塞的; 對文件進行read,要看內核態(tài)的read接口是注冊為同步接口還是異步接口(可參見file_operations結構體)
創(chuàng)建管道的接口除了pipe以外,Linux還支持新接口pipe2(int pipefd[2], int flags);
flags 如果傳入O_NONBLOCK,讀寫管道時就不會阻塞了。
具體的你man 一下就知道
1、啟動后臺子任務,在執(zhí)行命令后加操作符,表示將命令放在子shell中異步執(zhí)行。可以達到多線程效果。如下,sleep10#等待10秒,再繼續(xù)下一操作sleep10當前shell不等待,后臺子shell等待。
2、wait命令wait是用來阻塞當前進程的執(zhí)行,直至指定的子進程執(zhí)行結束后,才繼續(xù)執(zhí)行。使用wait可以在bash腳本“多進程”執(zhí)行模式下,起到一些特殊控制的作用。
文章題目:linux執(zhí)行命令不堵塞 linux命令卡住 無法退出
文章起源:http://jinyejixie.com/article38/dochcpp.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站設計、網(wǎng)頁設計公司、App設計、定制網(wǎng)站、網(wǎng)站導航、商城網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)