




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、進程間通信進程間通信PIPE 進程間通信進程間通信FIFO 信號中斷處理信號中斷處理 進程間通信進程間通信管道和信號管道和信號進程通信有如下一些目的:A、數(shù)據(jù)傳輸:一個進程需要將它的數(shù)據(jù)發(fā)送給另一個進程,發(fā)送的數(shù)據(jù)量在一個字節(jié)到幾M字節(jié)之間;B、共享數(shù)據(jù):多個進程想要操作共享數(shù)據(jù),一個進程對共享數(shù)據(jù)的修改,別的進程應(yīng)該立刻看到;C、通知事件:一個進程需要向另一個或一組進程發(fā)送消息,通知它(們)發(fā)生了某種事件(如進程終止時要通知父進程);D、資源共享:多個進程之間共享同樣的資源。為了做到這一點,需要內(nèi)核提供鎖和同步機制;E、進程控制:有些進程希望完全控制另一個進程的執(zhí)行(如Debug進程),此時
2、控制進程希望能夠攔截另一個進程的所有陷入和異常,并能夠及時知道它的狀態(tài)改變。2022-3-162進程間通信的方式linux下的進程通信手段基本上是從Unix平臺上的進程通信手段繼承而來的。而對Unix發(fā)展做出重大貢獻的兩大主力AT&T的貝爾實驗室及BSD(加州大學(xué)伯克利分校的伯克利軟件發(fā)布中心)在進程間通信方面的側(cè)重點有所不同。前者對Unix早期的進程間通信手段進行了系統(tǒng)的改進和擴充,形成了“system V IPC”,通信進程局限在單個計算機內(nèi);后者則跳過了該限制,形成了基于套接口(socket)的進程間通信機制。Linux則把兩者繼承了下來,其中,最初Unix IPC包括:管道、FIFO、
3、信號;System V IPC包括:System V消息隊列、System V信號量、System V共享內(nèi)存區(qū);Posix IPC包括: Posix消息隊列、Posix信號量、Posix共享內(nèi)存區(qū)。2022-3-163Linux進程通信方式linux下進程間通信的幾種主要手段簡介:1、管道(Pipe)及有名管道(named pipe):管道可用于具有親緣關(guān)系進程間的通信,有名管道克服了管道沒有名字的限制,因此,除具有管道所具有的功能外,它還允許無親緣關(guān)系進程間的通信;2、信號(Signal):信號是比較復(fù)雜的通信方式,用于通知接受進程有某種事件發(fā)生,除了用于進程間通信外,進程還可以發(fā)送信號給
4、進程本身;linux除了支持Unix早期信號語義函數(shù)signal外,還支持語義符合Posix.1標(biāo)準(zhǔn)的信號函數(shù)sigaction。2022-3-164Linux進程通信方式3、報文(Message)隊列(消息隊列):消息隊列是消息的鏈接表。有足夠權(quán)限的進程可以向隊列中添加消息,被賦予讀權(quán)限的進程則可以讀走隊列中的消息。消息隊列克服了信號承載信息量少,管道只能承載無格式字節(jié)流以及緩沖區(qū)大小受限等缺點。4、共享內(nèi)存:使得多個進程可以訪問同一塊內(nèi)存空間,是最快的可用IPC形式。是針對其他通信機制運行效率較低而設(shè)計的。往往與其它通信機制,如信號量結(jié)合使用,來達到進程間的同步及互斥。5、信號量(sema
5、phore):主要作為進程間以及同一進程不同線程之間的同步手段。2022-3-165管道管道的實質(zhì)是一個內(nèi)核緩沖區(qū),進程以先進先出的方式從緩沖區(qū)中存取數(shù)據(jù):管道一端的進程順序地將數(shù)據(jù)寫入緩沖區(qū),另一端的進程則順序地讀出數(shù)據(jù)。該緩沖區(qū)可以看作是一個循環(huán)隊列,讀和寫的位置都是自動增加的,不能隨意改變,一個數(shù)據(jù)只能被讀一次,讀出以后在緩沖區(qū)中就不復(fù)存在了。當(dāng)緩沖區(qū)讀空或?qū)憹M時,有一定的規(guī)則控制相應(yīng)的讀進程或?qū)戇M程是否進入等待隊列;當(dāng)空的緩沖區(qū)有新數(shù)據(jù)寫入或滿的緩沖區(qū)有數(shù)據(jù)讀出時,就喚醒等待隊列中的進程繼續(xù)讀寫。2022-3-166管道管道實際上以類似文件的方式與進程交互,但它并不與磁盤打交道,所以效
6、率要比文件操作高很多。它有兩個局限性:(1)支持半雙工;(2)只有具有親緣關(guān)系的進程之間才能使用這種無名管道;使用管道的注意事項:1.當(dāng)讀一個寫端已經(jīng)關(guān)閉的管道時,在所有數(shù)據(jù)被讀取之后,read函數(shù)返回值為0,以指示到了文件結(jié)束處;2.如果寫一個讀端關(guān)閉的管道,則產(chǎn)生SIGPIPE信號。如果忽略該信號或者捕捉該信號并處理程序返回,則write返回-1,errno設(shè)置為EPIPE2022-3-167管道示例 例如$ ls | more功能是將ls命令的輸出作為more命令的輸入,并顯示more的最終輸出。這里ls與more要由兩個進程來完成。這兩個進程的通信就通過父進程shell創(chuàng)建管道。ls向
7、管道輸入數(shù)據(jù),more從管道讀出數(shù)據(jù)。2022-3-168stdinstdinstdoutstdoutstderrstderrlsmore管 道 連 接 管道用于不同進程間通信。通常先創(chuàng)建一個管道管道用于不同進程間通信。通常先創(chuàng)建一個管道,再通過,再通過forkfork函數(shù)創(chuàng)建一個子進程,該子進程會繼函數(shù)創(chuàng)建一個子進程,該子進程會繼承父進程所創(chuàng)建的管道。承父進程所創(chuàng)建的管道。創(chuàng)建無名管道 extern int pipe(int _pipedes2)此函數(shù)的參數(shù)是一個整型數(shù)組。如果執(zhí)行成功,pipe將存儲兩個整形文件描述符于_pipedes數(shù)組中,它們分別指向管道的兩端。如果系統(tǒng)調(diào)用失敗,將返回
8、-1。2022-3-1610注意:fd0 用于讀取管道,fd1 用于寫入管道。圖1 linux中管道與文件描述符的關(guān)系#include #include #include #include int main()int pipe_fd2;if(pipe(pipe_fd)0)printf(pipe create errorn);return -1;else printf(pipe create successn);close(pipe_fd0);close(pipe_fd1);管道讀寫管道主要用于不同進程間通信。實際上,通常先創(chuàng)建一個管道,再通過fork函數(shù)創(chuàng)建一個子進程。圖2 父子進程管道的文件
9、描述符對應(yīng)關(guān)系子進程寫入和父進程讀的命名管道:圖 關(guān)閉父進程fd1 和子進程fd0例:父子進程通過無名管道通信#include #include #include #include #include #include main()pid_t result;int r_num;int pipe_fd2;char buf_r100,buf_w100; memset(buf_r,0,sizeof(buf_r);2022-3-1615例:父子進程通過無名管道通信if(pipe(pipe_fd)0)perror(pipe);exit(EXIT_FAILURE); result=fork();if(res
10、ult0)printf(child process has read %d characters from the pipe,the string is:%sn,r_num,buf_r);close(pipe_fd0);exit(0);2022-3-1616例:父子進程通過無名管道通信elseclose(pipe_fd0);printf(please input the string:);scanf(%s,buf_w);if(write(pipe_fd1,buf_w,strlen(buf_w)!=-1)printf(parent process has written:%s to the pi
11、pe!n,buf_w);close(pipe_fd1);waitpid(result,NULL,0);exit(0);2022-3-1617dup()extern int dup(int _fd)dup()會復(fù)制一份原來已經(jīng)打開的文件描述符,新的描述符指向系統(tǒng)文件表中下一個可用的最小非負文件描述符,它與原來的文件描述符共享同一個文件指針,并擁有相同的文件權(quán)限及模式。當(dāng)調(diào)用dup()時,總返回下一個最小的可用文件描述符。例如:下面語句即可以將輸出重定向到管道:int f_des2;pipe(f_des);close(fileno(stdout);dup(f_des1)此后,所有寫向標(biāo)準(zhǔn)輸出的數(shù)據(jù)
12、都將寫入到管道中。因此,要復(fù)制標(biāo)準(zhǔn)輸出輸入設(shè)備,應(yīng)先關(guān)閉這一設(shè)備,然后再復(fù)制。2022-3-1618復(fù)制文件描述符 2022-3-1619dup2() extern int dup2(int _fd, int _fd2)dup2()有兩個參數(shù),fd和fd2,fd2是小于文件描述符的最大允許值的非負整數(shù)。如果fd2是一個已打開的文件描述符,則首先關(guān)閉該文件,然后再復(fù)制。2022-3-1620綜合應(yīng)用舉例#include #include #include #include #include #define DEF_PAGER /bin/more“#define MAXLINE 10main(in
13、t argc,char * argv)int n;int fd2;pid_t pid;char *pager, *argv0;char lineMAXLINE;FILE *fp;2022-3-1621綜合應(yīng)用舉例if(argc!=2)printf(error usage!n);exit(EXIT_FAILURE); if(fp=fopen(argv1,r)=NULL)perror(open);exit(EXIT_FAILURE); if(pipe(fd)0) perror(pipe);exit(EXIT_FAILURE); if(pid=fork()0)close(fd0);while(fge
14、ts(line,MAXLINE,fp)!=NULL)n=strlen(line);if(write(fd1,line,n)!=n)perror(write);exit(EXIT_FAILURE);close(fd1);if(waitpid(pid,NULL,0)0)perror(wait);exit(EXIT_FAILURE);exit(0);2022-3-1623綜合應(yīng)用舉例elseclose(fd1);if(fd0!=STDIN_FILENO)if(dup2(fd0,STDIN_FILENO) != STDIN_FILENO)perror(dup);exit(EXIT_FAILURE);c
15、lose(fd0);if(pager=getenv(PAGER)=NULL)pager=DEF_PAGER;if(argv0=strrchr(pager,/)!=NULL) argv0+;elseargv0=pager;if(execl(pager,argv0,(char*)0)0)perror(exec);exit(EXIT_FAILURE);exit(0);2022-3-1624流重定向 extern FILE *popen(_const char * _command, _const char * _modes);popen 函數(shù)創(chuàng)建一個子進程,并在子進程中執(zhí)行第一個參數(shù)程序,同時返回一
16、個文件指針,即第一個參數(shù)*_command指向要執(zhí)行的命令的指針。第二個參數(shù)表示I/O模式的類型。如果此命令的輸出將作為其他命令的輸入,即輸出重定向,則需要設(shè)置其第二個參數(shù)為“r”權(quán)限;如果此命令的輸入數(shù)據(jù)要從其他命令的輸出數(shù)據(jù),即輸入重定向,則需要設(shè)置其第二個參數(shù)為“w”權(quán)限;在使用完重定向后,需要使用pclose()關(guān)閉相應(yīng)的流對象,該函數(shù)聲明如下:extern int pclose(FILE * _stream);2022-3-1625例:流重定向的應(yīng)用#include /#include #include #include #include #define PAGER $PAGER:-
17、more“#define MAXLINE 10main(int argc, char *argv)char lineMAXLINE;FILE *fpin,*fpout;if(argc!=2)printf(error usage!n);exit(EXIT_FAILURE); 2022-3-1626例:流重定向的應(yīng)用if(fpin=fopen(argv1,r)=NULL)perror(open);exit(EXIT_FAILURE); if(fpout=popen(PAGER,w)=NULL)perror(popen);exit(EXIT_FAILURE); while(fgets(line,MA
18、XLINE,fpin)!=NULL)if(fputs(line,fpout)=EOF)perror(fputs);exit(EXIT_FAILURE);if(pclose(fpout)=-1)perror(pclose);exit(EXIT_FAILURE); exit(0);2022-3-1627注意事項:1. 如果所有指向管道寫端的文件描述符都關(guān)閉了,而仍然有進程從管道的讀端讀數(shù)據(jù),那么管道中剩余的數(shù)據(jù)都被讀取后,再次read會返回0,就像讀到文件末尾一樣。2. 如果有指向管道寫端的文件描述符沒有關(guān)閉,而持有管道寫端的進程也沒有向管道中寫數(shù)據(jù),這時有進程從管道讀端讀數(shù)據(jù),那么管道中剩余的數(shù)
19、據(jù)都被讀取后,再次read會阻塞,直到管道中有數(shù)據(jù)可讀了才讀取數(shù)據(jù)并返回。3. 如果所有指向管道讀端的文件描述符都關(guān)閉了,這時有進程向管道的寫端write,那么該進程會收到信號SIGPIPE,通常會導(dǎo)致進程異常終止。2022-3-1628注意事項:4. 如果有指向管道讀端的文件描述符沒有關(guān)閉,而持有管道讀端的進程也沒有從管道中讀數(shù)據(jù),這時有進程向管道寫端寫數(shù)據(jù),那么在管道被寫滿時再次write會阻塞,直到管道中有空位置了才寫入數(shù)據(jù)并返回。5. 兩個進程通過一個管道只能實現(xiàn)單向通信,如果有時候也需要子進程寫父進程讀,就必須另開一個管道。2022-3-1629進程間通信管道和信號 進程間通信進程間
20、通信PIPE 進程間通信進程間通信FIFO 信號中斷處理信號中斷處理 FIFOFIFO就是命名管道,或有名管道。它同樣是基于VFS,對應(yīng)的文件類型就是FIFO文件,可以通過mknod命令在磁盤上創(chuàng)建一個FIFO文件。當(dāng)進程想通過該FIFO來通信時就可以標(biāo)準(zhǔn)的API open(close、read、write、unlink等)打開該文件,然后開始讀寫操作。對于FIFO的讀寫實現(xiàn),它與pipe是相同的。區(qū)別在于,F(xiàn)IFO有open這一操作,而pipe是在調(diào)用pipe這個系統(tǒng)調(diào)用時直接創(chuàng)建了一對文件描述符用于通信。并且,F(xiàn)IFO的open操作還有些細致的地方要考慮,例如如果寫者先打開,尚無讀者,那么
21、肯定是不能通信了,所以就需要先去睡眠等待讀者打開該FIFO,反之對讀者亦然。2022-3-1631用途1.FIFO由shell命令使用以便將數(shù)據(jù)從一條管道線傳送到另一條,為此無需創(chuàng)建中間臨時文件。2.FIFO用于客戶進程-服務(wù)器進程應(yīng)用程序中,以在客戶進程和服務(wù)器進程之間傳遞數(shù)據(jù)。2022-3-1632創(chuàng)建FIFO/Create a new FIFO named PATH, with permission bits MODE. */extern int mkfifo(_comst char * _path, _mode_t _mode)mkfifo()會根據(jù)參數(shù)建立特殊的有名管道文件,該文件必
22、須不存在,而參數(shù)mode為該文件的授權(quán),mkfifo()建立的FIFO文件其他進程都可以用讀寫一般文件的方式存取。當(dāng)使用open()函數(shù)打開FIFO文件時,O_NONBLOCK會有影響。如果執(zhí)行成功將返回0,否則返回-1,失敗原因存儲于errno中。2022-3-1633例:命名管道的使用#include #include #include #include #include #define FIFO /tmp/fifo“main()pid_t pid;char buffer80;int fd;unlink(FIFO);mkfifo(FIFO,0744);2022-3-1634例:命名管道的使
23、用if(pid=fork()0)char s=Hello!;fd=open(FIFO,O_WRONLY);printf(this is father write data is %sn,s);printf(fathers pid is %dn,getpid();write(fd,s,sizeof(s);close(fd);exit(0);2022-3-1635例:命名管道的使用else if(pid=0)sleep(2);fd=open(FIFO,O_RDONLY);read(fd,buffer,80);printf(this is child read data is: %sn,buffer
24、);close(fd);printf(childs pid is %dn,getpid();exit(0);2022-3-1636管道基本特點總結(jié)兩類型管道具有以下特點:(1)管道是特殊類型的文件,在滿足先入先出的原則條件下可能進行讀寫,但不能定位讀寫位置。(2)管道是單向的,要實現(xiàn)雙向,需要兩個管道。無名管道只能實現(xiàn)親緣關(guān)系進程間通信(即無名管道的兩個文件描述符可以被兩者都訪問到),而有名管道以磁盤文件的方式存在,可以實現(xiàn)本機任意兩進程間通信。2022-3-1637管道基本特點總結(jié)(續(xù)) (3)無名管道阻塞問題。無名管道無須顯式打開,創(chuàng)建時直接返回文件描述符,而在讀寫時需要確實對方的存在,否
25、則將退出。即如果當(dāng)前進程向無名管道的一端寫數(shù)據(jù)時,必須確定其另一端為某個進程(這個進程可以是當(dāng)前進程)擁有。如果寫入無名管道的數(shù)據(jù)超過其最大值,寫操作將阻塞,如果管道中沒有數(shù)據(jù),讀操作將阻塞,如果管道發(fā)現(xiàn)另一端斷開(另一端文件描述符關(guān)閉),將自動退出。2022-3-1638管道基本特點總結(jié)(續(xù)) (4)有名管道阻塞問題。有名管道在打開時需要確實對方的存在,否則將阻塞。即以讀方式打開某管道,該操作得以繼續(xù)執(zhí)行的條件是:在此之前,已經(jīng)有一個進程以寫的方式打開此管道,否則阻塞,直到條件滿足,因此有名管道將阻塞在打開位置。也可以以讀寫(ORDWR)方式打開有名管道,進程能夠繼續(xù)執(zhí)行(不阻塞),即當(dāng)前進
26、程讀,當(dāng)前進程寫。2022-3-1639進程間通信管道和信號 進程間通信進程間通信PIPE 進程間通信進程間通信FIFO 信號中斷處理信號中斷處理 信號概述信號是Linux系統(tǒng)中用于進程之間相互通信或操作的一種機制。信號可以在任何時候發(fā)給某一進程,而無需知道該進程的狀態(tài)。如果該進程當(dāng)前并未處于執(zhí)行狀態(tài),則該信號就由內(nèi)核保存起來,直到該進程恢復(fù)執(zhí)行并傳遞給它為止;如果一個信號被進程設(shè)置為阻塞,則該信號的傳遞被延遲,直到其阻塞被取消時才被傳遞給進程。進程之間可以互相通過系統(tǒng)調(diào)用kill發(fā)送軟中斷信號。內(nèi)核也可以因為內(nèi)部事件而給進程發(fā)送信號,通知進程發(fā)生了某個事件。信號機制除了基本通知功能外,還可以
27、傳遞附加信息。2022-3-1641Linux信號2022-3-1642/come from asm/signal.h常見的信號Linux系統(tǒng)中常見的信號說明如下:1)SIGHUP:用戶從終端注銷時,所有已啟動的進程都將收到SIGHUP信號。系統(tǒng)缺省狀態(tài)下對該信號的處理就是中止進程。2)SIGINT:程序終止信號。在程序運行過程中,用戶通過鍵盤按下【Ctrl】+【C】鍵將產(chǎn)生該信號。3)SIGQUIT:程序退出信號。在程序運行過程中,用戶通過按下【Ctrl】+【】鍵將產(chǎn)生該信號。4)SIGBUS和SIGSEGV:進程訪問非法地址時,引發(fā)該信號。5)SIGFPE:進行算術(shù)運算中出現(xiàn)致命錯誤,如除
28、零操作、數(shù)據(jù)溢出等。2022-3-1643常見的信號(續(xù))6)SIGKILL:終止用戶進程執(zhí)行的信號。在shell下通過執(zhí)行“kill -9”命令發(fā)送的就是該信號。7)SIGTERM:進程結(jié)束信號。在shell下執(zhí)行“kill 進程pid”命令發(fā)送的就是該信號。8)SIGALRM:定時器信號。9)SIGCLD:子進程退出信號。如果父進程沒有忽略該信號,也沒有處理該信號,則子進程退出后將形成僵尸進程。2022-3-1644信號的分類可靠信號:也稱為實時信號,支持排隊。不可靠信號:非實時信號,不支持排隊。發(fā)送用戶進程判斷后注冊,發(fā)現(xiàn)相同信號已經(jīng)在進程中注冊,就不再注冊,忽略該信號。2022-3-1
29、645可能的信號來源 信號是在軟件層次上對中斷機制的一種模擬,是一種異步通信方式。信號可以在用戶空間進程和內(nèi)核之間直接交互,內(nèi)核也可以利用信號來通知用戶空間的進程發(fā)生了哪些系統(tǒng)事件。信號事件的發(fā)生有兩個來源:1. 硬件來源:用戶按某些終端鍵時將產(chǎn)生信號,如CTRL+C將產(chǎn)生SIGINT(中止信號);硬件異常產(chǎn)生信號,如除數(shù)為0或無效的存儲訪問等。2. 軟件來源:終止進程信號,其他進程調(diào)用kill函數(shù),將信號發(fā)送個另一個進程或進程組;軟件異常產(chǎn)生信號。2022-3-1646信號的處理流程 (1)信號被某個進程產(chǎn)生,并設(shè)置此信號傳遞的對象(一般為對應(yīng)進程的pid),然后傳遞給操作系統(tǒng);(2)操作系
30、統(tǒng)根據(jù)接收進程的設(shè)置(是否阻塞)而選擇性的發(fā)送給接收者,如果接收者阻塞該信號(且該信號是可以阻塞的),操作系統(tǒng)將暫時保留該信號,而不傳遞,直到該進程解除對此信號的阻塞(如果對應(yīng)進程已經(jīng)退出,則丟棄此信號);如果對應(yīng)進程沒有阻塞,操作系統(tǒng)將傳遞此信號;(3)目的進程接收到此信號后,將根據(jù)當(dāng)前進程對此信號設(shè)置的預(yù)處理方式,暫時終止當(dāng)前代碼的執(zhí)行,保護上下文(主要包括臨時寄存器數(shù)據(jù)、當(dāng)前程序位置以及當(dāng)前CPU的狀態(tài))、轉(zhuǎn)而執(zhí)行中斷服務(wù)程序,執(zhí)行完成后再恢復(fù)到被中斷的位置。當(dāng)然,對于可搶占式內(nèi)核,在中斷返回時還將引發(fā)新的調(diào)度。 2022-3-1647信號的生命周期信號處理信號產(chǎn)生信號注冊信號注銷內(nèi)核進
31、程用戶進程2022-3-1648kill產(chǎn)生一個信號 kill()函數(shù)用來向指定進程發(fā)送一個信號。此函數(shù)聲明如下:/come from /usr/include/signal.hextern int kill (_pid_t _pid, int _sig)此函數(shù)的第一個參數(shù)為要傳遞信號的進程號(PID),第二個參數(shù)即發(fā)送的信號值。 pid可以取以下幾種值:pido:將信號發(fā)送給進程的PID值為pid的進程。pid=0:將信號發(fā)送給和當(dāng)前進程在同一進程組的所有進程。pid=-1:將信號發(fā)送給系統(tǒng)內(nèi)的所有進程。pid0:將信號發(fā)送給進程組號PGID為pid絕對值的所有進程。如果成功完成返回值0,否
32、則返回-1,并設(shè)置errno以指示錯誤。2022-3-1649#include #include void main(int argc,char *argv)int pid,signo;if(argc!=3)printf(usage: killsender pid signon);return;sscanf(argv1,%d,&pid); /獲取參數(shù)pidsscanf(argv2,%d,&signo); /獲取參數(shù)signoif(kill(pid,signo)0) /發(fā)送信號perror(kill);return;printf(ok: send out signal via kill syst
33、em call!n); 2022-3-1650例:編寫程序例:編寫程序killsender。通過。通過kill系統(tǒng)調(diào)用向指定進系統(tǒng)調(diào)用向指定進程(程(pid)發(fā)送信號。)發(fā)送信號。raise自舉一個信號 raise()函數(shù)用來給當(dāng)前進程發(fā)送一個信號,即喚醒一個進程。此函數(shù)聲明如下:/come from /usr/include/signal.h/*Raise signal SIG, i.e., send SIG to yourself. */extern int raise(int _sig)此函數(shù)相當(dāng)于采用以下方式執(zhí)行kill()函數(shù):if(kill(getpid(), int _sig)=
34、-1)perror(“raise”);2022-3-1651例:設(shè)計一個程序,創(chuàng)建一個子進程,父進程向子進程發(fā)例:設(shè)計一個程序,創(chuàng)建一個子進程,父進程向子進程發(fā)出信號,子進程收到此信號,結(jié)束子進程的運行。出信號,子進程收到此信號,結(jié)束子進程的運行。#include #include #include #include #include int main()pid_t result;int ret;result=fork();int newret;2022-3-1652if(result0)perror(fork);exit(EXIT_FAILURE);else if(result=0)rais
35、e(SIGSTOP);exit(0);elseprintf(childs pid=%dn,result);if(waitpid(result,NULL,WNOHANG)=0)if(ret=kill(result,SIGKILL)=0)printf(kill function finished %d process with return value=%dn,result,ret);elseperror(kill);2022-3-1653alarm()定時 alarm()函數(shù)用來傳遞定時信號,即在多少時間內(nèi)產(chǎn)生SIGALRM信號,此函數(shù)每調(diào)用一次,產(chǎn)生一個信號,并不是循環(huán)產(chǎn)生SIGALRM信號。
36、/come from /usr/include/unistd.hextern unsigned int alarm(unsigned int _seconds)此函數(shù)只有一個參數(shù),即在多少時間(秒)內(nèi)發(fā)送SIGALRM信號給當(dāng)前進程,默認情況下,當(dāng)進程接受到alarm信號后將終止執(zhí)行;如果sec為0,則取消所有先前發(fā)出的報警請求。如果在調(diào)用alarm()函數(shù)前沒有調(diào)用過alarm()函數(shù),如果執(zhí)行成功,將返回0,否則返回-1,并置errno標(biāo)致錯誤。2022-3-1654例:alarm的使用#include #include int main()printf(first time return
37、:%dn,alarm(4);sleep(1);printf(after sleep(1), remain:%dn,alarm(2);printf(renew alarm, remain:%dn,alarm(1);2022-3-1655ualarm定時 ualarm將使當(dāng)前進程在指定時間(第一個參數(shù),以us為單位)內(nèi)產(chǎn)生SIGALRM信號,然后每隔指定時間(第二個參數(shù),以us為單位)重復(fù)產(chǎn)生SIGALRM信號。如果執(zhí)行成功將返回0,該函數(shù)聲明如下:extern _useconds_t ualarm(_useconds_t _value, _useconds_t _interval)2022-3-
38、1656信號處理與signal安裝信號 信號處理辦法 :(1)忽略此信號。忽略此信號。大多數(shù)信號都可使用這種方式進行處理,但有兩種信號不能被忽略,SIGKILL和SIGSTOP。這兩種信號不能被忽略的原因是:它們向超級用戶提供一種使進程終止或停止的可靠方法。(2)捕捉信號。捕捉信號。通知內(nèi)核在某種信號發(fā)生時調(diào)用一個用戶函數(shù)。在用戶函數(shù)中,可執(zhí)行用戶希望對這種事件進行的處理,這需要安裝此信號。例如捕捉到SIGCHLD信號,則表示子進程已經(jīng)終止,所以此信號的捕捉函數(shù)可以調(diào)用waitpid()以取得該子進程的進程PID以及它的終止?fàn)顟B(tài)和資源。(3)執(zhí)行系統(tǒng)默認操作。執(zhí)行系統(tǒng)默認操作。Linux系統(tǒng)對
39、任何一個信號都規(guī)定了一個默認的操作。 2022-3-1657signal安裝信號 typedef void(*_sighandler_t)(int );extern _sighander_t signal(int _sig, sighandler_t _handler)此函數(shù)有兩個參數(shù), 第一個參數(shù)sig為接收到的信號,第二個參數(shù)為接收到此信號后的處理代碼入口或下面幾個宏:/* Fake signal functions. */#define SIG_ERR (_sighandler_t) -1) /*Error return. */#define SIG_DFL (_sighandler_t
40、) 0) /*Default action. */#define SIG_IGN (_sighandler_t) 1) /*Ignore signal. */2022-3-1658例:編寫程序:killrecerver和killsender。其中killrecerver用于接收SIGUSR1(值為10)信號,而killsender通過kill系統(tǒng)調(diào)用向指定進程(pid)發(fā)送信號。#include #include #include #include /SIGUSR1信號處理函數(shù)void CbSigUsr1(int signo) /輸出接收到的信號信息printf(nreceive signal
41、=%d.n,signo);2022-3-1659void main()/安裝SIGUSR1信號if(signal(SIGUSR1,CbSigUsr1)=SIG_ERR)perror(signal);return;printf(my pid is %dn,getpid();printf(waiting for SIGUSR1.n);/暫停,等待信號pause();2022-3-1660例:signal的應(yīng)用#include #include #include #include void fun_ctrl_c();int main()(void)signal(SIGINT,fun_ctrl_c);
42、printf(Now Im starting.n);while(1)printf(this is an endless loop unless Ctrl+c are pressd!n);sleep(2);exit(0);2022-3-1661例:signal的應(yīng)用void fun_ctrl_c()printf(tCtrl+c were pressed!n);printf(t This is just an example for signal function!n);printf(treset signal SIGINTn);(void)signal(SIGINT,SIG_DFL);2022-
43、3-1662sigaction安裝信號 extern int sigaction(int _sig, struct sigaction *_act, struct sigaction *_oact)此函數(shù)的第一個參數(shù)為接收到的信號,第二、三個參數(shù)均為信號結(jié)構(gòu)sigaction(用于描述要采取的操作及相關(guān)信息,見后續(xù)說明)變量。第二個參數(shù)用來指定欲設(shè)置的信號處理信息,第三個參數(shù)將返回執(zhí)行此程序前信號處理信息。如果第二個參數(shù)act不為空指針,則指定信號關(guān)聯(lián)的操作為此參數(shù)指向的結(jié)構(gòu)。如果參數(shù)oact不為空指針,則用來存儲以前設(shè)置的與此信號關(guān)聯(lián)的操作。如果參數(shù)act為空指針,則信號處理保持不變;因此,
44、該調(diào)用可用于詢問對指定信號的當(dāng)前處理。2022-3-1663struct sigaction Struct sigactionunion_sighandler_t _sa_handler;void(*_sa_sigaction)(int , struct siginfo *, void *); _u;sigset_t sa_mask;unsigned long sa_flags;void(*sa_restorer)(void);#define sa_handler _u.sa_handler#define sa_sigaction _u._sa_sigaction2022-3-1664例:si
45、gaction的應(yīng)用#include #include #include void myhandler(int sig);int main()struct sigaction act,oact;act.sa_handler=myhandler;sigemptyset(&act.sa_mask);act.sa_flags=0;sigaction(SIGUSR1,&act,&oact);while(1)printf(hello world!n);pause();2022-3-1665void myhandler(int sig)printf(the signal %d was caught.n,s
46、ig);信號集與屏蔽信號 中斷是可以被屏蔽(阻塞)的(部分硬件中斷是必須立即處理的,例如復(fù)位中斷),因此,Linux的信號是可以屏蔽,即阻塞信號。但這與前面提到的忽略是有區(qū)別的。信號忽略:系統(tǒng)仍然傳遞該信號,只是相應(yīng)進程對該信號不作任何處理而已。信號阻塞:系統(tǒng)不傳遞該信號,顯示該進程無法接收到該信號直到進程的信號集發(fā)生改變。2022-3-1666sigprocmask設(shè)置進程阻塞的信號集 extern int sigprocmask(int _how, _const sigset_t * _restrict_set, sigset_t * _restrict_oset)此函數(shù)第一個參數(shù)為更改該集合的方式,如下所示:/come from /usr/include/asm/signal.h#define SIG_BLOCK 0 /*for blocking signals */#define SIG_UNBLOCK 1 /*for unblockin
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025某餐飲品牌特許加盟合同協(xié)議書范本
- 2025年二月份跨境獨立站運營借款協(xié)議GMV增長對賭協(xié)議
- 胸腔鏡手術(shù)病人的護理
- 超市員工管理規(guī)章制度
- 基于過盈聯(lián)接的機油泵襯套壓裝質(zhì)量監(jiān)控設(shè)計與應(yīng)用
- 二零二五版收購企業(yè)合同范例
- 基金投資組合基金池
- 有關(guān)車位租賃合同范例
- 二零二五池塘承包合同范例
- 內(nèi)務(wù)管理制度500字
- 初中綜合實踐-【課堂實錄】手工橡皮章教學(xué)設(shè)計學(xué)情分析教材分析課后反思
- 民用無人機駕駛員管理規(guī)定
- 2023年四川二造《建設(shè)工程計量與計價實務(wù)(土木建筑)》高頻核心題庫300題(含解析)
- 凸透鏡成像規(guī)律動畫可拖動最佳版swf
- 6層框架住宅畢業(yè)設(shè)計結(jié)構(gòu)計算書
- 《春秋三傳導(dǎo)讀》課件
- 教師情緒和壓力疏導(dǎo)課件
- 麻醉科進修匯報課件
- 中小學(xué)生心理健康教育主題班會PPT教學(xué)課件
- ISO-IEC 27002-2022中文版完整詳細
- 口腔正畸病例書寫模板
評論
0/150
提交評論