Linux第5章進程、信號和消息隊列_第1頁
Linux第5章進程、信號和消息隊列_第2頁
Linux第5章進程、信號和消息隊列_第3頁
Linux第5章進程、信號和消息隊列_第4頁
Linux第5章進程、信號和消息隊列_第5頁
已閱讀5頁,還剩34頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第五章進程、信號和消息隊列12§5.1什么是進程“一個其中運行著一個或多個線程的地址空間和這些線程所需要的系統(tǒng)資源?!薄罢谶\行的程序。”進程由程序代碼、數(shù)據(jù)、變量(占用著系統(tǒng)內存)、打開的文件(文件描述符)和環(huán)境組成。3§5.2進程的結構多進程的管理方式示例:兩個用戶同時運行grep程序搜索結束之前運行ps命令PID:2~32768代碼區(qū):共享函數(shù)庫:共享數(shù)據(jù)區(qū)、棧空間、環(huán)境變量等:不共享4§5.2進程的結構多進程的管理方式示例:兩個用戶同時運行grep程序搜索結束之前運行ps命令PID:2~32768代碼區(qū):共享函數(shù)庫:共享數(shù)據(jù)區(qū)、??臻g、環(huán)境變量等:不共享5§5.2進程的結構進程表Linux進程表是一個數(shù)據(jù)結構,其中保存了當前所有進程的相關信息,包括PID、狀態(tài)、命令字符串等(參見ps命令輸出項)。操作系統(tǒng)通過PID對進程進行管理,PID是進程表的索引。系統(tǒng)可同時運行的進程數(shù)只與可用于建立進程表項的內存容量有關。父進程與子進程Linux啟動時運行一個名為init的進程,該進程是系統(tǒng)運行的第一個進程,它的PID為1。一般進程(除init外)都是由一個“父進程”創(chuàng)建的,被父進程創(chuàng)建的進程稱為“子進程”,init進程是其他所有進程的祖先進程。UIDPIDPPIDCSTIMETTYTIMECMDroot10020:41?00:00:00/sbin/initmolin19331932020:45pts/100:00:00-bashmolin20471020:47?00:00:01gnome-terminal6§5.2進程的結構進程狀態(tài)$psaxPIDTTYSTATTIMECOMMAND1?Ss0:00/sbin/init37?SN0:00[ksmd]892?Ssl0:00gdm-binary2049pts/0Ss+0:00bash8204?S<0:00udevd--daemon12682pts/1R+0:00psaxSTAT代碼說明S睡眠。通常是在等待某個事件的發(fā)生。R運行/可運行。即在運行隊列中,處于正在運行或即將運行狀態(tài)。D不可中斷的睡眠(等待)。通常是在等待輸入或輸出完成。T停止。通常是被shell作業(yè)控制所停止,或處于調試器控制下。Z僵尸(zombie)進程。N低優(yōu)先級任務。s進程是會話期首進程。+進程屬于前臺進程組。l進程是多線程的。<高優(yōu)先級任務。7system函數(shù)可以調用標準庫函數(shù)system在程序內啟動另一個程序,從而創(chuàng)建一個新進程。#include<stdlib.h>intsystem(constchar*command);說明command 待運行的程序(命令字符串)。返回值 無法啟動shell時,返回127;其它錯誤時返回-1;否 則,返回命令的退出碼。system函數(shù)運行command命令并等待該命令完成,本質是調用:/bin/sh–ccommand。注:使用system函數(shù)并非啟動其他進程的理想手段,因其必須先啟動一個shell,再使用該shell執(zhí)行相應的命令?!?.3創(chuàng)建進程8§5.3創(chuàng)建進程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替換進程映像可以調用exec系列函數(shù)把當前進程替換為一個新進程。#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[]);說明path 待運行的程序全路徑名(命令字符串)。file 待運行的程序名,通過PATH環(huán)境變量搜索其路徑。arg 命令參數(shù)。argv[] 命令參數(shù)。envp 傳遞給待運行程序的環(huán)境變量。返回值 成功時不返回(原程序不再執(zhí)行);出錯時返回-1,并設置 errno變量。§5.3創(chuàng)建進程參數(shù)個數(shù)可變,以一空指針結束。其他函數(shù)通常是用execve函數(shù)實現(xiàn)的。10§5.3創(chuàng)建進程替換進程映像用法#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)建進程替換進程映像示例#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”說明ps命令結束后,不再返回exam09_02程序,所以不會打印出“Done”。新進程的PID、PPID及nice值和原先的完全一樣。exec系列函數(shù)啟動的新進程的參數(shù)表和環(huán)境變量的總長度是有限制的。上限由ARG_MAX給出,POSIX規(guī)定至少為4KB,Linux中為128KB。原進程中已打開的文件描述符在新進程中仍保持打開(除非“執(zhí)行時關閉標志”被置位)。原進程中打開的目錄流在新進程中被關閉。12復制進程映像可以調用fork函數(shù)創(chuàng)建一個新進程。#include<unistd.h>pid_tfork(void);說明返回值 成功時,父進程中返回子進程的PID,子進程中返回0;失 敗時返回-1,并設置errno變量。fork系統(tǒng)調用復制當前進程,在進程表中添加一個新的表項,新表項的多數(shù)屬性與當前進程相同。新進程與原進程執(zhí)行的代碼完全相同,但新進程有自己的數(shù)據(jù)空間、環(huán)境和文件描述符。通常,使用fork和exec系列函數(shù)一起創(chuàng)建多進程環(huán)境。典型的fork代碼?!?.3創(chuàng)建進程典型錯誤為E_AGAIN——子進程超過CHILD_MAX限制ENOMEM——進程表無足夠空間pid_tnew_pid;new_pid=fork();switch(new_pid){case-1:/*Error*/break;case0:/*Wearechild*/break;default:/*Weareparent*/break;}13復制進程映像示例§5.3創(chuàng)建進程#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運行結果14等待進程在父進程中調用wait函數(shù)可以讓父進程等待任一子進程的結束。#include<sys/types.h>#include<sys/wait.h>pid_twait(int*status);說明status 輸出參數(shù),用于獲取子進程的退出狀態(tài)。返回值 成功時,返回已結束子進程的PID;出錯時返回-1,并設置 errno變量。以下宏可用于解釋子進程退出狀態(tài)信息。§5.3創(chuàng)建進程宏說明WIFEXITED(status)

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

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

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

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

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

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

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

intsa_flags; //可決定回調行為的位標志值

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

綜合示例§5.5消息隊列34綜合示例§5.5消息隊列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;}}/*刪除消息隊列*/if(msgctl(msgid,IPC_RMID,0)==-1){fp

溫馨提示

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

評論

0/150

提交評論