語言基礎(chǔ)筆記-linux進程間通信_第1頁
語言基礎(chǔ)筆記-linux進程間通信_第2頁
語言基礎(chǔ)筆記-linux進程間通信_第3頁
語言基礎(chǔ)筆記-linux進程間通信_第4頁
語言基礎(chǔ)筆記-linux進程間通信_第5頁
已閱讀5頁,還剩26頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

信信號sil機制是ix系統(tǒng)中最為古老的進程之間的通信機制。ix信號也可以稱為軟中斷,是在軟件層次上對中斷機制的一種模擬。在原理上,一個進程收到一個信號與處理器收到一個中斷請求可以說是一樣的。信號作是異步通知,通知接收信號的進程發(fā)生了什么。信號時間的發(fā)生有兩個來硬件來源,比如我們按下了鍵盤或者其他硬件信號觸kill軟件來源,最常見發(fā)送信號的系統(tǒng)函 killLinux系統(tǒng)中定義了一系列的信號,可以

命令列出所有的信號Linux的信號機制是從Unix繼承下來的,早期Unix系統(tǒng)只定義了32種信號,現(xiàn)在Linux支持64種信 6)SIGABRT:調(diào)用abort函數(shù)時產(chǎn)生該信號。默認動作為終止進程并產(chǎn)生core )) ) ))RMM)N():進程可以通過三種方式來響應和處理一個信忽略信號:即對信號不做任何處理,但是兩個信號不能忽略捕捉信號:當信號發(fā)生時,執(zhí)行用戶定義的信號處理函

以 執(zhí)行默認操作:Linux對每種信號都規(guī)定了默認操作,man7signal查看1123456789TermDefaultactionistoterminatetheIgnDefaultactionistoignoretheCoreDefaultactionistoterminatetheprocessanddumpcore(seecore(5)).StopDefaultactionistostoptheprocess.ContDefaultactionistocontinuetheprocessifitiscurrently行。#include#includevoid(*signal(intsig,void(*func)(int))主要用于前32種非實時信號的安:是要安裝的信號值func:是指定信號處理函數(shù),如果想忽略信號可以

(函數(shù)地址宏),如果想采用系統(tǒng)默認處理函 (函數(shù)地址宏) intsigaction(intsignum,conststructsigaction*act,structsigactionsigaction用于后32種實時信號的安裝信號處SIGCHLD的產(chǎn)生條源代碼#include#include#include#include5void{intpid_tpid=waitpid(‐1,&status,WUNTRACED|printf("recvchildpid%d\n",printf("childprocessexitedwith%d\n",elseprintf("childprocesssignaledwith%d\n",elseprintf("childprocesselseprintf("childprocess intmain(intargc,char** pid_tsignal(SIGCHLD,pid=if(pid=={printf("childPID[%d]\n", elseif(pid!={{ { 運行結(jié)果where@ubuntu:~where@ubuntu:~$childPIDchildPID[9881]return并不是每個進程都可以向其他的進程發(fā)送信號。一般的進程只能向具有相同i和i同進程組中的其他進程發(fā)送信號。常用的發(fā)送信號的函數(shù)有kill、is、lm、stitim、t等。kill()函數(shù)可以給指定的進程發(fā)送某一個信號,其函數(shù)原型是#include#includeintkill(pid_tpid,int參 含義pid含pid>給PID為pid的進程發(fā)送信pid=給同一個進程的所有進程發(fā)送pid<0pid!=-給進程組ID為pid的所有進程發(fā)送信pid=-給除了自身之外的PID大于1的進程發(fā)送 通過errno以及perror可以查看錯誤宏含所發(fā)送的信號無效沒有向目標進程發(fā)送信號的權(quán)目標進程不存在或進程已經(jīng)終止,處于僵尸狀源代碼1123456789#include#includevoid{}intmain(intargc,char**{pid_tpid;if(pid==0){printf("childprocess\n");kill(getppid(),SIGBUS);}elseif(pid!={{}}{}return}raise()函數(shù)用戶給進程本身發(fā)送一個信號,其函數(shù)原型#include#includeintraise(int源代#include#include#include#includevoidhandle_sig(int{if(sig=={printf("get intmain(intargc,char**{signal(SIGBUS,return 定時器函數(shù),alarm()專為SIGALRM信號設計,其函數(shù)原型#include#includeunsignedintalarm(unsignedint參 是定時器的時間,單位為秒,當設置了alarm()之后,在指定

秒之后,將給自己發(fā)一個SIGALRM信號,當參 為0的時候,將清除當前進程的alrm設置調(diào)用lm函數(shù)時,如果進程已經(jīng)有一個未結(jié)束的lm,那么舊的lm將被刪除,并返回舊的lm的剩余時間。否則lm函數(shù)返回。源代碼:1123456789#include#include<unistd.h>#include<signal.h>voidhandle_sig(intsig){staticinti=printf("signalalarm%d\n",i++);}intmain(intargc,char**{signal(SIGALRM,{}return}更強大的定時器函數(shù)setitimer(),其函數(shù)原型如下 intsetitimer(intwhich,conststructitimerval*value,structitimerval*which參數(shù)指定定時器類含以系統(tǒng)真實的時間來計算,它送出SIGALRM信號以該進程在用戶態(tài)下花費的時間來計算,它送出SIGVTALRM信號以該進程在用戶態(tài)下和內(nèi)核態(tài)下所費的時間來計算,它送出SIGPROF信號value參數(shù)指定定時時間1123456789structitimervalstructtimevalit_interval;/*每隔多少秒發(fā)送一次信號structtimeval/*第一次定時時間structtimevalsuseconds_t/*seconds/*microseconds123456789#include#include<signal.h>#include<unistd.h>voidhandle_sig(123456789#include#include<signal.h>#include<unistd.h>voidhandle_sig(intsig){staticinti=printf("signalalarm[%d]\n",}intmain(intargc,char**{structitimervaltimval;timval.it_interval.tv_usec=timval.it_value.tv_usec=0;signal(SIGALRM,handle_sig);{}return abort()向進程發(fā)送SIGABORT信號,默認情況下進程會異常退管道符:一個用與而另一個用于寫入。任何從管道寫入端寫入的數(shù)據(jù),可以從管道端讀出。管道通信具有以下特點管道存放在內(nèi)存中,是一種獨立的文件系系統(tǒng)調(diào)用pipe()用于創(chuàng)建一個管道,其函數(shù)原型如#include#includeintpipe(int

文件描述符用來從管道 如果管道讀端被關(guān)閉,那么這個時候如果

管道,會發(fā)出信

。如果管道寫端被關(guān)閉那么這個時候如果繼

管道直接返回0源代#include#include3voidchild_process(int{inti=charwritebuf[128]=8{sprintf(writebuf,"writepipe:%d",i); write(pipefd[1],writebuf, printf("writepipe:%s\n", i=(i+1)% voidfather_process(int{charreadbuf[128]={ printf("readpipe:%s\n", intmain(intargc,char**{intpid_tif(pipe(pipefd)=={return pid=if(pid=={ elseif(pid!={}{}return}運行結(jié)果:子進程寫數(shù)據(jù),父進程讀出數(shù)據(jù)并且打where@ubuntu:~where@ubuntu:~$writepipe:writepipe:readpipe:writepipe:writepipe:writepipe:readpipe:writepipe:writepipe:writepipe:readpipe:writepipe:writepipe:writepipe:命名管道FIFO是firstinfirstout(先進先出)的縮寫,F(xiàn)IFO也稱為“命名管道”。FIFO是一種特殊類型的管道,它在文件

函數(shù)創(chuàng)建。在FIFO文件創(chuàng)建之后,任何一個具有適當權(quán)限的進程都可以mkfifo()函數(shù)原型為#include#includeintmkfifo(constchar*pathname,mode_t參數(shù)一個FIFO文件的路徑名與普通文

函數(shù)中的mode參數(shù)相同返回值如果要創(chuàng)建的文件已經(jīng)存在,返回- 錯誤,成功返回0#include#include#include#include#includevoidhandle_sig(int{printf("signal intmain(intargc,char**{intintcharinti=signal(SIGPIPE,if(mkfifo("./fifo",0640)=={if(errno!={return fd=open("./fifo",if(fd=={return sprintf(buf,"data%d", ret=write(fd,buf,strlen(buf)); printf("writefifo[%d]%s\n",ret,buf); return 源碼中,通過mkfifo來創(chuàng)建FIFO文件,并且以只寫的方式打開,只有當兩邊的管道都打開的時候才能..

函數(shù)上,如果管道另一端打開后被關(guān)閉,那么這個時候如果繼

FIFO管道,源代碼1123456789#include#include<unistd.h>#include<stdio.h>#include<errno.h>#includeintmain(intargc,char**{intfd;charbuf[128];if(mkfifo("./fifo",0640)==‐1){if(errno!=EEXIST)/*如果錯誤類型是fifo文件已經(jīng)存在,則繼續(xù)執(zhí)行{return‐1;}}fd=open("./fifo",O_RDONLY);if(fd==‐1){return‐1;}{memset(buf,0,ret=read(fd,buf,sizeof(buf)‐1);printf("readfifo[%s]:%s\n",ret,buf);}return}

使用管道需要注意以下4種特殊情況(假設都是阻塞I/O操作,沒有設置O_NONBLOCK標志如果所有指向管道寫端的文件描述符都關(guān)閉了(管道寫端的計數(shù)等于0),而仍然有進程從管道的讀端讀數(shù)據(jù),那么管道中剩余的數(shù)據(jù)都被后,再次read會返回0,就像讀到文件末尾一樣。如果有指向管道寫端的文件描述符沒關(guān)閉(管道寫端的計數(shù)大于),而持有管道寫端的進程也沒有向管道中寫數(shù)據(jù),這時有進程從管道讀端讀數(shù)據(jù),那么管道中剩余的數(shù)據(jù)都被后,再次會阻塞,直到管道中有數(shù)據(jù)可讀了才數(shù)據(jù)并返回。如果所有指向管道讀端的文件描述符都關(guān)閉了(管道讀端的計數(shù)等于),這時有進程向管道的寫端it,那么該進程會收到信號SIPIPE,通常會導致進程異常終止。講信號時會講到怎樣使SIPIPE信號不終止進程。如果有指向管道讀端的文件描述符沒關(guān)閉(管道讀端的計數(shù)大于),而持有管道讀端的進程也沒有從管道中讀數(shù)據(jù),這時有進程向管道寫端寫數(shù)據(jù),那么在管道被寫滿時再次it會阻塞,直到管道中有空位置了才寫入數(shù)據(jù)并返回。信號在Unix的SystemV版本,AT&T引進了一種新形式的IPC機制(Inter-ProcessCommunication,進程間通信),SystemIPC中,對于每一個新建的信號量、消息隊列以及共享內(nèi)存,都有一個在整個系統(tǒng)中唯一的標識符,在終端輸入命 ,可以看到目前系統(tǒng)中所有的IPC信息1where@ubuntu:~$234 擁有 權(quán) 字5 26 27 28 29 2 2 2 2 2信號量數(shù)組 擁有者權(quán) 消息隊列 擁有者權(quán) 已用字節(jié)數(shù)消#include#includekey_tftok(constchar*pathname,int#include#includekey_tftok(constchar*pathname,intkey_t函數(shù)返key_t字

指向的文件相對應文件索引節(jié)

來確定一個IPC關(guān)必須是一個已經(jīng)存在并具 權(quán)限的文件

只有最低的8個字節(jié)是有效的,所以通常用ASCII字符來作 。

完全相同時,每次調(diào)

都會獲取一個相同的鍵通過調(diào)用semget()創(chuàng)建信號量集,其函數(shù)原型是#include#include#include#includeintsemget(key_tkey,intnsems,int :是信號量鍵值。 :是信號量的數(shù)目參 :是一些標志。這些標志包括:如果key指定的信號量不存在,創(chuàng)建一個新信號量集: 標志一起使用,如果信號量已經(jīng)存在,返回錯誤返回值

調(diào)用成功時,返回與鍵 對應的信號量集的標識符,否則返回-1當進程需要申請或者釋放公共資源時候,可以調(diào)用semop()來對信號量進行操作,其函數(shù)原型#include#include#include#includeintsemop(intsemid,structsembuf*sops,unsigned參 是信號量ID參 指向一

結(jié)構(gòu)的數(shù)組,每一

結(jié)構(gòu)都定義了在對信號量的操參 為sops指向數(shù)組的大小其 結(jié)構(gòu)如下112345structunsignedshort;對應信號集中的信號量的索引是一個指定了操作類型的整數(shù),如果sem_op是一個正整數(shù),則這個值會立刻被加到信號量的值上。 量的值至少等于操作值的絕對值。

為0,這個操作會導致進程阻塞,直到信號量的值為零才恢

非阻塞操作,如

,Linux會在進程退出的時返回值

調(diào)用成功時返回0,否則返回-的功能和semop()基本一樣,只是增加了一個時間限制,其函數(shù)原型如 intsemtimedop(intsemid,structsembuf*sops,unsignednsops,structtimespec*如果信號量操作時進程被阻塞,那么經(jīng)過timeout時間后,還是沒有可用資源,那么函數(shù)會立即返系統(tǒng)調(diào)用用于對信號量的各種控制操作,其函數(shù)原型#include#include#include#includeintsemctl(intsemid,intsemnum,intcmd,參 指定信號量集參 指定了對信號量集里面的哪一個信號量進行操作參 指定具體的操作類型操一個信號量集的數(shù)據(jù)結(jié)構(gòu)semid_ds,并將其在semun中的buf參數(shù)中設置信號量集的數(shù)據(jù)結(jié)構(gòu)semid_ds中的元素ipc_perm,其值取自semun中的buf從內(nèi)存中立即刪除信號量用于信號量集中的所有信號量的值T返回正在等待資源的進程返回最后一個對信號量操作的進程返回信號量集中的一個單個的信號量的T返回等待semnum鎖代表的信號量值成為0的進程數(shù)目設置信號量集中的所有的信號量的設置semnum所代表信號量的值最后一個是可選參數(shù),取決 的值,必須是這樣一個1123456789unionsemunval;/*Valueforsemid_ds*buf;/*Bufferforunsigned *arrary;/*Bufferfor/*structsemid_ds在sys/sem.h中定義structsemid_dsstructipc_permsem_perm;/*Ownershipandpermissionssem_otime;/*Lastsemoptimesem_ctime;/*Lastchangetime*/sem_nsems;/*No.ofsemaphoresinset*/調(diào)用失敗時返回-1,調(diào)用成功時,根據(jù)cmd的不同,返回值也各不相同,具體可以查看semctlman手冊

并不初始化各個信號量的值,這個初始化必須通,查詢當前等待在某個信號量上的進程

命令或

命令調(diào) printf("%dprocesseswaitforsemid[%d]",semctl(semid, 使 ,刪除信號量集 semctl(semid,0,#include#include#include#include8unionsemunintstructsemid_dsunsignedshort intmain(intargc,char{intintkey_tkey=ftok("./creat",if(key=={return semidsemget(key1IPC_CREAT|IPC_EXCL|0666);//創(chuàng)建1個信號if(semid=={if(errno=={semid=semget(key,1,printf("semid[%d]alreadyexist\n", {return {unionsemunsem_args.setval= rsret=semctl(semid,0,SETVAL,if(ret=={return }}structsembufsem_opt_request[1]={0,‐1,SEM_UNDO};structsembufsem_opt_release[1]={0,1,SEM_UNDO};{printf("PID[%d]wait...\n",semop(semid,sem_opt_request,1);//獲取進程2的資源,讓進程2等待printf("PID[%d]requested\n",getpid());semop(semid,sem_opt_release,1);//喚醒進程1,即釋放資源的使用權(quán)printf("PID[%d]release\n",getpid());}return從隊列中,每一個消息隊列用一個唯一的IP標識符表示。系統(tǒng)定義的消息類型#include#includestructlongchar 指消息的類型,它由一個整數(shù)來代表,并且它只能是大于0的整數(shù)是消息本身字段不但可以字符,還可以任何其他的數(shù)據(jù)類型,此字段可以說是完全任意的,因為程序員structstructlongcharstructclient 這里的消息類型字段和前面的一樣,但數(shù)據(jù)結(jié)構(gòu)的其余部分則由其他的兩個成員所代替,而其中 還是個結(jié)構(gòu)體,這就體現(xiàn)了消息隊列的靈活之處。內(nèi)核本身并不對消息結(jié)構(gòu)中的數(shù)據(jù)做任何翻譯。你可以再其中發(fā)送任何消息,但存在一個內(nèi)部給定的消息大小的限制。在ix系統(tǒng)中,消息的最大的長度是個字節(jié),其中包括mty,它占用個字節(jié)的長度。系統(tǒng)調(diào)用msgget()用于創(chuàng)建一個新的消息隊列,或者存取一個已經(jīng)存在的消息隊列,其函數(shù)原型#include#include#includeintmsgget(key_tkey,int 參 是消息隊列關(guān)鍵字值,可以通 獲得參 是一些標志IPC_CREATIPC_CREAT: 執(zhí)行成功時,返回消息隊列的標識符,否則返回-1,通

查看錯誤信下面是一個打開和創(chuàng)建消息隊列的例子,函數(shù)返回消息隊列的標識intintopen_queue(key_t{intqid=msgget(keyval,IPC_CREAT|if(qid=={return return

系統(tǒng)調(diào)用用于向隊列發(fā) intmsgsnd(intmsqid,structmsgbuf*msgp,sizetmsgsz,int 參 :是隊列標識符參 :是指向消息緩沖區(qū)的指針參 :指定了消息的字節(jié)大小,但是不包括消息類型的長度(4個字節(jié))參 :可以設置為值含0此時為忽略此參數(shù),如果隊列已滿,調(diào)用進程將會掛起,直到消息可以寫入到隊列消息源碼intintsend_message(intqid,structmymsgbuf*{intlength=sizeof(structmymsgbuf)‐result=msgsnd(qid,qbuf,length,if(result=={return return msgrcv()系統(tǒng)調(diào)用用于從消息隊列一條消息,其函數(shù)原型是 ssize_tmsgrcv(intmsqid,structmsgbuf*msgp,size_tmsgsz,longmsgtype,int 參 :消息隊列的標識符參 :代表要消息的緩沖區(qū)的地址參數(shù)msgsz:消息緩沖區(qū)的長度,不包括mtype的長度,它可以按照如下方法計算mysmsgbufsizeof(long參 :是要從消息隊列 的消息的類型。如 ,接收到消息隊列的第一個消息。

絕對值的所參 取值為值含0此時為忽略此參數(shù),如果隊列已滿,調(diào)用進程將會掛起,直到消息可以寫入到隊列下面時一個接收消息的例intintread_message(intqid,longtype,structmymsgbuf{intresult,length=sizeof(structmymsgbuf)‐result=msgrcv(qid,qbuf,length,type,if(result=={return return #includestruct{longchar 9intsend_message(intqid,structmymsgbuf*{intlength=sizeof(structmymsgbuf)‐result=msgsnd(qid,qbuf,length,if(result=={return return intmain(intargc,char**{structmymsgbufkey_tkeyval=ftok("./creat",inti=if(keyval=={return intqid=msgget(keyval,IPC_CREAT|if(qid=={return {msg.mtype=sprintf(msg.buf,"msg%d",send_message(qid,printf("sendmessage:mtype[%ld]buf[%s]\n",msg.mtype, return 源碼#includestruct{longchar 9 intread_message(intqid,longtype,structmymsgbuf*{intlength=sizeof(structmymsgbuf)‐result=msgrcv(qid,qbuf,length,type,if(result=={return return intmain(intargc,char**{structmymsgbufkey_tkeyval=ftok("./creat",inti=if(keyval=={return intqid=msgget(keyval,IPC_CREAT|if(qid=={return {read_message(qid,100,printf("readmessage:mtype[%ld]buf[%s]\n",msg.mtype, return 消息隊列標識符的屬性被記錄在一個msgid_ds結(jié)構(gòu)體1123456789structstructipc_permmsg_perm;/*所有者和權(quán)限msg_stime;/*最后一次向隊列發(fā)送消息的時間msg_rtime/*最后一次從隊列接收消息的時間*/msg_ctime;/*隊列最后一次改動的時間*/msg_cbyptes;/*當前隊列所有消息的總長度}通過msgctl()可以對消息隊列進行控制或者一些屬性的修改,其函數(shù)原型 intmsgctl(intmsgid,intcmd,structmsqid_ds*參 :是消息隊列的標識符參 :指定了操作含消息隊列的數(shù)據(jù)結(jié)構(gòu)msqid_ds,并將其在buf指定的地址中設置消息隊列的數(shù)據(jù)結(jié)構(gòu)msqid_ds中的ipc_permmsg_qbytesmsg_ctime元素的值。這從系統(tǒng)內(nèi)核中移走消息隊下面是一個刪除消息隊列的例intintremove_queue(int{if(msgctl(qid,IPC_RMID,0)=={return return 共享內(nèi)存可以說是最有用的進程間通信方式,也是最塊的IPC形式。兩個不同進程A、B共享內(nèi)存的基本原是,同一塊物理內(nèi)存被映射到進程A、B各自的進程地址空間。進程A可以即時看到進程B對共享內(nèi)存種數(shù)據(jù)的更新,反之亦然。由于多個進程共享同一塊內(nèi)存區(qū)域,必然需要某種同步機制,互斥鎖和信號量都可以。系統(tǒng)調(diào)用shmget()用于創(chuàng)建共享內(nèi)存或者獲取一個已經(jīng)存在的共享內(nèi)存的標識符,其函數(shù)原型#include#include#includeintshmget(key_tkey,size_tsize,int 參 是一些標志,包括含如果內(nèi)核中沒有此共享內(nèi)存,則創(chuàng)建當和IPC_CREAT一起使用時,如果共享內(nèi)存已經(jīng)存在,則返回錯返回:當shmget()執(zhí)行成功時,返回共享內(nèi)存的標識符,否則返回-1,通

查看錯誤值獲取共享內(nèi)存標識intintopen_segment(key_tkeyval,int{intshmid=shmget(keyval,segsize,IPC_CREAT|if((shmid=={return return 系統(tǒng)調(diào)用shmat()可以獲取一個共享內(nèi)存的地址,并將其連接到進程中,其函數(shù)原型 void*shmat(intshmid,constvoid*shnaddr,int 參 :是共享內(nèi)存標識符參 與參 關(guān)聯(lián)使用用含shmaddr為共享內(nèi)

溫馨提示

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

評論

0/150

提交評論