Linux環(huán)境下C程序設(shè)計(jì)Linux程序設(shè)計(jì)進(jìn)程間通信_(tái)第1頁
Linux環(huán)境下C程序設(shè)計(jì)Linux程序設(shè)計(jì)進(jìn)程間通信_(tái)第2頁
Linux環(huán)境下C程序設(shè)計(jì)Linux程序設(shè)計(jì)進(jìn)程間通信_(tái)第3頁
Linux環(huán)境下C程序設(shè)計(jì)Linux程序設(shè)計(jì)進(jìn)程間通信_(tái)第4頁
Linux環(huán)境下C程序設(shè)計(jì)Linux程序設(shè)計(jì)進(jìn)程間通信_(tái)第5頁
已閱讀5頁,還剩79頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

第八章進(jìn)程間通信

本章首先介紹Linux下進(jìn)程間通信地相關(guān)內(nèi)容;然后介紹Linux平臺(tái)下進(jìn)程間通信相互通信地方法,包含共享內(nèi)存,信號(hào)量,管道通信,命名管道,消息隊(duì)列;最后結(jié)合具體地項(xiàng)目案例,闡述進(jìn)程間通信地相關(guān)操作地具體應(yīng)用。

本節(jié)學(xué)習(xí)目標(biāo):

√共享內(nèi)存

√信號(hào)量

√管道通信

√命名管道

√消息隊(duì)列*Linux操作系統(tǒng)18.1進(jìn)程間通信概述

Linux系統(tǒng)是多任務(wù)多進(jìn)程地操作系統(tǒng),對(duì)于大型地應(yīng)用系統(tǒng)而言,通常需求多個(gè)任務(wù)多個(gè)進(jìn)程相互協(xié)作共同完成,而進(jìn)程地地址空間又是各自獨(dú)立地,所以需求進(jìn)程間進(jìn)行通信。進(jìn)程間地通信(InterProcessConnection簡稱IPC)是指多個(gè)進(jìn)程間相互協(xié)調(diào),進(jìn)行信息交換,相互交流地方法。Linux下進(jìn)程間進(jìn)行相互通信地方法包含共享內(nèi)存,信號(hào)量,管道,命名管道,消息隊(duì)列。下面對(duì)Linux下地進(jìn)程間地通信方法做個(gè)簡單介紹。

共享內(nèi)存:共享內(nèi)存是指由一個(gè)進(jìn)程創(chuàng)建并且可以被其它進(jìn)程訪問地內(nèi)存段。共享內(nèi)存是進(jìn)程間通信方式最快地IPC方式,經(jīng)常與信號(hào)量通信機(jī)制配合使用,通信速度最快,運(yùn)行效率最高。*Linux操作系統(tǒng)28.1進(jìn)程間通信概述

信號(hào)量:信號(hào)量在形式上是一個(gè)計(jì)數(shù)器,主要用來協(xié)調(diào)進(jìn)程間或同一個(gè)進(jìn)程內(nèi)不同線程間同時(shí)訪問共享資源地問題。所以,信號(hào)量也稱為一種信號(hào)鎖,保證同一時(shí)刻只有一個(gè)進(jìn)程或線程訪問共享資源,其余進(jìn)程或線程無法訪問該共享資源;信號(hào)量也是一種同步機(jī)制,同一時(shí)刻可以有多個(gè)進(jìn)程訪問共享資源。

管道:管道在形式上是一種文件,主要用在具有親緣關(guān)系地進(jìn)程間地通信。管道是一種半雙工地通信方式,它地顯著特點(diǎn)是管道有讀入端與寫入端,數(shù)據(jù)只能單向流動(dòng)。與共享內(nèi)存相比,管道通信相對(duì)慢些,但是它用起來方便很多,系統(tǒng)開銷也小。*Linux操作系統(tǒng)38.1進(jìn)程間通信概述

命名管道:命名管道是管道中地一種,具有管道地所有功能與特點(diǎn)。命名管道是一個(gè)設(shè)備文件,不僅僅可用在具有親緣關(guān)系地進(jìn)程間地通信,而且也可用在不具有親緣關(guān)系地進(jìn)程間。命名管道要求提供一個(gè)路徑名與它關(guān)聯(lián)地文件,只要可以訪問這個(gè)路徑文件地進(jìn)程,都可以進(jìn)程間地相互通信。

消息隊(duì)列:消息隊(duì)列是存放在操作系統(tǒng)內(nèi)核中地消息鏈表,每個(gè)消息隊(duì)列由消息隊(duì)列標(biāo)識(shí)符標(biāo)示。消息隊(duì)列存放在內(nèi)核中,所以只有重啟操作系統(tǒng)或主動(dòng)刪除一個(gè)消息隊(duì)列,消息隊(duì)列才會(huì)消除。消息隊(duì)列具有傳遞信息量大,可以承載各種格式地字節(jié)流與可以動(dòng)態(tài)設(shè)置緩沖區(qū)大小地優(yōu)點(diǎn)。*Linux操作系統(tǒng)48.2共享內(nèi)存

在Linux系統(tǒng)中,共享內(nèi)存是由一個(gè)進(jìn)程創(chuàng)建并且可以被其它進(jìn)程訪問地內(nèi)存段。每個(gè)進(jìn)程所創(chuàng)建地共享內(nèi)存在操作系統(tǒng)內(nèi)核中維護(hù)著一個(gè)與之相應(yīng)地?cái)?shù)據(jù)結(jié)構(gòu)shmid_ds,它地具體定義如下所示:*Linux操作系統(tǒng)58.2共享內(nèi)存*Linux操作系統(tǒng)68.2共享內(nèi)存

這個(gè)結(jié)構(gòu)詳細(xì)描述了共享內(nèi)存地各種屬性,它們地具體含義如下所示:

shm_perm:表示共享內(nèi)存地用戶ID,組ID信息;shm_segsz:以字節(jié)為單位表示共享內(nèi)存地大小;shm_lkt:表示共享內(nèi)存段鎖定地時(shí)間大小;shm_cpid:表示創(chuàng)建共享內(nèi)存地進(jìn)程ID;shm_lpid:表示最后一次操作共享內(nèi)存地進(jìn)程ID;shm_nattch:表示當(dāng)前使用共享內(nèi)存地進(jìn)程數(shù);shm_atime:表示最后一次附加共享內(nèi)存地時(shí)間;*Linux操作系統(tǒng)78.2共享內(nèi)存

shm_dtime:表示最后一次分離共享內(nèi)存地時(shí)間;

shm_ctime:表示最后一次修改共享內(nèi)存地時(shí)間;

下面給出基于上述共享內(nèi)存數(shù)據(jù)結(jié)構(gòu)地函數(shù)調(diào)用。*Linux操作系統(tǒng)81共享內(nèi)存地創(chuàng)建

創(chuàng)建共享內(nèi)存地函數(shù)是shmget。系統(tǒng)通過調(diào)用它在程序中完成共享內(nèi)存地創(chuàng)建工作。在Linux系統(tǒng)終端中使用幫助命令“manshmget”,得到共享內(nèi)存地創(chuàng)建函數(shù)信息如下:

#include<sys/ipc.h>

#include<sys/shm.h>

intshmget(key_tkey,size_tsize,intshmflg);*Linux操作系統(tǒng)91共享內(nèi)存地創(chuàng)建

shmget:該函數(shù)地返回類型為整型,用于創(chuàng)建進(jìn)程地共享內(nèi)存。key參數(shù)表示由ftok生成地共享內(nèi)存鍵。size參數(shù)表示共享內(nèi)存地大小,若是新創(chuàng)建一個(gè)共享內(nèi)存則size須大于0;若是訪問已經(jīng)存在地共享內(nèi)存則size為0。shmflg參數(shù)表示共享內(nèi)存地操作代表位,用于設(shè)置共享內(nèi)存地訪問權(quán)限,若shmflg參數(shù)取值為IPC_CREATE,則表示系統(tǒng)將參數(shù)key與其它地共享內(nèi)存key進(jìn)行比較,如果相同則返回已經(jīng)存在地共享內(nèi)存區(qū)地標(biāo)識(shí)符,如果不同則新建一個(gè)共享內(nèi)存區(qū)并返回其標(biāo)識(shí)符;若shmflg參數(shù)取值為IPC_EXCL,則表示無意義;若shmflg參數(shù)取值為IPC_CREATE|IPC_EXCL,表示如果發(fā)現(xiàn)信號(hào)集已經(jīng)存在,則返回-1。*Linux操作系統(tǒng)101共享內(nèi)存地創(chuàng)建

函數(shù)shmget調(diào)用成功返回共享內(nèi)存地引用標(biāo)示符,同時(shí)該共享內(nèi)存地shmid_ds結(jié)構(gòu)被初始化;否則調(diào)用失敗返回-1。*Linux操作系統(tǒng)112共享內(nèi)存地附加

共享內(nèi)存地附加函數(shù)是shmat。系統(tǒng)通過調(diào)用它在程序中完成共享內(nèi)存地附加工作。在Linux系統(tǒng)終端中使用幫助命令“manshmat”,得到共享內(nèi)存地附加函數(shù)信息如下:

#include<sys/types.h>

#include<sys/shm.h>

void*shmat(intshmid,constvoid*shmaddr,intshmflg);*Linux操作系統(tǒng)122共享內(nèi)存地附加

shmat:該函數(shù)地返回類型為指針,指向共享內(nèi)存地地址,用于附加進(jìn)程地共享內(nèi)存。shmid參數(shù)表示附加地共享內(nèi)存地引用標(biāo)示符。shmflg參數(shù)表示共享內(nèi)存地讀寫操作方式。shmaddr參數(shù)表示共享內(nèi)存地附加地址空間,若shmaddr參數(shù)取值為空,則表示由內(nèi)核選擇一個(gè)空閑地內(nèi)存區(qū);若shmaddr參數(shù)取值為非空,并且shmflg參數(shù)指定為SHM_RND值則附加地址為共享內(nèi)存地低端邊界地址后地地址,否則附加地址為shmaddr指定地地址。通常shmaddr參數(shù)設(shè)置為NULL。

函數(shù)shmat調(diào)用成功返回共享內(nèi)存地附加地址;否則調(diào)用失敗返回-1。*Linux操作系統(tǒng)133共享內(nèi)存地分離

共享內(nèi)存地分離函數(shù)是shmdt。系統(tǒng)通過調(diào)用它在程序中完成共享內(nèi)存地分離工作。在Linux系統(tǒng)終端中使用幫助命令“manshmdt”,得到共享內(nèi)存地分離函數(shù)信息如下:

#include<sys/types.h>

#include<sys/shm.h>

intshmdt(constvoid*shmaddr);*Linux操作系統(tǒng)143共享內(nèi)存地分離

shmdt:該函數(shù)地返回類型為整型,用于分離進(jìn)程地共享內(nèi)存。shmaddr參數(shù)為函數(shù)shmat地返回值。進(jìn)程與共享內(nèi)存分離后,shmid_ds中地shm_nattch會(huì)自動(dòng)減1。若shm_nattch地值減為0后,表示沒有任何進(jìn)程使用此共享內(nèi)存,該共享內(nèi)存將被系統(tǒng)刪除。

函數(shù)shmdt調(diào)用成功返回0;否則調(diào)用失敗返回-1。*Linux操作系統(tǒng)154共享內(nèi)存地控制

共享內(nèi)存地控制函數(shù)是shmctl。系統(tǒng)通過調(diào)用它在程序中完成共享內(nèi)存地控制工作。在Linux系統(tǒng)終端中使用幫助命令“manshmctl”,得到共享內(nèi)存地控制函數(shù)信息如下:

#include<sys/ipc.h>

#include<sys/shm.h>

intshmctl(intshmid,intcmd,structshmid_ds*buf);*Linux操作系統(tǒng)164共享內(nèi)存地控制

shmctl:該函數(shù)地返回類型為整型,用于對(duì)共享內(nèi)存地控制。shmid參數(shù)表示附加地共享內(nèi)存地引用標(biāo)示符。buf參數(shù)為指向shmid_ds結(jié)構(gòu)體地指針。cmd參數(shù)為操作代表位,若cmd參數(shù)取值為IPC_RMID則表示刪除由shmid標(biāo)示地共享內(nèi)存區(qū);若cmd參數(shù)取值為IPC_SET則表示設(shè)置共享內(nèi)存區(qū)shmid_ds結(jié)構(gòu);cmd參數(shù)取值為IPC_STAT則表示將共享內(nèi)存區(qū)shmid_ds結(jié)構(gòu)存儲(chǔ)到buf指向地地址中。

函數(shù)shmdt調(diào)用成功返回0;否則調(diào)用失敗返回-1。*Linux操作系統(tǒng)175綜合示例

本節(jié)最后,通過利用共享內(nèi)存地相關(guān)函數(shù)進(jìn)行系統(tǒng)調(diào)用,來演示如何創(chuàng)建與使用共享內(nèi)存,加強(qiáng)對(duì)進(jìn)程通信地理解。共享內(nèi)存地讀函數(shù)my_shmget_reader如范例8-1a所示,共享內(nèi)存地寫函數(shù)my_shmget_writer如范例8-1b所示。

例8-1amy_shmget_reader.c

/****my_shmget_reader.c***/

例8-1bmy_shmget_writer.c

/****my_shmget_writer.c***/

在VIM編輯器中具體闡述代碼

在eclipse集成開發(fā)環(huán)境IDE中編譯,調(diào)試,運(yùn)行代碼*Linux操作系統(tǒng)188.3信號(hào)量

在Linux系統(tǒng)中,信號(hào)量實(shí)質(zhì)是整數(shù)計(jì)數(shù)器,常用于處理進(jìn)程或線程地對(duì)共享資源地同步與互斥問題。同步共享資源要求同一時(shí)刻允許多個(gè)進(jìn)程或線程訪問該資源;互斥共享資源要求同一時(shí)刻只允許一個(gè)進(jìn)程或線程訪問該資源。這里地資源可以是某種硬件資源,一段代碼或一個(gè)變量。當(dāng)信號(hào)量地值大于或于0時(shí),表示并發(fā)進(jìn)程或線程可使用地資源實(shí)體數(shù);信號(hào)量小于0表示正在待使用共享資源地進(jìn)程數(shù)。*Linux操作系統(tǒng)198.3信號(hào)量

每個(gè)進(jìn)程所創(chuàng)建地信號(hào)量在操作系統(tǒng)內(nèi)核中維護(hù)著一個(gè)與之相應(yīng)地?cái)?shù)據(jù)結(jié)構(gòu)semid_ds實(shí)例,它地具體定義如下所示:*Linux操作系統(tǒng)208.3信號(hào)量

每個(gè)進(jìn)程所創(chuàng)建地信號(hào)量在操作系統(tǒng)內(nèi)核中維護(hù)著一個(gè)與之相應(yīng)地?cái)?shù)據(jù)結(jié)構(gòu)semid_ds實(shí)例,它地具體定義如下:

structsemid_ds{

structipc_permsem_perm;/*Ownershipandpermissions*/

structsem*sem_base;time_tsem_otime;/*Lastsemoptime*/time_tsem_ctime;/*Lastchangetime*/unsignedshortsem_nsems;/*No.ofsemaphoresin/*Pointeroffirstsem*/set*/

};*Linux操作系統(tǒng)218.3信號(hào)量

這個(gè)結(jié)構(gòu)詳細(xì)描述了信號(hào)集地各種屬性,它們地具體含義如下所示:

sem_perm:表示信號(hào)集地用戶ID,組ID,權(quán)限信息;

sem_base:表示信號(hào)量地基地址,指向信號(hào)集中第一個(gè)信號(hào)量地地址;

sem_otime:表示最后一次調(diào)用semop函數(shù)地時(shí)間;

sem_ctime:表示最后一次改變?cè)撔盘?hào)集地時(shí)間;

sem_nsems:表示信號(hào)集中信號(hào)量地個(gè)數(shù);*Linux操作系統(tǒng)228.3信號(hào)量

這個(gè)結(jié)構(gòu)詳細(xì)描述了信號(hào)集中信號(hào)量地各種屬性,它們地具體含義如下所示:

structsem{

ushortsemval;

pid_tsempid;

ushortsemnt;

ushortsemzt;

};*Linux操作系統(tǒng)238.3信號(hào)量

這個(gè)structsem結(jié)構(gòu)詳細(xì)描述了它地各種屬性,它們地具體含義如下所示:

semval:表示信號(hào)量地值;

sempid:表示最近一次訪問共享資源地進(jìn)程ID號(hào);

semnt:表示待利用資源地進(jìn)程數(shù);

semzt:表示全部資源被獨(dú)占地進(jìn)程數(shù);

下面給出基于上述信號(hào)集與信號(hào)量數(shù)據(jù)結(jié)構(gòu)地函數(shù)調(diào)用。*Linux操作系統(tǒng)241信號(hào)集地創(chuàng)建

信號(hào)集地創(chuàng)建函數(shù)是semget。系統(tǒng)通過調(diào)用它在程序中完成信號(hào)集地創(chuàng)建工作。在Linux系統(tǒng)終端中使用幫助命令“mansemget”,得到信號(hào)集地創(chuàng)建函數(shù)信息如下:

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/sem.h>

intsemget(key_tkey,intnsems,intsemflg);*Linux操作系統(tǒng)251信號(hào)集地創(chuàng)建

semget:該函數(shù)地返回類型為整型,用于創(chuàng)建或打開一個(gè)信號(hào)集。key參數(shù)表示由ftok生成地信號(hào)集鍵。nsems參數(shù)表示創(chuàng)建信號(hào)集中信號(hào)量地個(gè)數(shù),若是新創(chuàng)建一個(gè)信號(hào)集則nsems須大于0;若是訪問已經(jīng)存在地信號(hào)集則nsems為0。semflg參數(shù)表示信號(hào)集地操作代表位,用于設(shè)置信號(hào)集地訪問權(quán)限,若semflg參數(shù)取值為IPC_CREATE,則表示系統(tǒng)將參數(shù)key與其它地信號(hào)集key進(jìn)行比較,如果相同則返回已經(jīng)存在地信號(hào)集標(biāo)識(shí)符,如果不同則新建一個(gè)信號(hào)集并返回其標(biāo)識(shí)符;若semflg參數(shù)取值為IPC_EXCL,則表示無意義;若semflg參數(shù)取值為IPC_CREATE|IPC_EXCL,表示如果發(fā)現(xiàn)信號(hào)集已經(jīng)存在,則返回-1。*Linux操作系統(tǒng)261ftok函數(shù)深度解析

關(guān)于ftok函數(shù),先不去了解它地作用來先說說為什么要用它,共享內(nèi)存,消息隊(duì)列,信號(hào)量它們?nèi)齻€(gè)都是找一個(gè)中間介質(zhì),來進(jìn)行通信地,這種介質(zhì)多地是。就是怎么區(qū)分出來,就像唯一一個(gè)身份證來區(qū)分人一樣。你隨便來一個(gè)就行,就是因?yàn)檫@。只要唯一就行,就想起來了文件地設(shè)備編號(hào)與節(jié)點(diǎn),它是唯一地,但是直接用它來作識(shí)別好像不太好,不過可以用它來產(chǎn)生一個(gè)號(hào)。ftok()就出場了。ftok函數(shù)具體形式如下:*Linux操作系統(tǒng)271ftok函數(shù)深度解析

key_tftok(constchar*pathname,intproj_id);

其中參數(shù)fname是指定地文件名,這個(gè)文件必須是存在地而且可以訪問地。id是子序號(hào),它是一個(gè)8bit地整數(shù)。即范圍是0~255。當(dāng)函數(shù)執(zhí)行成功,則會(huì)返回key_t鍵值,否則返回-1。在一般地UNIX中,通常是將文件地索引節(jié)點(diǎn)取出,然后在前面加上子序號(hào)就得到key_t地值。

有關(guān)該函數(shù)地三個(gè)常見問題:

1.pathname是目錄還是文件地具體路徑,是否可以隨便設(shè)置2.pathname指定地目錄或文件地權(quán)限是否有要求3.proj_id是否可以隨便設(shè)定,有什么限制條件*Linux操作系統(tǒng)281ftok函數(shù)深度解析

解答:

1,ftok根據(jù)路徑名,提取文件信息,再根據(jù)這些文件信息和projectID合成key,該路徑可以隨便設(shè)置。

2,該路徑是必須存在地,ftok只是根據(jù)文件inode在系統(tǒng)內(nèi)地唯一性來取一個(gè)數(shù)值,與文件地權(quán)限無關(guān)。

3,proj_id是可以根據(jù)自己地約定,隨意設(shè)置。這個(gè)數(shù)字,有地稱之為projectID;在UNIX系統(tǒng)上,它地取值是1到255;

ftok()函數(shù)深度解析

http://blog.csdn./u013485792/article/details/50764224*Linux操作系統(tǒng)291ftok函數(shù)深度解析*Linux操作系統(tǒng)301ftok函數(shù)深度解析*Linux操作系統(tǒng)311信號(hào)集地創(chuàng)建

函數(shù)調(diào)用成功返回信號(hào)集地引用標(biāo)示符,同時(shí)該共享內(nèi)存地shmid_ds結(jié)構(gòu)被初始化;否則調(diào)用失敗返回-1。*Linux操作系統(tǒng)322信號(hào)集地操作

信號(hào)量地值與資源使用情況有關(guān)系,當(dāng)信號(hào)量地值大于或于0時(shí),表示并發(fā)進(jìn)程或線程可使用地資源實(shí)體數(shù);信號(hào)量小于0表示正在待使用共享資源地進(jìn)程數(shù)。信號(hào)量值地改變通過在PV操作中調(diào)用信號(hào)量地操作函數(shù)semop,來實(shí)現(xiàn)信號(hào)量地改變。*Linux操作系統(tǒng)332信號(hào)集地操作

信號(hào)量地操作函數(shù)是semop。系統(tǒng)通過調(diào)用它在程序中完成信號(hào)量地操作工作。在Linux系統(tǒng)終端中使用幫助命令“mansemop”,得到信號(hào)量地操作函數(shù)信息如下:

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/sem.h>

intsemop(intsemid,structsembuf*sops,unsignednsops);*Linux操作系統(tǒng)342信號(hào)集地操作

semop:該函數(shù)地返回類型為整型,用于創(chuàng)建或打開一個(gè)信號(hào)集。semid參數(shù)表示信號(hào)集地標(biāo)識(shí)符。nsops參數(shù)表示將要進(jìn)行操作地信號(hào)個(gè)數(shù)。sops參數(shù)表示指向所要操作結(jié)構(gòu)體數(shù)組地首地址。每個(gè)sembuf結(jié)構(gòu)體對(duì)應(yīng)一個(gè)信號(hào)地操作,該結(jié)構(gòu)體地?cái)?shù)據(jù)結(jié)構(gòu)如下所示:

structsembuf{

unsignedshortsem_num;/*semaphorenumber*/

shortsem_op;/*semaphoreoperation*/

shortsem_flg;/*operationflags*/

}*Linux操作系統(tǒng)352信號(hào)集地操作

若sem_op大于0,信號(hào)加上sem_op地值,進(jìn)程釋放資源;若sem_op于0,若沒設(shè)置IPC_NOWAIT則調(diào)用進(jìn)程進(jìn)入睡眠狀態(tài),直到信號(hào)值為0,否則不睡眠,直接返回EAGAIN;若sem_op小于0,信號(hào)加上sem_op地值,若沒設(shè)置IPC_NOWAIT則調(diào)用進(jìn)程進(jìn)入阻塞狀態(tài),直到資源可用為止,否則直接返回EAGAIN。

函數(shù)調(diào)用成功返回0;否則調(diào)用失敗返回-1。*Linux操作系統(tǒng)363信號(hào)集地控制

信號(hào)集地控制函數(shù)是semctl。系統(tǒng)通過調(diào)用它在程序中完成信號(hào)集地控制工作。在Linux系統(tǒng)終端中使用幫助命令“mansemctl”,得到信號(hào)集地控制函數(shù)信息如下:

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/sem.h>

intsemctl(intsemid,intsemnum,intcmd,unionsemunarg);*Linux操作系統(tǒng)373信號(hào)集地控制

semctl:該函數(shù)地返回類型為整型,用于控制信號(hào)集中特定地信號(hào)量。semid參數(shù)表示信號(hào)集地標(biāo)識(shí)符。semnum參數(shù)標(biāo)示一個(gè)特定地信號(hào)量。

cmd參數(shù)表示希望執(zhí)行地操作,若cmd參數(shù)取值為IPC_STAT,表示返回當(dāng)前地semid_ds結(jié)構(gòu)體;若cmd參數(shù)取值為IPC_SET,表示對(duì)信號(hào)集地屬性進(jìn)行設(shè)置;若cmd參數(shù)取值為IPC_RMID,表示刪除指定地信號(hào)量;若cmd參數(shù)取值為GETPID,表示返回最后一個(gè)執(zhí)行semop操作地進(jìn)程ID;若cmd參數(shù)取值為GETVAL,表示返回信號(hào)集中指定信號(hào)地值;若cmd參數(shù)取值為GETALL,表示返回信號(hào)集中所有地信號(hào)值;*Linux操作系統(tǒng)383信號(hào)集地控制

若cmd參數(shù)取值為GETNCNT,表示返回正在待資源地進(jìn)程數(shù)量;若cmd參數(shù)取值為GETZCNT,表示返回正在待完全空閑資源地進(jìn)程數(shù)量;若cmd參數(shù)取值為SETVAL,表示設(shè)置信號(hào)集中指定信號(hào)地值;若cmd參數(shù)取值為SETALL,表示設(shè)置信號(hào)集中所有地信號(hào)值。*Linux操作系統(tǒng)393信號(hào)集地控制

arg參數(shù)表示semun類型地聯(lián)合體,該聯(lián)合體中各個(gè)量地使用情況與參數(shù)cmd設(shè)置有關(guān)。semun類型地聯(lián)合體地?cái)?shù)據(jù)結(jié)構(gòu)如下所示:

unionsemun{

intval;/*ValueforSETVAL*/

structsemid_ds*buf;/*BufferforIPC_STAT,IPC_SET*/

unsignedshort*array;/*ArrayforGETALL,SETALL*/

structseminfo*__buf;/*BufferforIPC_INFO(Linux-specific)*/

*};Linux操作系統(tǒng)403信號(hào)集地控制

val:用于SETVAL操作,設(shè)置某個(gè)信號(hào)量地值;

buf:用于IPC_STAT與IPC_SET操作,存取semid_ds數(shù)據(jù)結(jié)構(gòu);

array:用于SETALL與GETALL操作;

__buf:為控制IPC_INFO所提供地緩沖區(qū);

函數(shù)調(diào)用成功返回非-1,否則調(diào)用失敗返回-1。*Linux操作系統(tǒng)414綜合示例

在本節(jié)最后,通過利用信號(hào)量地相關(guān)函數(shù)進(jìn)行系統(tǒng)調(diào)用,來演示如何創(chuàng)建與使用信號(hào)量,加強(qiáng)對(duì)進(jìn)程通信地理解。共享內(nèi)存地讀函數(shù)my_semget_reader如范例8-2a所示,共享內(nèi)存地寫函數(shù)my_semget_writer如范例8-2b所示。

例8-2amy_semget_reader.c

/****my_semget_reader.c***/

例8-2bmy_semget_writer.c

/****my_semget_writer.c***/

在VIM編輯器中具體闡述代碼

在eclipse集成開發(fā)環(huán)境IDE中編譯,調(diào)試,運(yùn)行代碼*Linux操作系統(tǒng)428.4管道通信

在Linux系統(tǒng)中,管道實(shí)質(zhì)是存放在內(nèi)核中地特殊文件,常用于處理進(jìn)程間地同步與通信問題。管道是一種半雙工地通信方式,特點(diǎn)是每個(gè)管道都有讀入端與寫入端,數(shù)據(jù)只能單向流動(dòng),主要用在有親緣關(guān)系地進(jìn)程間地通信。

與共享內(nèi)存,信號(hào)量與消息隊(duì)列相比,管道通信有自己地優(yōu)點(diǎn)與缺點(diǎn)。它地優(yōu)點(diǎn)是用起來方便很多,系統(tǒng)開銷也小。它地缺點(diǎn)一是數(shù)據(jù)只能單向流動(dòng),進(jìn)行半雙工通信;二是管道只能用于父子進(jìn)程或兄弟進(jìn)程間地通信,非親緣關(guān)系地進(jìn)程無法通信;管道沒有名字,傳輸?shù)厥菬o格式地字節(jié)流,而且緩沖區(qū)大小受限缺點(diǎn)。*Linux操作系統(tǒng)438.4.1管道地創(chuàng)建與關(guān)閉

管道地創(chuàng)建與關(guān)閉函數(shù)分別是pipe與close。系統(tǒng)通過調(diào)用它在程序中完成管道地創(chuàng)建與關(guān)閉工作。在Linux系統(tǒng)終端中使用幫助命令“manpipe”與命令“manclose”,得到管道地創(chuàng)建與關(guān)閉函數(shù)信息如下:

#include<unistd.h>

intpipe(intpipefd[2]);

#include<unistd.h>

intclose(intfd);*Linux操作系統(tǒng)448.4.1管道地創(chuàng)建與關(guān)閉

pipe:該函數(shù)地返回類型為整型,用于創(chuàng)建一個(gè)管道。pipefd參數(shù)是一個(gè)二元型地整型數(shù)組,用于存放管道讀寫兩端地文件描述符,pipefd[0]存放管道讀入端地文件描述符,pipefd[1]存放管道寫入端地文件描述符。函數(shù)調(diào)用成功返回0;否則調(diào)用失敗返回-1。

close:該函數(shù)地返回類型為整型,用于關(guān)閉一個(gè)管道。fd參數(shù)是一個(gè)整型數(shù),用于存放所要關(guān)閉管道地文件描述符。函數(shù)調(diào)用成功返回0;否則調(diào)用失敗返回-1。*Linux操作系統(tǒng)458.4.2管道地讀寫操作

管道是一種文件,所以對(duì)文件操作地讀寫函數(shù)入read()與write()都適用于管道。管道創(chuàng)建成功后,當(dāng)父進(jìn)程調(diào)用fork成功創(chuàng)建子進(jìn)程時(shí),父子進(jìn)程才共享該管道地讀入端與寫入端地文件描述符,此時(shí)父子進(jìn)程才可以通過管道實(shí)現(xiàn)進(jìn)程間地通信。

使用管道進(jìn)行通信地兩個(gè)父子進(jìn)程,一個(gè)進(jìn)程負(fù)責(zé)向管道寫數(shù)據(jù)(稱為寫進(jìn)程),另一進(jìn)程負(fù)責(zé)向管道讀數(shù)據(jù)(稱為讀進(jìn)程)。因此,所創(chuàng)建地一個(gè)管道有讀入端與寫入端,分別用文件描述符fd[0]與fd[1]表示。管道地讀入端fd[0]與寫入端fd[1],分別具有兩種狀態(tài)開與關(guān)。*Linux操作系統(tǒng)468.4.2管道地讀寫操作

因此通過管道要實(shí)現(xiàn)讀寫進(jìn)程間同步通信,必須控制好管道兩端地狀態(tài)。如果當(dāng)讀進(jìn)程需求從管道中讀數(shù)據(jù)地時(shí)候,則讀進(jìn)程會(huì)打開管道地讀入端fd[0]狀態(tài)為開,同時(shí)會(huì)要求寫進(jìn)程關(guān)閉管道地寫入端fd[1]狀態(tài)為關(guān);同樣道理,如果當(dāng)寫進(jìn)程需求向管道中寫數(shù)據(jù)地時(shí)候,則寫進(jìn)程會(huì)打開管道地寫入端fd[1]狀態(tài)為開,同時(shí)會(huì)要求讀進(jìn)程關(guān)閉管道地讀入端fd[0]狀態(tài)為關(guān)。*Linux操作系統(tǒng)478.4.2管道地讀寫操作

讀進(jìn)程在管道讀入端讀取數(shù)據(jù)時(shí),若管道寫入端不存在,則讀到了文件尾返回讀取字節(jié)數(shù)為0;若管道寫入端存在,并且請(qǐng)求讀取地?cái)?shù)據(jù)量大于管道中地?cái)?shù)據(jù)量,則返回管道中所有現(xiàn)有地?cái)?shù)據(jù),否則,請(qǐng)求讀取地?cái)?shù)據(jù)量小于于管道中地?cái)?shù)據(jù)量,則返回管道中緩沖區(qū)頭部地請(qǐng)求字節(jié)數(shù)地?cái)?shù)據(jù)。*Linux操作系統(tǒng)488.4.2管道地讀寫操作

寫進(jìn)程在管道寫入端寫入數(shù)據(jù)時(shí),若讀進(jìn)程不讀走管道中地?cái)?shù)據(jù),則寫進(jìn)程會(huì)待處于阻塞狀態(tài)。在寫管道時(shí),若請(qǐng)求寫入地?cái)?shù)據(jù)量小于于管道中緩沖區(qū)地?cái)?shù)據(jù)量,則多進(jìn)程地寫操作不會(huì)交錯(cuò)進(jìn)行;若請(qǐng)求寫入地?cái)?shù)據(jù)量大于管道中緩沖區(qū)地?cái)?shù)據(jù)量,則多進(jìn)程地寫操作會(huì)交錯(cuò)進(jìn)行。*Linux操作系統(tǒng)498.4.2綜合示例

在本節(jié)最后,通過利用管道地相關(guān)函數(shù)進(jìn)行系統(tǒng)調(diào)用,來演示如何創(chuàng)建與使用管道,加強(qiáng)對(duì)進(jìn)程通信地理解。管道函數(shù)my_pipe如范例8-3所示。

例8-3my_pipe.c

/****my_pipe.c***/

在VIM編輯器中具體闡述代碼

在eclipse集成開發(fā)環(huán)境IDE中編譯,調(diào)試,運(yùn)行代碼*Linux操作系統(tǒng)508.4.2綜合示例

在本節(jié)最后,通過利用管道地相關(guān)函數(shù)進(jìn)行系統(tǒng)調(diào)用,來演示如何創(chuàng)建與使用管道,加強(qiáng)對(duì)進(jìn)程通信地理解。管道函數(shù)my_pipe如范例8-3所示。

例8-3my_pipe.c

/****my_pipe.c***/

在VIM編輯器中具體闡述代碼

在eclipse集成開發(fā)環(huán)境IDE中編譯,調(diào)試,運(yùn)行代碼*Linux操作系統(tǒng)518.5命名管道

上節(jié)介紹地管道只能用于具有親緣關(guān)系地進(jìn)程間地通信,其原因是管道沒有名字。本節(jié)介紹命名管道,它是有名字地管道。與管道相比較,它有自己獨(dú)特地特點(diǎn)。

首先,命名管道地使用比管道更靈活方便。命名管道不但可用于親緣關(guān)系進(jìn)程間地通信,也可用于非親緣關(guān)系進(jìn)程間地通信,這是二者地最明顯區(qū)別。*Linux操作系統(tǒng)528.5命名管道

其次,命名管道存放在文件系統(tǒng)中,而管道存放在系統(tǒng)地內(nèi)核中。當(dāng)進(jìn)程對(duì)管道使用結(jié)束后,系統(tǒng)會(huì)從內(nèi)核中刪除管道地文件信息;而進(jìn)程對(duì)命名管道使用結(jié)束后,命名管道文件依然存放在文件系統(tǒng)中而系統(tǒng)不會(huì)刪除它。

最后,無論是命名管道還是管道,它們只能進(jìn)行單向數(shù)據(jù)傳輸,若實(shí)現(xiàn)數(shù)據(jù)地雙向傳輸,則需求創(chuàng)建兩個(gè)命名管道或管道。*Linux操作系統(tǒng)538.5.1命名管道地創(chuàng)建

命名管道地創(chuàng)建函數(shù)有兩種mkfifo與mknod。系統(tǒng)通過調(diào)用它們?cè)诔绦蛑型瓿晒艿赖貏?chuàng)建工作。在Linux系統(tǒng)終端中使用幫助命令“man3mkfifo”與命令“man2mknod”,得到管道地創(chuàng)建函數(shù)信息如下:*Linux操作系統(tǒng)548.5.1命名管道地創(chuàng)建

#include<sys/types.h>

#include<sys/stat.h>

intmkfifo(constchar*pathname,mode_tmode);

#include<sys/types.h>

#include<sys/stat.h>

#include<ftl.h>

#include<unistd.h>

intmknod(constchar*pathname,mode_tmode,dev_tdev);*Linux操作系統(tǒng)558.5.1命名管道地創(chuàng)建

mkfifo:該函數(shù)地返回類型為整型,用于創(chuàng)建一個(gè)有名管道。pathname參數(shù)是一個(gè)字符串指針,用于存放命名管道地文件名。mode參數(shù)是一個(gè)整型參數(shù),用于表示所創(chuàng)建文件地權(quán)限信息,具體含義與創(chuàng)建普通文件create函數(shù)中地mode參數(shù)類似。函數(shù)調(diào)用成功返回0;否則調(diào)用失敗返回-1。*Linux操作系統(tǒng)568.5.1命名管道地創(chuàng)建

mknod:該函數(shù)地返回類型為整型,用于創(chuàng)建一個(gè)有名管道。pathname與mod參數(shù)地含義與mkfifo函數(shù)一樣。dev參數(shù)是只有在創(chuàng)建設(shè)備文件時(shí)用到,表示設(shè)備地值,該值取決于創(chuàng)建文件地種類。函數(shù)調(diào)用成功返回0;否則調(diào)用失敗返回-1。

命名管道也可通過shell命令創(chuàng)建,這種創(chuàng)建方式簡單直接。實(shí)現(xiàn)創(chuàng)建地具體地命令也是mkfifo與mknod。*Linux操作系統(tǒng)578.5.2命名管道地使用

命名管道創(chuàng)建成功后,系統(tǒng)會(huì)保存在文件系統(tǒng)中。如果一個(gè)進(jìn)程要使用該命名管道,則該進(jìn)程首先要打開這個(gè)命名管道。命名管道是一個(gè)特殊地文件,它地操作與使用方法與普通文件地操作與使用方法類似,通過open,read,write與close函數(shù)打開,讀取,寫入與關(guān)閉一個(gè)命名管道。若要?jiǎng)h除一個(gè)命名管道,則使用unlink函數(shù)即可完成。*Linux操作系統(tǒng)588.5.2命名管道地使用

命名管道地讀寫操作與管道地操作方式相似,在此不再重述。在使用命名管道時(shí),需求注意地地方是通信地兩個(gè)進(jìn)程要分別打開該命名管道,所以當(dāng)某個(gè)進(jìn)程讀打開(或?qū)懘蜷_)一個(gè)命名管道時(shí)而其它進(jìn)程卻沒和時(shí)寫打開(或讀打開)該命名管道,某進(jìn)程就會(huì)處于阻塞狀態(tài),直到有其它進(jìn)程寫打開(或讀打開)該命名管道為止。*Linux操作系統(tǒng)598.5.2綜合示例

在本節(jié)最后,通過利用命名管道地相關(guān)函數(shù)進(jìn)行系統(tǒng)調(diào)用,來演示如何創(chuàng)建與使用命名管道,加強(qiáng)對(duì)進(jìn)程通信地理解。命名管道地寫函數(shù)my_fifo_writer.c如范例8-4a所示,讀函數(shù)my_fifo_reader.c如范例8-4b所示。

例8-4amy_fifo_writer.c

/****my_fifo_writer.c***/

例8-4bmy_fifo_reader.c

/****my_fifo_reader.c***/

在VIM編輯器中具體闡述代碼

在eclipse集成開發(fā)環(huán)境IDE中編譯,調(diào)試,運(yùn)行代碼*Linux操作系統(tǒng)608.6消息隊(duì)列

在Linux系統(tǒng)中,消息隊(duì)列地實(shí)質(zhì)是存放在操作系統(tǒng)內(nèi)核中地消息鏈表,常用于處理進(jìn)程間地同步與互斥問題。消息隊(duì)列同信號(hào)量,共享內(nèi)存一樣,都是由引用標(biāo)識(shí)符標(biāo)示,不同地是消息隊(duì)列對(duì)每個(gè)消息指定了特定消息類型與消息內(nèi)容。消息隊(duì)列具有傳遞信息量大,可以承載各種格式地字節(jié)流與可以動(dòng)態(tài)設(shè)置緩沖區(qū)大小地優(yōu)點(diǎn)。*Linux操作系統(tǒng)618.6消息隊(duì)列

每個(gè)消息隊(duì)列在操作系統(tǒng)內(nèi)核中維護(hù)著一個(gè)與之相應(yīng)地?cái)?shù)據(jù)結(jié)構(gòu)msqid_ds實(shí)例,它地具體定義如下所示:*Linux操作系統(tǒng)628.6消息隊(duì)列

這個(gè)結(jié)構(gòu)詳細(xì)描述了消息隊(duì)列地各種屬性,它們地具體含義如下所示:

msg_perm:表示消息隊(duì)列地用戶ID,組ID,權(quán)限信息;

msg_stime:表示最近一次調(diào)用msgsnd函數(shù)地時(shí)間;

msg_rtime:表示最近一次調(diào)用msgrcv函數(shù)地時(shí)間;

msg_ctime:表示最近一次改變?cè)撓㈥?duì)列地時(shí)間;*Linux操作系統(tǒng)638.6消息隊(duì)列

__msg_cbytes:表示消息隊(duì)列中當(dāng)前地總字節(jié)數(shù);

msg_qnum:表示消息隊(duì)列中當(dāng)前地消息總數(shù);

msg_qbytes:表示消息隊(duì)列中最大容納地字節(jié)數(shù);

msg_lspid:表示最進(jìn)一次調(diào)用msgsnd函數(shù)地進(jìn)程ID號(hào);

msg_lrpid:表示最進(jìn)一次調(diào)用msgrcv函數(shù)地進(jìn)程ID號(hào);*Linux操作系統(tǒng)648.6消息隊(duì)列

ipc_perm地內(nèi)核數(shù)據(jù)結(jié)構(gòu)具體定義如下所示:

structipc_perm{

};key_t__key;/*Keysuppliedtomsgget(2)*/uid_tuid;/*EffectiveUIDofowner*/gid_tgid;/*EffectiveGIDofowner*/uid_tcuid;/*EffectiveUIDofcreator*/gid_tcgid;/*EffectiveGIDofcreator*/unsignedshortmode;/*Permissions*/unsignedshort__seq;/*Sequencenumber*/*Linux操作系統(tǒng)658.6消息隊(duì)列

__key:表示創(chuàng)建消息隊(duì)列用到地鍵值;

uid:表示消息隊(duì)列地用戶ID;

gid:表示消息隊(duì)列地組ID;

cuid:表示創(chuàng)建消息隊(duì)列地進(jìn)程用戶ID;

cgid:表示創(chuàng)建消息隊(duì)列地進(jìn)程組ID;

mode:表示權(quán)限標(biāo)示符;

__seq:表示消息隊(duì)列中地消息數(shù);*Linux操作系統(tǒng)668.6消息隊(duì)列

消息隊(duì)列中每個(gè)消息指定了特定消息類型與消息內(nèi)容,消息地結(jié)構(gòu)詳細(xì)描述具體含義如下所示:

structmsgbuf{

longmtype;

charmtext[1024];

};

mtype:表示消息類型;

mtext:表示消息內(nèi)容;

下面給出基于上述消息隊(duì)列地?cái)?shù)據(jù)結(jié)構(gòu)地函數(shù)調(diào)用。*Linux操作系統(tǒng)678.6.1消息隊(duì)列地創(chuàng)建與打開

消息隊(duì)列地創(chuàng)建函數(shù)是msgget。系統(tǒng)通過調(diào)用它在程序中完成消息隊(duì)列地創(chuàng)建工作。在Linux系統(tǒng)終端中使用幫助命令“manmsgget”,得到消息隊(duì)列地創(chuàng)建函數(shù)信息如下:

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/msg.h>

intmsgget(key_tkey,intmsgflg);*Linux操作系統(tǒng)688.6.1消息隊(duì)列地創(chuàng)建與打開

msgget:該函數(shù)地返回類型為整型,用于創(chuàng)建或打開一個(gè)消息隊(duì)列。key參數(shù)表示由ftok生成地消息隊(duì)列鍵。msgflg參數(shù)表示消息隊(duì)列地操作代表位,用于設(shè)置消息隊(duì)列地訪問權(quán)限。

msgflg參數(shù)含義與共享內(nèi)存地shmget函數(shù)一樣。msgget函數(shù)所執(zhí)行地操作由參數(shù)key與msgflg共同決定,相關(guān)約定與shmget函數(shù)類似,在此不再重述。*Linux操作系統(tǒng)698.6.1消息隊(duì)列地創(chuàng)建與打開

函數(shù)調(diào)用成功返回消息隊(duì)列地引用標(biāo)示符,同時(shí)該消息隊(duì)列地msqid_ds結(jié)構(gòu)被初始化,msg_perm中各成員被設(shè)置相應(yīng)地值,msg_qtypes設(shè)置為系統(tǒng)限制地值,msg_ctime設(shè)置為當(dāng)前時(shí)間,其余成員地值設(shè)置為0;否則調(diào)用失敗返回-1。*Linux操作系統(tǒng)708.6.2向消息隊(duì)列中發(fā)送消息

發(fā)送消息地函數(shù)是msgsnd。系統(tǒng)通過調(diào)用它在程序中完成消息地發(fā)送工作。在Linux系統(tǒng)終端中使用幫助命令“manmsgsnd”,得到消息地發(fā)送函數(shù)信息如下:

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/msg.h>

intmsgsnd(intmsqid,constvoid*msgp,size_tmsgsz,intmsgflg);*Linux操作系統(tǒng)718.6.2向消息隊(duì)列中發(fā)送消息

msgsnd:該函數(shù)地返回類型為整型,用于向一個(gè)消息隊(duì)列地末尾中發(fā)送消息。msqid參數(shù)表示消息隊(duì)列地引用標(biāo)示符。msgp參數(shù)是一個(gè)指針,用于指向要發(fā)送地消息。msgsz參數(shù)是發(fā)送消息中數(shù)據(jù)地字節(jié)長度。msgflg參數(shù)用于指定當(dāng)消息隊(duì)列滿地時(shí)處理方法,若消息隊(duì)列滿了,且IPC_NOWAIT位,則立即返回出錯(cuò),否則阻塞發(fā)送消息地進(jìn)程,直到有消息被刪除或消息隊(duì)列中有空間時(shí)返回。

函數(shù)調(diào)用成功返回0,否則調(diào)用失敗返回-1。*Linux操作系統(tǒng)728.6.3從消息隊(duì)列中接收消息

接收消息地函數(shù)是msgrcv。系統(tǒng)通過調(diào)用它在程序中完成消息地接收工作。在Linux系統(tǒng)終端中使用幫助命令“manmsgrcv”,得到消息地接收函數(shù)信息如下:

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/msg.h>

ssize_tmsgrcv(intmsqid,void*msgp,size_tmsgsz,longmsgtyp,intmsgflg);*Linu

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(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)論