Linux第5章進(jìn)程、信號(hào)和消息隊(duì)列_第1頁(yè)
Linux第5章進(jìn)程、信號(hào)和消息隊(duì)列_第2頁(yè)
Linux第5章進(jìn)程、信號(hào)和消息隊(duì)列_第3頁(yè)
Linux第5章進(jìn)程、信號(hào)和消息隊(duì)列_第4頁(yè)
Linux第5章進(jìn)程、信號(hào)和消息隊(duì)列_第5頁(yè)
已閱讀5頁(yè),還剩34頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第五章進(jìn)程、信號(hào)和消息隊(duì)列12§5.1什么是進(jìn)程“一個(gè)其中運(yùn)行著一個(gè)或多個(gè)線程的地址空間和這些線程所需要的系統(tǒng)資源?!薄罢谶\(yùn)行的程序?!边M(jìn)程由程序代碼、數(shù)據(jù)、變量(占用著系統(tǒng)內(nèi)存)、打開的文件(文件描述符)和環(huán)境組成。3§5.2進(jìn)程的結(jié)構(gòu)多進(jìn)程的管理方式示例:兩個(gè)用戶同時(shí)運(yùn)行g(shù)rep程序搜索結(jié)束之前運(yùn)行ps命令PID:2~32768代碼區(qū):共享函數(shù)庫(kù):共享數(shù)據(jù)區(qū)、??臻g、環(huán)境變量等:不共享4§5.2進(jìn)程的結(jié)構(gòu)多進(jìn)程的管理方式示例:兩個(gè)用戶同時(shí)運(yùn)行g(shù)rep程序搜索結(jié)束之前運(yùn)行ps命令PID:2~32768代碼區(qū):共享函數(shù)庫(kù):共享數(shù)據(jù)區(qū)、棧空間、環(huán)境變量等:不共享5§5.2進(jìn)程的結(jié)構(gòu)進(jìn)程表Linux進(jìn)程表是一個(gè)數(shù)據(jù)結(jié)構(gòu),其中保存了當(dāng)前所有進(jìn)程的相關(guān)信息,包括PID、狀態(tài)、命令字符串等(參見ps命令輸出項(xiàng))。操作系統(tǒng)通過(guò)PID對(duì)進(jìn)程進(jìn)行管理,PID是進(jìn)程表的索引。系統(tǒng)可同時(shí)運(yùn)行的進(jìn)程數(shù)只與可用于建立進(jìn)程表項(xiàng)的內(nèi)存容量有關(guān)。父進(jìn)程與子進(jìn)程Linux啟動(dòng)時(shí)運(yùn)行一個(gè)名為init的進(jìn)程,該進(jìn)程是系統(tǒng)運(yùn)行的第一個(gè)進(jìn)程,它的PID為1。一般進(jìn)程(除init外)都是由一個(gè)“父進(jìn)程”創(chuàng)建的,被父進(jìn)程創(chuàng)建的進(jìn)程稱為“子進(jìn)程”,init進(jìn)程是其他所有進(jìn)程的祖先進(jìn)程。UIDPIDPPIDCSTIMETTYTIMECMDroot10020:41?00:00:00/sbin/initmolin19331932020:45pts/100:00:00-bashmolin20471020:47?00:00:01gnome-terminal6§5.2進(jìn)程的結(jié)構(gòu)進(jìn)程狀態(tài)$psaxPIDTTYSTATTIMECOMMAND1?Ss0:00/sbin/init37?SN0:00[ksmd]892?Ssl0:00gdm-binary2049pts/0Ss+0:00bash8204?S<0:00udevd--daemon12682pts/1R+0:00psaxSTAT代碼說(shuō)明S睡眠。通常是在等待某個(gè)事件的發(fā)生。R運(yùn)行/可運(yùn)行。即在運(yùn)行隊(duì)列中,處于正在運(yùn)行或即將運(yùn)行狀態(tài)。D不可中斷的睡眠(等待)。通常是在等待輸入或輸出完成。T停止。通常是被shell作業(yè)控制所停止,或處于調(diào)試器控制下。Z僵尸(zombie)進(jìn)程。N低優(yōu)先級(jí)任務(wù)。s進(jìn)程是會(huì)話期首進(jìn)程。+進(jìn)程屬于前臺(tái)進(jìn)程組。l進(jìn)程是多線程的。<高優(yōu)先級(jí)任務(wù)。7system函數(shù)可以調(diào)用標(biāo)準(zhǔn)庫(kù)函數(shù)system在程序內(nèi)啟動(dòng)另一個(gè)程序,從而創(chuàng)建一個(gè)新進(jìn)程。#include<stdlib.h>intsystem(constchar*command);說(shuō)明command 待運(yùn)行的程序(命令字符串)。返回值 無(wú)法啟動(dòng)shell時(shí),返回127;其它錯(cuò)誤時(shí)返回-1;否 則,返回命令的退出碼。system函數(shù)運(yùn)行command命令并等待該命令完成,本質(zhì)是調(diào)用:/bin/sh–ccommand。注:使用system函數(shù)并非啟動(dòng)其他進(jìn)程的理想手段,因其必須先啟動(dòng)一個(gè)shell,再使用該shell執(zhí)行相應(yīng)的命令?!?.3創(chuàng)建進(jìn)程8§5.3創(chuàng)建進(jìn)程system函數(shù)示例#include<stdlib.h>#include<stdio.h>intmain(){printf("Runningpswithsystem\n");system("ps-ef");printf("Done.\n");exit(0);}$./exam09_01RunningpswithsystemUIDPIDPPIDCSTIMETTYTIMECMDroot10020:41?00:00:00/sbin/init....molin1214311937022:20pts/100:00:00./exam09_01molin12144

12143022:20pts/100:00:00sh-cps-efmolin1214512144022:20pts/100:00:00ps-efDone.9替換進(jìn)程映像可以調(diào)用exec系列函數(shù)把當(dāng)前進(jìn)程替換為一個(gè)新進(jìn)程。#include<unistd.h>externchar**environ;intexecl(constchar*path,constchar*arg,...);intexeclp(constchar*file,constchar*arg,...);intexecle(constchar*path,constchar*arg,...,char*constenvp[]);intexecv(constchar*path,char*constargv[]);intexecvp(constchar*file,char*constargv[]);intexecve(constchar*filename,char*constargv[],char*constenvp[]);說(shuō)明path 待運(yùn)行的程序全路徑名(命令字符串)。file 待運(yùn)行的程序名,通過(guò)PATH環(huán)境變量搜索其路徑。arg 命令參數(shù)。argv[] 命令參數(shù)。envp 傳遞給待運(yùn)行程序的環(huán)境變量。返回值 成功時(shí)不返回(原程序不再執(zhí)行);出錯(cuò)時(shí)返回-1,并設(shè)置 errno變量。§5.3創(chuàng)建進(jìn)程參數(shù)個(gè)數(shù)可變,以一空指針結(jié)束。其他函數(shù)通常是用execve函數(shù)實(shí)現(xiàn)的。10§5.3創(chuàng)建進(jìn)程替換進(jìn)程映像用法#include<unistd.h>/*Exampleofanargumentlist*//*Notethatweneedaprogramnameforargv[0]*/char*constps_argv[]= {“ps”,“ax”,0};/*Exampleenvironment,notterriblyuseful*/char*constps_envp[]= {“PATH=/bin:/usr/bin”,“TERM=console”,0};/*Possiblecallstoexecfunctions*/execl(“/bin/ps”,“ps”,“ax”,0); /*assumespsisin/bin*/execlp(“ps”,“ps”,“ax”,0); /*assumes/binisinPATH*/execle(“/bin/ps”,“ps”,“ax”,0,ps_envp); /*passesownenvironment*/execv(“/bin/ps”,ps_argv);execvp(“ps”,ps_argv);execve(“/bin/ps”,ps_argv,ps_envp);11§5.3創(chuàng)建進(jìn)程替換進(jìn)程映像示例#include<unistd.h>#include<stdio.h>#include<stdlib.h>intmain(){printf(“Runningpswithexeclp\n”);execlp(“ps”,“ps”,“ax”,0);printf(“Done.\n”);exit(0);}$./exam09_02RunningpswithexeclpPIDTTYSTATTIMECOMMAND1?S0:03init[5]...1262pts/1Ss0:00/bin/bash1514pts/1R+0:00psax沒有輸出“Done”說(shuō)明ps命令結(jié)束后,不再返回exam09_02程序,所以不會(huì)打印出“Done”。新進(jìn)程的PID、PPID及nice值和原先的完全一樣。exec系列函數(shù)啟動(dòng)的新進(jìn)程的參數(shù)表和環(huán)境變量的總長(zhǎng)度是有限制的。上限由ARG_MAX給出,POSIX規(guī)定至少為4KB,Linux中為128KB。原進(jìn)程中已打開的文件描述符在新進(jìn)程中仍保持打開(除非“執(zhí)行時(shí)關(guān)閉標(biāo)志”被置位)。原進(jìn)程中打開的目錄流在新進(jìn)程中被關(guān)閉。12復(fù)制進(jìn)程映像可以調(diào)用fork函數(shù)創(chuàng)建一個(gè)新進(jìn)程。#include<unistd.h>pid_tfork(void);說(shuō)明返回值 成功時(shí),父進(jìn)程中返回子進(jìn)程的PID,子進(jìn)程中返回0;失 敗時(shí)返回-1,并設(shè)置errno變量。fork系統(tǒng)調(diào)用復(fù)制當(dāng)前進(jìn)程,在進(jìn)程表中添加一個(gè)新的表項(xiàng),新表項(xiàng)的多數(shù)屬性與當(dāng)前進(jìn)程相同。新進(jìn)程與原進(jìn)程執(zhí)行的代碼完全相同,但新進(jìn)程有自己的數(shù)據(jù)空間、環(huán)境和文件描述符。通常,使用fork和exec系列函數(shù)一起創(chuàng)建多進(jìn)程環(huán)境。典型的fork代碼。§5.3創(chuàng)建進(jìn)程典型錯(cuò)誤為E_AGAIN——子進(jìn)程超過(guò)CHILD_MAX限制ENOMEM——進(jìn)程表無(wú)足夠空間pid_tnew_pid;new_pid=fork();switch(new_pid){case-1:/*Error*/break;case0:/*Wearechild*/break;default:/*Weareparent*/break;}13復(fù)制進(jìn)程映像示例§5.3創(chuàng)建進(jìn)程#include<sys/types.h>#include<unistd.h>#include<stdio.h>#include<stdlib.h>intmain(){pid_tpid;char*message;intn;

printf(“forkprogramstarting\n”);pid=fork();switch(pid){case-1:perror(“forkfailed”);exit(1);case0:message=“Thisisthechild”;n=5;break;default:message=“Thisistheparent”;n=3;break;}

for(;n>0;n--){puts(message);sleep(1);}

exit(0);}$./fork1forkprogramstartingThisisthechildThisistheparentThisistheparentThisisthechildThisistheparentThisisthechild$ThisisthechildThisisthechild運(yùn)行結(jié)果14等待進(jìn)程在父進(jìn)程中調(diào)用wait函數(shù)可以讓父進(jìn)程等待任一子進(jìn)程的結(jié)束。#include<sys/types.h>#include<sys/wait.h>pid_twait(int*status);說(shuō)明status 輸出參數(shù),用于獲取子進(jìn)程的退出狀態(tài)。返回值 成功時(shí),返回已結(jié)束子進(jìn)程的PID;出錯(cuò)時(shí)返回-1,并設(shè)置 errno變量。以下宏可用于解釋子進(jìn)程退出狀態(tài)信息。§5.3創(chuàng)建進(jìn)程宏說(shuō)明WIFEXITED(status)

如果子進(jìn)程正常結(jié)束,則取非零值。WEXITSTATUS(status)

如果WIFEXITED非零,則得到子進(jìn)程的退出碼。WIFSIGNALED(status)

如果子進(jìn)程因未捕獲的信號(hào)而終止,則取非零值。WTERMSIG(status)

如果WIFSIGNALED非零,則得到引起子進(jìn)程終止的信號(hào)代碼。WIFSTOPPED(status)

如果子進(jìn)程已意外終止,則取非零值。WSTOPSIG(status)

如果WIFSTOPPED非零,則得到引起子進(jìn)程終止的信號(hào)代碼。15等待進(jìn)程在父進(jìn)程中調(diào)用waitpid函數(shù)可以讓父進(jìn)程等待指定的子進(jìn)程的結(jié)束。#include<sys/types.h>#include<sys/wait.h>pid_twaitpid(pid_tpid,int*status,intoptions);說(shuō)明pid 要等待的子進(jìn)程的PID,值為-1時(shí)意為任一子進(jìn)程。status 輸出參數(shù),用于獲取子進(jìn)程的退出狀態(tài)。options 常見的選項(xiàng)為WNOHANG,意為不掛起調(diào)用者進(jìn)程。返回值 成功時(shí),返回已結(jié)束子進(jìn)程的PID;若指定了WNOHANG選 項(xiàng),但沒有子進(jìn)程終止,則返回0。出錯(cuò)時(shí)返回-1,并設(shè)置 errno變量?!?.3創(chuàng)建進(jìn)程若要周期性地檢查某個(gè)子進(jìn)程是否已終止,可以使用如下調(diào)用方式:

waitpid(child_pid,(int*)0,WNOHANG);16等待進(jìn)程示例intmain(){pid_tpid;char*message;intn;intexit_code;

printf(“forkprogramstarting\n”);pid=fork();switch(pid){case-1:perror(“forkfailed”);exit(1);case0:message=“Thisisthechild”;n=5;exit_code=37;break;default:message=“Thisistheparent”;n=3;exit_code=0;break;}§5.3創(chuàng)建進(jìn)程for(;n>0;n--){puts(message);sleep(1);}

if(pid!=0){intstat_val;pid_tchild_pid;

child_pid=wait(&stat_val);

printf(“Childhasfinished:PID =%d\n”, child_pid);if(WIFEXITED(stat_val))printf(“Childexitedwithcode%d\n”, WEXITSTATUS(stat_val));elseprintf(“Childterminatedabnormally\n”);}exit(exit_code);}$./waitforkprogramstartingThisisthechildThisistheparentThisistheparentThisisthechildThisistheparentThisisthechildThisisthechildThisisthechildChildhasfinished:PID=1582Childexitedwithcode37$運(yùn)行結(jié)果17僵尸進(jìn)程子進(jìn)程終止時(shí),它與父進(jìn)程之間的關(guān)聯(lián)還會(huì)保持(進(jìn)程表中代表子進(jìn)程的表項(xiàng)不會(huì)立刻釋放,其中含退出碼),直到父進(jìn)程也正常終止或父進(jìn)程調(diào)用了wait或waitpid函數(shù)。已結(jié)束運(yùn)行但進(jìn)程表項(xiàng)仍存在的子進(jìn)程稱為“僵尸進(jìn)程”。如果一個(gè)僵尸進(jìn)程的父進(jìn)程因異常而終止,該僵尸進(jìn)程將由init進(jìn)程接管,它將一直保持在進(jìn)程表中直到被init進(jìn)程發(fā)現(xiàn)并釋放。應(yīng)盡量避免產(chǎn)生僵尸進(jìn)程。§5.3創(chuàng)建進(jìn)程18概述信號(hào)是UNIX和Linux系統(tǒng)為響應(yīng)某些條件而產(chǎn)生的一個(gè)事件。信號(hào)一般是因某些錯(cuò)誤條件而產(chǎn)生的,如內(nèi)存段沖突、浮點(diǎn)處理器錯(cuò)誤或非法指令等。信號(hào)可作為進(jìn)程間通信的一種機(jī)制,由一個(gè)進(jìn)程發(fā)送給另一個(gè)進(jìn)程。信號(hào)可被生成、捕獲或響應(yīng),對(duì)于一些信號(hào)也可被忽略。信號(hào)的名稱在頭文件signal.h中定義,均以SIG開頭?!?.4信號(hào)19信號(hào)種類下表中的信號(hào)未安排捕獲時(shí),進(jìn)程會(huì)立刻終止,并生成核心轉(zhuǎn)儲(chǔ)文件core?!?.4信號(hào)信號(hào)名稱說(shuō)明SIGABORT*進(jìn)程異常終止SIGALRM超時(shí)。一般由alarm設(shè)置的定時(shí)器產(chǎn)生。SIGFPE*浮點(diǎn)運(yùn)算異常SIGHUP終端關(guān)閉或斷開連接。由處于非連接狀態(tài)的終端發(fā)給控制進(jìn)程或由控制進(jìn)程在自身結(jié)束時(shí)發(fā)給每個(gè)前臺(tái)進(jìn)程。SIGILL*非法指令。通常由一個(gè)崩潰的程序或無(wú)效的共享內(nèi)存模塊引起。SIGINT程序終止,一般由從終端敲入的中斷字符(Ctrl+C)產(chǎn)生。SIGKILL終止進(jìn)程(此信號(hào)不能被捕獲或忽略),一般在shell中用它來(lái)強(qiáng)制終止異常進(jìn)程。SIGPIPE向管道寫數(shù)據(jù)時(shí)沒有與之對(duì)應(yīng)的讀進(jìn)程時(shí)產(chǎn)生。SIGQUIT程序退出。一般由終端敲入的退出字符(Ctrl+\)產(chǎn)生。SIGSEGV*無(wú)效內(nèi)存段訪問。一般是因?yàn)閷?duì)內(nèi)存中的無(wú)效地址進(jìn)行讀寫引起,如數(shù)組越界、解引用無(wú)效指針。SIGTERMkill命令默認(rèn)發(fā)送的信號(hào),要求進(jìn)程結(jié)束運(yùn)行。UNIX在關(guān)機(jī)時(shí)也用此信號(hào)要求服務(wù)停止運(yùn)行。SIGUSR1用戶定義信號(hào)1,用于進(jìn)程間通信SIGUSR2用戶定義信號(hào)2,用于進(jìn)程間通信20信號(hào)種類其它常見信號(hào)。§5.4信號(hào)信號(hào)名稱說(shuō)明SIGCHLD子進(jìn)程停止或退出時(shí)產(chǎn)生,默認(rèn)被忽略SIGCONT如果進(jìn)程被暫停則繼續(xù)執(zhí)行。SIGSTOP停止執(zhí)行(此信號(hào)不能被捕獲或忽略)SIGTSTP終端掛起。通常因按下Ctrl+Z組合鍵而產(chǎn)生。SIGTTIN后臺(tái)進(jìn)程嘗試讀操作。shell用以表明后臺(tái)進(jìn)程因需要從終端讀取輸入而暫停運(yùn)行。SIGTTOU后臺(tái)進(jìn)程嘗試寫操作。shell用以表明后臺(tái)進(jìn)程因需要產(chǎn)生輸出而暫停運(yùn)行。在命令行使用:kill-<信號(hào)名><PID>,可以向PID進(jìn)程發(fā)送指定信號(hào)。如:kill–HUP512在命令行使用:killall-<信號(hào)名><命令名>,可以向所有運(yùn)行<命令名>的進(jìn)程發(fā)送指定信號(hào)。如:killall–HUPinetd21捕獲信號(hào)在程序中可以調(diào)用signal函數(shù)來(lái)捕獲信號(hào)。§5.4信號(hào)說(shuō)明sig 準(zhǔn)備捕獲或忽略的信號(hào)。func 捕獲到信號(hào)后將要調(diào)用的回調(diào)函數(shù)??梢栽O(shè)為以下特殊值:SIG_IGN 忽略信號(hào)SIG_DFL 恢復(fù)默認(rèn)行為返回值 成功時(shí)返回原先定義信號(hào)處理函數(shù),如果原先未定義則返回 SIG_ERR,并設(shè)置errno為一正數(shù)值;如給出的是一個(gè)無(wú)效的 信號(hào)或不可捕獲或不可忽略的信號(hào),則返回SIG_ERR,并設(shè) 置errno為EINVAL。注意:回調(diào)函數(shù)中捕獲到一次信號(hào)后,對(duì)相應(yīng)的信號(hào)的處理方式會(huì)自動(dòng)恢復(fù)到默認(rèn)行為。#include<signal.h>void(*signal(intsig,void(*func)(int)))(int);#include<signal.h>typedefvoid(*CALLBACK)(int);CALLBACKsignal(intsig,CALLBACKfunc);22捕獲信號(hào)示例§5.4信號(hào)#include<signal.h>#include<stdio.h>#include<unistd.h>voidouch(intsig){printf(“OUCH!-Igotsignal%d\n”,sig);(void)signal(SIGINT,SIG_DFL);}intmain(){(void)signal(SIGINT,ouch);while(1){printf(“HelloWorld!\n”);sleep(1);}}$./ctrlc1HelloWorld!HelloWorld!HelloWorld!HelloWorld!^COUCH!-Igotsignal2HelloWorld!HelloWorld!HelloWorld!HelloWorld!^C$運(yùn)行結(jié)果23發(fā)送信號(hào)進(jìn)程可以通過(guò)kill系統(tǒng)調(diào)用向包括自身在內(nèi)的進(jìn)程發(fā)送一個(gè)信號(hào)?!?.4信號(hào)說(shuō)明pid 接收信號(hào)的進(jìn)程PID。sig 要發(fā)送的信號(hào)。返回值 成功時(shí)返回0;失敗時(shí)返回-1,并設(shè)置errno變量。EINVAL 給定的信號(hào)無(wú)效EPERM 發(fā)送進(jìn)程權(quán)限不夠ESRCH 目標(biāo)進(jìn)程不存在注:發(fā)送信號(hào)的進(jìn)程應(yīng)具有相應(yīng)的權(quán)限。一般而言,兩個(gè)進(jìn)程應(yīng)擁有相同的UID(即只能發(fā)送信號(hào)給屬于自己的進(jìn)程),但超級(jí)用戶可以發(fā)送信號(hào)給任何進(jìn)程。#include<sys/types.h>#include<signal.h>intkill(pid_tpid,intsig);24發(fā)送信號(hào)進(jìn)程可以通過(guò)alarm函數(shù)在經(jīng)過(guò)一定時(shí)間后發(fā)送一個(gè)SIGALRM信號(hào),即設(shè)置一個(gè)鬧鐘(定時(shí)器)?!?.4信號(hào)說(shuō)明seconds 指定幾秒后發(fā)送SIGALRM信號(hào),0表示取消設(shè)置。返回值 成功時(shí)返回以前設(shè)置的鬧鐘時(shí)間的余留秒數(shù);失敗時(shí)返回0。注:在接收到SIGALRM信號(hào)之前再次調(diào)用alarm函數(shù),鬧鐘會(huì)重新開始計(jì)時(shí)。#include<unistd.h>unsignedalarm(unsignedseconds);25sigaction系統(tǒng)調(diào)用在Linux中,提供了一個(gè)比signal更健壯的用于捕獲信號(hào)的編程接口:sigaction。§5.4信號(hào)#include<unistd.h>intsigaction(intsig,conststructsigaction*act, structsigaction*oldact);說(shuō)明sig 準(zhǔn)備捕獲或忽略的信號(hào)。act 將要設(shè)置的信號(hào)處理動(dòng)作。oldact 用于取回原先的信號(hào)處理動(dòng)作。返回值 成功時(shí)返回0;失敗時(shí)返回-1,并設(shè)置errno變量,如給出的 是一個(gè)無(wú)效的信號(hào)或不可捕獲或不可忽略的信號(hào),errno為 EINVAL。注:和signal不一樣,由sigaction設(shè)置的信號(hào)處理函數(shù)默認(rèn)是不被重置的。如果需要自動(dòng)重置,應(yīng)在sa_flags成員中包含值SA_RESETHAND。structsigaction{void(*sa_handler)(int);//信號(hào)處理函數(shù),同signalsigset_tsa_mask; //回調(diào)過(guò)程中將被屏蔽的信號(hào)集

intsa_flags; //可決定回調(diào)行為的位標(biāo)志值

…}SA_NOCLDSTOP子進(jìn)程停止時(shí)不產(chǎn)生SIGCHLD信號(hào)SA_RESETHAND在信號(hào)處理函數(shù)入口處將對(duì)此信號(hào)的處理方式重置為SIG_DFL SA_RESTART重啟可中斷的函數(shù)而不是給EINTR錯(cuò)誤SA_NODEFER捕獲到信號(hào)時(shí)不將它添加到信號(hào)屏蔽字中26sigaction系統(tǒng)調(diào)用示例§5.4信號(hào)#include<signal.h>#include<stdio.h>#include<unistd.h>voidouch(intsig){printf(“OUCH!-Igotsignal%d\n”,sig);}intmain(){structsigactionact;act.sa_handler=ouch;sigemptyset(&act.sa_mask);act.sa_flags=0;sigaction(SIGINT,&act,0);while(1){printf(“HelloWorld!\n”);sleep(1);}}$./ctrlc2HelloWorld!HelloWorld!HelloWorld!^COUCH!-Igotsignal2HelloWorld!HelloWorld!^COUCH!-Igotsignal2HelloWorld!HelloWorld!^\Quit$運(yùn)行結(jié)果27信號(hào)集在頭文件signal.h中定義了類型sigset_t和用來(lái)處理信號(hào)集的函數(shù)?!?.4信號(hào)#include<signal.h>intsigemptyset(sigset_t*set);intsigfillset(sigset_t*set);intsigaddset(sigset_t*set,intsig);intsigdelset(sigset_t*set,intsig);intsigismember(constsigset_t*set,intsig);說(shuō)明set 信號(hào)集sig 信號(hào)。返回值 失敗時(shí)返回-1,并設(shè)置errno變量,只有一個(gè)錯(cuò)誤代碼 EINVAL,表示給定的信號(hào)無(wú)效。成功時(shí),sigismeber函數(shù) 返回1或0;其他函數(shù)返回0。typedefstruct{unsignedlongsig[_NSIG_WORDS];}sigset_t;28概述消息隊(duì)列(messagequeues)是Linux中的一種IPC(Inter-ProcessCommunication)機(jī)制。消息隊(duì)列提供了一種在兩個(gè)不相關(guān)的進(jìn)程間傳遞數(shù)據(jù)的有效方法。消息隊(duì)列獨(dú)立于發(fā)送和接收進(jìn)程而存在。使用消息隊(duì)列可以從一個(gè)進(jìn)程向另一個(gè)進(jìn)程發(fā)送數(shù)據(jù)塊。每個(gè)數(shù)據(jù)塊有一個(gè)最大長(zhǎng)度的限制,系統(tǒng)中所有隊(duì)列所包含的全部數(shù)據(jù)塊的總長(zhǎng)度也有一個(gè)上限值。Linux中有兩個(gè)宏定義MSGMAX和MSGMNB,它們分別定義了一條消息的最大長(zhǎng)度和一個(gè)隊(duì)列的最大長(zhǎng)度。§5.5消息隊(duì)列29msgget函數(shù)可以通過(guò)msgget系統(tǒng)調(diào)用創(chuàng)建或獲取一個(gè)消息隊(duì)列。說(shuō)明key 一個(gè)整數(shù)值,用于標(biāo)識(shí)一個(gè)消息隊(duì)列。msgflg 一組標(biāo)志。低端的九個(gè)bit對(duì)應(yīng)九種訪問權(quán)限,如open系統(tǒng) 調(diào)用。此外,可以和IPC_CREAT按位或以創(chuàng)建一個(gè)新的消 息隊(duì)列。返回值 成功時(shí)返回一個(gè)正整數(shù),即消息隊(duì)列標(biāo)識(shí)符;失敗時(shí)返回-1, 并設(shè)置errno變量。注:使用IPC_CREAT標(biāo)志,當(dāng)消息隊(duì)列已存在時(shí),只是忽略創(chuàng)建動(dòng)作,而不會(huì)出錯(cuò)。#include<sys/types.h>#include<sys/ipc.h>#include<sys/msg.h>intmsgget(key_tkey,intmsgflg);§5.5消息隊(duì)列30msgsnd函數(shù)可以通過(guò)msgsnd系統(tǒng)調(diào)用把一條消息添加到消息隊(duì)列中。說(shuō)明msgid 由msgget返回的消息隊(duì)列標(biāo)識(shí)符。msgp 指向要發(fā)送的消息的指針。msgsz 消息長(zhǎng)度。這個(gè)長(zhǎng)度不包括長(zhǎng)整形成員變量的長(zhǎng)度。msgflg 標(biāo)志。指定IPC_NOWAIT時(shí),表示當(dāng)隊(duì)列滿或達(dá)到系統(tǒng)限制 時(shí),函數(shù)立即返回(返回值為-1),不發(fā)送消息。返回值 成功時(shí)返回0;失敗時(shí)返回-1,并設(shè)置errno變量。注:消息的結(jié)構(gòu)受兩方面的約束:長(zhǎng)度必須小于系統(tǒng)規(guī)定的上限。必須以一個(gè)長(zhǎng)整型成員變量開始,接收函數(shù)以此成員來(lái)確定消息的類型。#include<sys/types.h>#include<sys/ipc.h>#include<sys/msg.h>intmsgsnd(intmsqid,constvoid*msgptr,size_tmsgsz,intmsgflg);§5.5消息隊(duì)列structmy_message{longintmessage_type;/*Thedatayouwishtotransfer*/};31msgrcv函數(shù)可以通過(guò)msgrcv系統(tǒng)調(diào)用從一個(gè)消息隊(duì)列獲取消息。說(shuō)明msgid 由msgget返回的消息隊(duì)列標(biāo)識(shí)符。msgp 指向準(zhǔn)備接收消息的指針。msgsz 消息長(zhǎng)度。這個(gè)長(zhǎng)度不包括長(zhǎng)整形成員變量的長(zhǎng)度。msgtyp 一個(gè)長(zhǎng)整數(shù)。若值為0,獲取隊(duì)列中的第一個(gè)可用消息;若值 大于0,獲取具有相同類型的第一個(gè)消息;若小于0,獲取消息 類型小于或等于其絕對(duì)值的第一個(gè)消息。msgflg 標(biāo)志。指定IPC_NOWAIT時(shí),表示當(dāng)中沒有相應(yīng)類型消息 時(shí),函數(shù)立即返回(返回值為-1),不接收消息。返回值 成功時(shí)返回0;失敗時(shí)返回-1,并設(shè)置errno變量。#include<sys/types.h>#include<sys/ipc.h>#include<sys/msg.h>ssize_tmsgrcv(intmsqid,void*msgp,size_tmsgsz,longmsgtyp,intmsgflg);§5.5消息隊(duì)列32msgctl函數(shù)可以通過(guò)msgctl系統(tǒng)調(diào)用直接控制消息隊(duì)列。說(shuō)明msgid 由msgget返回的消息隊(duì)列標(biāo)識(shí)符。cmd 要采取的動(dòng)作。IPC_WAIT 把msqid_ds結(jié)構(gòu)中的數(shù)據(jù)設(shè)置為消息隊(duì)列的當(dāng)前關(guān)聯(lián)值。IPC_SET 如果進(jìn)程有足夠的權(quán)限,就把消息隊(duì)列的當(dāng)前關(guān)聯(lián)值設(shè)置為msgqid_ds 結(jié)構(gòu)中給出的值。IPC_RMID 刪除消息隊(duì)列。buf 緩沖區(qū),作用視cmd而定。返回值 成功時(shí)返回0;失敗時(shí)返回-1,并設(shè)置errno變量。如果在進(jìn) 程正阻塞于msgsnd或msgrcv中等待時(shí)刪除消息隊(duì)列,則這 兩個(gè)函數(shù)將失敗。#include<sys/types.h>#include<sys/ipc.h>#include<sys/msg.h>intmsgctl(intmsqid,intcmd,structmsqid_ds*buf);§5.5消息隊(duì)列structmsqid_ds{uid_tmsg_perm.uid;uid_tmsg_perm.gidmode_tmsg_perm.mode;};33/*接收程序.msg1.c*/#include<stdlib.h>#include<stdio.h>#include<string.h>#include<errno.h>#include<unistd.h>#include<sys/msg.h>structmy_msg_st{longintmy_msg_type;charsome_text[BUFSIZ];};intmain(){intrunning=1;intmsgid;structmy_msg_stsome_data;longintmsg_to_receive=0;/*建立消息隊(duì)列*/msgid=msgget((key_t)1234,0666|IPC_CREAT);

綜合示例§5.5消息隊(duì)列34綜合示例§5.5消息隊(duì)列if(msgid==-1){fprintf(stderr,"msggetfailedwitherror:%d\n",errno);exit(EXIT_FAILURE);}while(running){/*接收消息*/if(msgrcv(msgid,(void*)&some_data,BUFSIZ,msg_to_receive,0)==-1){fprintf(stderr,"msgrcvfailedwitherror:%d\n",errno);exit(EXIT_FAILURE);}printf("Youwrote:%s",some_data.some_text);if(strncmp(some_data.some_text,"end",3)==0){running=0;}}/*刪除消息隊(duì)列*/if(msgctl(msgid,IPC_RMID,0)==-1){fp

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論