西安郵電大學Linux高級編程進程間通信_第1頁
西安郵電大學Linux高級編程進程間通信_第2頁
西安郵電大學Linux高級編程進程間通信_第3頁
西安郵電大學Linux高級編程進程間通信_第4頁
西安郵電大學Linux高級編程進程間通信_第5頁
已閱讀5頁,還剩64頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

第5章SystemV進程間通信12SystemV

IPC基礎

消息隊列

3信號量通信機制

4共享內(nèi)存

第一頁,共七十三頁。為了提供與其他系統(tǒng)的兼容性,Linux也支持三種SystemV的進程間通信機制:消息隊列、信號量和共享內(nèi)存,Linux對這些機制的實施大同小異。我們把信號量、消息隊列和共享內(nèi)存統(tǒng)稱SystemVIPC對象。就像每個文件都有一個打開文件號一樣,每個對象也都有唯一的識別號,進程可以通過系統(tǒng)調(diào)用傳遞的識別號來存取這些對象。與文件的存取一樣,對這些對象的存取也要驗證存取權限,SystemVIPC可以通過系統(tǒng)調(diào)用對對象的創(chuàng)建者設置這些對象的存取權限。2023/5/82第二頁,共七十三頁。ipcs命令Ipcs命令用于顯示消息隊列、共享內(nèi)存、信號量的信息。

q顯示消息隊列s顯示信號量

m顯示共享內(nèi)存a詳細信息對每一個資源,這個命令會顯示:TYPE包括信息隊列(q),共享內(nèi)存(m),或者信號量(s)。ID資源條目的唯一的表示號KEY應用程序存取資源使用的參數(shù)。MODE存取模式和許可權限的標記OWNERandGROUP登錄名和用戶屬主的組號2023/5/83第三頁,共七十三頁。key值和ID值Linux系統(tǒng)為每個IPC機制都分配了唯一的ID,所有針對該IPC機制的操作都使用對應的ID。因此,通信的雙方都需要通過某個辦法來獲取ID值。顯然,創(chuàng)建者根據(jù)創(chuàng)建函數(shù)的返回值可獲取該值,但另一個進程如何實現(xiàn)呢?由于Linux兩個進程不能隨意訪問對方的空間(一個特殊是,子進程可以繼承父親進程的數(shù)據(jù),實現(xiàn)父親進程向子進程的單向傳遞),也就不能夠直接獲取這一ID值。為解決這一問題,IPC在實現(xiàn)時約定使用key值做為參數(shù)創(chuàng)建,如果在創(chuàng)建時使用相同的key值將得到同一個IPC對象的ID(即一方創(chuàng)建,另一方獲取的是ID),這樣就保證了雙方可以獲取用于傳遞數(shù)據(jù)的IPC機制ID值。2023/5/84第四頁,共七十三頁。ftokexternkey_tftok(__constchar*__pathname,int__proj_id);此函數(shù)有兩個參數(shù),pathname為文件路徑名,可以是特殊文件(例如目錄文件),也可以是當前目錄“.”,而通常也是設置此參數(shù)為當前目錄,因為當前目錄一般都是存在的,且不會被立即刪除。第二個參數(shù)為一個int型變量。2023/5/85第五頁,共七十三頁。例:ftok的使用#include<stdio.h>#include<sys/types.h>main(){ key_tkey; key=ftok(".",1); printf("thekeyis%x\n",key); }2023/5/8人民郵電出版社出版楊宗德編著6第六頁,共七十三頁。ftokftok函數(shù)創(chuàng)建key值過程中使用了該文件屬性的st_dev和st_ino。具體構成如下:key值的第31-24為ftok()第二個參數(shù)的低8位;key值的第23-16為該文件的st_dev屬性的低8位;key值的第15-0為該文件的st_ino屬性的低16位;因此,如果使用相同的文件路徑及整數(shù),得到的key值是唯一的,而唯一的key值創(chuàng)建某類IPC機制時將得到同一個IPC機制(但如果使用相同的key值分別創(chuàng)建一個消息隊列和一個信號量,兩者沒有聯(lián)系),而文件路徑的訪問對兩個進程來說很容易統(tǒng)一,因此,便捷的實現(xiàn)了兩進程通信機制的確定。2023/5/87第七頁,共七十三頁。例:ftok函數(shù)和參數(shù)的關系#include<sys/ipc.h>#include<stdio.h>#include<stdlib.h>#include<sys/stat.h>main(intargc,char*argv[]){ key_tkey; inti; structstatbuf; if(argc!=3) { printf("errorusage\n"); return1; } i=atoi(argv[2]);2023/5/88第八頁,共七十三頁。例:ftok函數(shù)和參數(shù)的關系 if((stat(argv[1],&buf))==-1) { perror("stat"); exit(EXIT_FAILURE); } printf("\n",buf.st_dev); printf("\n",buf.st_ino); printf("number=%x\n",i); key=ftok(argv[1],i); printf("key=0x%x",key);}2023/5/89第九頁,共七十三頁。第5章SystemV進程間通信12SystemV

IPC基礎

消息隊列

3信號量通信機制

4共享內(nèi)存

第十頁,共七十三頁。消息隊列的基本概念消息隊列就是一個消息的鏈表,是一系列保存在內(nèi)核中的消息的列表。用戶進程可以向消息隊列添加消息,也可以從消息隊列讀取消息。消息隊列與管道通信相比,其優(yōu)勢是對每一個消息指定特定消息類型,接收的時候不需要按隊列次序,而是可以根據(jù)自定義條件接收特定類型的消息??梢园严⒖醋饕粋€記錄,具有特定的格式以及特定的優(yōu)先級。對消息隊列有寫權限的進程可以向消息隊列中按照一定的規(guī)則添加新消息;對消息隊列有讀權限的進程則可以從消息隊列中讀取消息。2023/5/811第十一頁,共七十三頁。消息隊列屬性2023/5/812第十二頁,共七十三頁。消息structmsg結(jié)構體//comefrom/usr/src/kernels/’uname–r’/inlcude/linux/msg.h/*onemsg_msgstructureforeachmessage*/structmsg_msg{ structlist_headm_list; longm_type; intm_ts;/*messagetestsize*/ structmsg_msgseg*next; void*security; /*theactualmessagefollowsimmediately*/};2023/5/813第十三頁,共七十三頁。消息隊列2023/5/814第十四頁,共七十三頁。對消息隊列的說明對消息隊列的限定://comefrom/usr/include/linux/msg.h#defineMSGMNI16/*<=IPCMNI*//*max#ofmsgqueueidentifiers*/#defineMSGMAX8192/*<=INT_MAX*//*maxsizeofmessage(bytes)*/#defineMSGMNB16384/*<=INT_MAX*//*defaultmaxsizeofamessagequeue*/不同的系統(tǒng)限制值可以通過msgctl函數(shù)使用IPC_INFO參數(shù)獲得。2023/5/815第十五頁,共七十三頁。消息隊列常用的系統(tǒng)調(diào)用函數(shù)功能ftok根據(jù)文件路徑和參數(shù)生成標準keymsgget創(chuàng)建或打開消息隊列msgsnd添加消息msgrcv讀取消息msgctl控制消息隊列2023/5/816第十六頁,共七十三頁。創(chuàng)建消息隊列externintmsgget(key_t__key,int__msgflg);第一個參數(shù)key為由ftok創(chuàng)建的key值。第二個參數(shù)__msgflg的低位用來確定消息隊列的訪問權限。如0770,為文件的訪問權限類型。此外,還可以附加以下參數(shù)值。這些值可以與基本權限以或的方式一起使用。//comefrom/usr/include/bit/ipc.h/*resourcegetrequestflags*/#defineIPC_CREAT00001000/*createifkeyisnonexistent*/#defineIPC_EXCL00002000/*failifkeyexists*/#defineIPC_NOWAIT00004000/returnerroronwait*/2023/5/817第十七頁,共七十三頁。msgget返回說明:成功執(zhí)行時,返回消息隊列標識值。失敗返回-1,errno被設為以下的某個值,有時也會返回0,這個時候也是可以正常使用的。EACCES:指定的消息隊列已存在,但調(diào)用進程沒有權限訪問它,而且不擁有CAP_IPC_OWNER權限EEXIST:key指定的消息隊列已存在,而msgflg中同時指定IPC_CREAT和IPC_EXCL標志ENOENT:key指定的消息隊列不存在,同時msgflg中不指定IPC_CREAT標志ENOMEM:需要建立消息隊列,但內(nèi)存不足ENOSPC:需要建立消息隊列,但已達到系統(tǒng)的最大消息隊列容量2023/5/818第十八頁,共七十三頁。例:創(chuàng)建消息隊列#include<stdio.h>#include<sys/ipc.h>#include<sys/types.h>intmain(){ key_tkey; key=ftok(".",1); printf("thekeyis%x\n",key); intid; id=msgget(key+1,IPC_CREAT|0666); printf("id=%d\n",id); system(“ipcs”);}2023/5/8人民郵電出版社出版楊宗德編著19第十九頁,共七十三頁。消息隊列屬性控制externintmsgctl(int__msqid,int__cmd,structmsqid_ds*__buf);第一個參數(shù)__msqid為消息隊列標識符,該值為使用msgget函數(shù)創(chuàng)建消息隊列的返回值。第二個參數(shù)__cmd為執(zhí)行的控制命令,即要執(zhí)行的操作。包括以下選項://comefrom/usr/include/linux/ipc.h/*Controlcommandsusedwithsemctl,msgctlandshmctlseealsospecificcommandsinsem.h,msg.handshm.h*/#defineIPC_RMID0/*removeresource*/#defineIPC_SET1/*setipc_permoptions*/#defineIPC_STAT2/*getipc_permoptions*/#defineIPC_INFO3/*seeipcs*/2023/5/820第二十頁,共七十三頁。例:刪除消息隊列#include<stdio.h>#include<sys/ipc.h>#include<sys/types.h>intmain(){ key_tkey; intid; key=ftok(".",1); id=msgget(key+1,IPC_CREAT|0666); printf("id=%d\n",id); msgctl(id,IPC_RMID,NULL); sytem(“ipcs”);}2023/5/8人民郵電出版社出版楊宗德編著21第二十一頁,共七十三頁。發(fā)送信息到消息隊列externintmsgsnd(int__msqid,__constvoid*__msgp,size_t__msgsz,int__msgflg)第一個參數(shù)msqid為指定的消息隊列標識符(由msgget生成的消息隊列標識符),即將消息添加到那個消息隊列中。第二個參數(shù)msgp為指向的用戶定義緩沖區(qū)。第三個參數(shù)為接收信息的大小,其數(shù)據(jù)類型為size_t,即unsignedint類型。其大小為0到系統(tǒng)對消息隊列的限定值。第四個參數(shù)用來指定在達到系統(tǒng)為消息隊列鎖定的界限(如達到字數(shù)限制)時應采取的操作。2023/5/822第二十二頁,共七十三頁。發(fā)送信息到消息隊列(2)

第二個參數(shù)其定義如下://comefrom/usr/include/linux/msg.h/*messagebufferformsgsndandmsgrevcalls*/structmsgbuf{longmtype;/*typeofmessage*/charmtext[1];/*messagetext*/}mtype是一個正整數(shù),由產(chǎn)生消息的進程生成,用于表示消息的類型,因此,接收進程可以用來進行消息選擇(消息隊列在存儲信息時是按發(fā)送的先后順序放置的)。mtext是文本內(nèi)容,即消息內(nèi)容,此處大小為1,顯然不夠用,在使用時自己重新定義此結(jié)構。2023/5/823第二十三頁,共七十三頁。發(fā)送信息到消息隊列(3)第四個參數(shù)用來指定在達到系統(tǒng)為消息隊列鎖定的界限(如達到字數(shù)限制)時應采取的操作。:如果設置為IPC_NOWAIT,如果需要等待,則不發(fā)送消息并且調(diào)用進程立即返回錯誤信息EAGAIN.如果設置為0,則忽略標志位。成功調(diào)用后,此函數(shù)將返回0,否則返回-1,同時將對消息隊列msqid數(shù)據(jù)結(jié)構的成員執(zhí)行下列操作:msg_qnum以1為增量遞增。msg_lspid設置為調(diào)用進程的進程ID。msg_stime設置為當前時間。2023/5/824第二十四頁,共七十三頁。從消息隊列接收信息externintmsgrev(int__msqid,void*__msgp,size_t__msgsz,longint__msgtyp,int__msgflg);此函數(shù)從與msqid指定的消息隊列標識符相關聯(lián)的隊列中讀取消息,并將其放置到msgp指向的結(jié)構中。第一個參數(shù)為讀的對象,即從哪個消息隊列獲得消息。第二個參數(shù)為一個臨時消息數(shù)據(jù)結(jié)構,用來保存讀取的信息。其定義與發(fā)送信息的第二個參數(shù)相同。第三個參數(shù)msgsz指定mtext的大?。ㄒ宰止?jié)為單位)。如果收到的消息大于msgsz,并且msgflg&MSG_NOERROR為真,則將該消息截至msgsz字節(jié),消息的截斷部分將丟失,并且不向調(diào)用進程提供截斷的提示2023/5/825第二十五頁,共七十三頁。從消息隊列接收信息(2)

第四個參數(shù)msgtyp指定請求的消息類型:msgtyp=0收到隊列中的第一條消息,任意類型。msgtyp>0收到第一條msgtyp類型的消息。msgtyp<0收到第一條最低類型(小于或等于msgtyp的絕對值)的消息。第五個參數(shù)msgflg指定所需類型消息不在隊列上時將要采取的操作。0,表示忽略;IPC_NOWAIT,如果消息隊列為空,則返回一個ENOMSG,并將控制權交回調(diào)用函數(shù)的進程。2023/5/826第二十六頁,共七十三頁。消息隊列應用實例#include<stdio.h>#include<stdlib.h>#include<string.h>#include<sys/types.h>#include<sys/msg.h>#include<sys/ipc.h>#include<unistd.h>structmsgmbuf{ longmsg_type; charmsg_text[512];};2023/5/827第二十七頁,共七十三頁。消息隊列應用實例intmain(){ intqid; key_tkey; intlen; structmsgmbufmsg; if((key=ftok(".",'a'))==-1) { perror("ftok"); exit(EXIT_FAILURE); } if((qid=msgget(key,IPC_CREAT|0666))==-1) { perror("msgget"); exit(EXIT_FAILURE); }2023/5/828第二十八頁,共七十三頁。消息隊列應用實例 printf("IDofthequeueis:%d\n",qid); puts("pleaseinputthemssage:"); if((fgets((&msg)->msg_text,512,stdin))==NULL) { puts("nomessage!"); exit(EXIT_FAILURE); } msg.msg_type=getpid(); len=strlen(msg.msg_text); if((msgsnd(qid,&msg,len,0))<0) { perror("msgsnd"); exit(EXIT_FAILURE); }

2023/5/829第二十九頁,共七十三頁。消息隊列應用實例 if((msgrcv(qid,&msg,512,0,0))<0) { perror("msgrcv"); exit(EXIT_FAILURE); } printf("themessageis:%s\n",(&msg)->msg_text); if((msgctl(qid,IPC_RMID,NULL))<0) { perror("msgctl"); exit(EXIT_FAILURE); } exit(0);}2023/5/830第三十頁,共七十三頁。第5章SystemV進程間通信12SystemV

IPC基礎

消息隊列

3信號量通信機制

4共享內(nèi)存

第三十一頁,共七十三頁。信號量基本概念信號量是操作系統(tǒng)中解決進程或線程同步與互斥的最重要機制之一。Linux內(nèi)核提供SystemV的信號量機制,用于實現(xiàn)進程之間通信。信號量常用系統(tǒng)調(diào)用見下表函數(shù)功能sem_init初始化一個信號量sem_wait阻塞線程sem_post增加信號量的值sem_destory釋放信號量2023/5/832第三十二頁,共七十三頁。信號量集合屬性2023/5/833第三十三頁,共七十三頁。信號量結(jié)構//comefrom/usr/src/kernels/’uname-r’/include/linux/sem.h/*Onesemaphorestructureforeachsemaphoreinthesystem.*/structsem{ intsemval;/*currentvalue*/ intsempid;/*pidoflastoperation*/};2023/5/834第三十四頁,共七十三頁。信號量通信機制概念圖2023/5/835第三十五頁,共七十三頁。創(chuàng)建信號量集合externintsemget(key_t__key,int__nsems,int__semflg);第一個參數(shù)為key_t類型的key值,一般由ftok函數(shù)產(chǎn)生。第二個參數(shù)__nsems為創(chuàng)建的信號量個數(shù),各信號量以數(shù)組的方式存儲。這個數(shù)組用于初始化數(shù)組對象。第三個參數(shù)__semflg用來標識信號量集合的權限。如0770,為文件的訪問權限類型。此外,還可以附加以下參數(shù)值。這些值可以與基本權限以或的方式一起使用。//comefrom/usr/include/bit/ipc.h/*resourcegetrequestflags*/#defineIPC_CREAT00001000/*createifkeyisnonexistent*/#defineIPC_EXCL00002000/*failifkeyexists*/#defineIPC_NOWAIT00004000/*returnerroronwait*/2023/5/836第三十六頁,共七十三頁??刂菩盘柫考稀⑿盘柫縠xternintsemctl(int__semid,int__semnum,int__cmd,……)該函數(shù)最多可有四個參數(shù)(有可能只有三個參數(shù))。第一個參數(shù)__semid為要操作的信號量集合標識符,該值一般由semget函數(shù)返回。第二個參數(shù)為集合中信號量的編號。如果標識某個信號量,此值為該信號量的下標(從0到n-1);如果標識整個信號量集合,則設置為0。第三個參數(shù)為要執(zhí)行的操作,如果是對整個信號量集合,這些操作在/usr/include/linux/ipc.h文件中定義。其操作包括IPC_RMID、IPC_SET、IPC_STAT和IPC_INFO,具體含義同msgctl的相關操作。2023/5/837第三十七頁,共七十三頁。2023/5/838第三十八頁,共七十三頁。信號量操作externintsemop(int__semid,structsembuf*__sops,size_t__nsops);此函數(shù)第一個參數(shù)為要操作的信號量集合標識符,該值一般由semget函數(shù)返回。第二個參數(shù)為structsembuf結(jié)構的變量,其定義如下://comefrom/usr/include/linux/sem.h/*semopsystemcallstakesanarrayofthese.*/structsembuf{unsignedshortsem_num;/*semaphoreindexinarray*/shortsem_op;/*semaphoreoperation*/shortsem_flg;/*operationflags*/}2023/5/839第三十九頁,共七十三頁。信號量操作(2)

此結(jié)構體有三個成員變量。1)sem_num為操作的信號量編號。2)sem_op為作用于信號量的操作:該值如果為正整數(shù)表示增加信號量的值,如果為負整數(shù)表示減小信號量的值,如果為0表示對信號量的當前值進行是否為0的測試。3)sem_flg為操作標識。2023/5/840第四十頁,共七十三頁。使用信號量實現(xiàn)生產(chǎn)消費問題生產(chǎn)消費問題是一個經(jīng)典的數(shù)學問題,要求生產(chǎn)者-消費者在固定的倉庫空間條件下,生產(chǎn)者每生產(chǎn)一個產(chǎn)品將占用一個倉庫空間,生產(chǎn)者生產(chǎn)的產(chǎn)品庫存不能越過倉庫的存儲量,消費者每消費一個產(chǎn)品將增加一個倉庫空間,消費者在倉庫產(chǎn)品為0時不能再消費。本例中采用信號量來解決這個問題,為了便于理解,本例中使用了兩個信號量,一個用來管理消費者(以下為sem_produce),一個用來管理生產(chǎn)者(以下為sem_custom),即sem_produce表示當前倉庫可用空間的數(shù)量,sem_custom用來表示當前倉庫中產(chǎn)品的數(shù)量。對于生產(chǎn)者來說,其需要申請的資源為倉庫中的剩余空間,因此,生產(chǎn)者在生產(chǎn)一個產(chǎn)品前,申請sem_produce信號量,當此信號量的值大于0,即有可用空間,將生產(chǎn)產(chǎn)品,并將sem_produce的值減去1(因為占用了一個空間);同時,當其生產(chǎn)一個產(chǎn)品后,當前倉庫的產(chǎn)品數(shù)量增加1,需要將sem_custom信號量自動加1。對于消費者來說,其需要申請的資源為倉庫中的產(chǎn)品,因此,消費者在消費一個產(chǎn)品前,將申請sem_custom信號量,當此信號量的值大于0時,即有可用產(chǎn)品,將消費一個產(chǎn)品,并將sem_custom信號量的值減去(因為消費了一個產(chǎn)品),同時,當消費一個產(chǎn)品,當前倉庫的剩余空間增加1,需要將sem_produce信號量自動加1。2023/5/841第四十一頁,共七十三頁。第5章SystemV進程間通信12SystemV

IPC基礎

消息隊列

3信號量通信機制

4共享內(nèi)存

第四十二頁,共七十三頁。共享內(nèi)存的基本概念共享內(nèi)存允許兩個或多個進程共享一個給定的存儲區(qū),這一段存儲區(qū)可以被兩個或兩個以上的進程映射至自身的地址空間中,數(shù)據(jù)不需要在進程間復制,所以這是最快的一種IPC。使用共享內(nèi)存時,多個進程之間對一給定的存儲區(qū)需進行同步訪問。即若一個進程正在將數(shù)據(jù)放入共享存儲區(qū),則在它做完這一操作之前,其他進程不應當去讀取這些數(shù)據(jù)。通常,信號量被用來實現(xiàn)對共享存儲的訪問。2023/5/843第四十三頁,共七十三頁。共享內(nèi)存屬性2023/5/844第四十四頁,共七十三頁。共享內(nèi)存IPC原理2023/5/845第四十五頁,共七十三頁。共享內(nèi)存與管道對比2023/5/846第四十六頁,共七十三頁。共享內(nèi)存的常用函數(shù)函數(shù)功能mmap建立共享內(nèi)存映射munmap解除共享內(nèi)存映射shmget獲取共享內(nèi)存區(qū)域的IDshmctl共享內(nèi)存控制shmat映射共享內(nèi)存對象shmdt分離共享內(nèi)存對象2023/5/847第四十七頁,共七十三頁。內(nèi)存映射函數(shù)mmap將某個文件的指定內(nèi)容映射到內(nèi)存空間中,該函數(shù)聲明如下:#include<sys/mman.h>void*mmap(void*start,size_tlength,intprot,intflags,intfd,off_toffset);此函數(shù)將在進程的虛擬地址空間(起始為start,長度為length字節(jié))和與文件描述符fd關聯(lián)的文件(偏移量為offset,長度為length)之間建立映射。參數(shù)start一般情況下設置為NULL,由系統(tǒng)分配。第三個參數(shù)prot描述映射的內(nèi)存權限,該參數(shù)是以下選項的組合:PORT_READ允許讀該內(nèi)存PORT_WRITE允許寫該內(nèi)存PORT_EXEC允許執(zhí)行該內(nèi)存段PORT_NONE該內(nèi)存段不能被訪問2023/5/848第四十八頁,共七十三頁。內(nèi)存映射參數(shù)flags控制程序?qū)υ搩?nèi)存段的改變所造成的影響,常用選項如下:MAP_PRIVATE:內(nèi)存段是私有的,對他的修改只在此局部范圍內(nèi)有效,其他進程不可見。MAP_SHARED:共享映射,某進程對該段內(nèi)存空間的更新對其他進程來說是可見的,但該文件的內(nèi)容并不會立即更新,要更新文件內(nèi)容,需要調(diào)用msync和munmap函數(shù)。2023/5/849第四十九頁,共七十三頁。例:內(nèi)存映射的使用#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<fcntl.h>#include<sys/mman.h>typedefstruct{ charname[4]; intage;}people;main(intargc,char*argv[]){ pid_tresult; inti; people*p_map; chartemp;2023/5/850第五十頁,共七十三頁。例:內(nèi)存映射的使用 p_map=(people*)mmap(NULL,sizeof(people)*10,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0); result=fork(); if(result<0) { perror("fork"); exit(EXIT_FAILURE); } elseif(result==0) { sleep(2); for(i=0;i<5;i++) printf("readbychild:No.%d'sageis:%d\n",i+1,(*(p_map+i)).age);2023/5/851第五十一頁,共七十三頁。例:內(nèi)存映射的使用 (*p_map).age=110; munmap(p_map,sizeof(people)*10); exit(0); } else { temp='a'; for(i=0;i<5;i++) { temp+=1; memcpy((p_map+i)->name,&temp,2); ((p_map+i)->age=20+i); }2023/5/852第五十二頁,共七十三頁。例:內(nèi)存映射的使用 sleep(5); printf("readbyparent:thesumofageis:%d\n",(*p_map).age); printf("unmaping>>>>\n"); munmap(p_map,sizeof(people)*10); printf("unmapsuccessful!\n"); }}2023/5/853第五十三頁,共七十三頁。創(chuàng)建共享內(nèi)存externintshmget(key_t__key,size_t__size,int__shmflg);第一個參數(shù)為key_t類型的key值,一般由ftok函數(shù)產(chǎn)生。第二個參數(shù)size為欲創(chuàng)建的共享內(nèi)存段大?。▎挝粸樽止?jié))。第三個參數(shù)shmflg用來標識共享內(nèi)存段的創(chuàng)建標識。包括//comefrom/usr/include/linu/ipc.h#defineIPC_CREAT01000/*Createkeyifkeydoesnotexist.*/#defineIPC_EXCL020000/*Failifkeyexists.*/#defineIPC_NOWAIT04000/*Returnerroronwait.*/2023/5/854第五十四頁,共七十三頁。創(chuàng)建共享內(nèi)存另外,在/usr/include/linux/shm.h文件還定義了另外兩個選項://comefrom/usr/include/linux/shm.h/*permissionflagforshmget*/#defineSHM_R0400/*orS_IRUGOfrom<linux/stat.h>*/#defineSHM_W0200/*orS_IWUGOfrom<linux/stat.h>*/2023/5/855第五十五頁,共七十三頁。共享內(nèi)存控制externintshmctl(int__shmid,int__cmd,structshmid_ds*__buf);第一個參數(shù)為要操作的共享內(nèi)存標識符,該值一般由shmget函數(shù)返回。第二個參數(shù)為要執(zhí)行的操作,這些操作在/usr/include/linux/ipc.h文件中定義。其操作包括IPC_RMID、IPC_SET、IPC_STAT和IPC_INFO,具體含義同msgctl的相關操作。如果是超級用戶,還可以執(zhí)行以下兩個命令://comefrom/usr/include/sys/shm.h/*superusershmctlcommands*/#defineSHM_LOCK11#defineSHM_UNLOCK12第三個參數(shù)為structshmid_ds結(jié)構的臨時共享內(nèi)存變量信息,此內(nèi)容根據(jù)第二個參數(shù)的不一樣而改變。2023/5/856第五十六頁,共七十三頁。映射共享內(nèi)存對象進程使用共享內(nèi)存前,需要將該共享內(nèi)存與當前進程建立聯(lián)系,即將該共享內(nèi)存使用shmat函數(shù)映射到當前進程。其函數(shù)聲明如下:#include<sys/shm.h>externvoid*shmat(int__shmid,__constvoid*__shmaddr,int__shmflag);如果執(zhí)行成功,將返回共享內(nèi)存段首地址。第一個參數(shù)__shmid為要操作的共享內(nèi)存標識符,該值一般由shmget函數(shù)返回。第二個參數(shù)shmaddr指定共享內(nèi)存的映射地址。如果該值為非零,則將用此值作為映射共享內(nèi)存的地址,如果此值為0,則由系統(tǒng)來選擇映射的地址。一般都將此值設置為0。2023/5/857第五十七頁,共七十三頁。映射共享內(nèi)存對象#include<sys/shm.h>externvoid*shmat(int__shmid,__constvoid*__shmaddr,int__shmflag);第三個參數(shù)用來指定共享內(nèi)存短的訪問權限和映射條件。//comefrom/usr/include/linux/shm.h/*modeforattach*/#defineSHM_RDNOLY010000/*read-onlyaccess*/#defineSHM_RND020000/*roundattachattachaddresstoSHMLBAbounary*/#defineSHM_REMAP040000/*take-overregiononattach*/#defineSHM_EXEC0100000/*executionaccess*/2023/5/858第五十八頁,共七十三頁。分離共享內(nèi)存對象在共享內(nèi)存使用完畢后,需要使用shmdt函數(shù)將其與當前進程分離。其函數(shù)聲明如下://comefrom/usr/include/sys/shm.hexternintshmdt(__constvoid*__shmaddr);其參數(shù)即為與當前進程分離的共享內(nèi)存標志ID。2023/5/859第五十九頁,共七十三頁。例一#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<sys/ipc.h>#include<sys/shm.h>#include<sys/types.h>typedefstruct{ charname[4]; intage;}people;main(){ intshm_id,i; key_tkey; people*p_map; char*name="/dev/shm/myshm2";2023/5/860第六十頁,共七十三頁。例一 key=ftok(name,0); shm_id=shmget(key,4096,IPC_CREAT); if(shm_id==-1) { perror("shmget"); exit(EXIT_FAILURE); } p_map=(people*)shmat(shm_id,NULL,0); for(i=0;i<10;i++) { printf("name:%s\t",(p_map+i)->name); printf("age:%d\n",(p_map+i)->age); } if(shmdt(p_map)==-1) perror("shmdt");}2023/5/861第六十一頁,共七十三頁。例一#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<sys/ipc.h>#include<sys/shm.h>#include<sys/types.h>typedefstruct{ charname[4]; intage;}people;main(){ intshm_id,i; key_tkey; people*p_map; char*name="/dev/shm/myshm2";2023/5/862第六十二頁,共七十三頁。例一 key=ftok(name,0); if(key==-1) { perror("ftok"); exit(EXIT_FAILURE); } shm_id=shmget(key,4096,IPC_CREAT|0666); if(shm_id==-1) { perror("shmget"); exit(EXIT_FAILURE); } p_map=shmat(shm_id,0,0);//(people*)shmat(shm_id,0,0); temp='a'; for(i=0;i<10;i++) { temp+=1; memcpy((p_map+i)->name,&temp,1); (p_map+i)->age=20+i; } if(shmdt(p_map)==-1) perror("shmdt");}2023/5/8人民郵電出版社出版楊宗德編著63第六十三頁,共七十三頁。例二#include<stdio.h>#include<stdlib.h>#include<sys/ipc.h>#include<sys/shm.h>#include<sys/types.h>#include<time.h>#include<unistd.h>typedefstruct{ charstr1[50]; charstr2[50]; intno1,no2;}str;2023/5/864第六十四頁,共七十三頁。例二main(intargc,char*agv[]){ intshm_id,i; key_tkey; str*p_map; time_ttimep; structtm*p; char*name="/dev/shm/myshm2"; key=ftok(name,0); shm_id=shmget(key,4096,IPC_CREAT|0666); if(shm_id==-1) { perror("shmget"); exit(EXIT_FAILURE); } p_map=(str*)shmat(shm_id,NULL,0); p_map->no1=0; p_map->no2=0; printf("ThisisA.\n"); fgets(p_map->str2,sizeof(p_map->str2),stdin); p_map->no1=1;2023/5/865第六十五頁,共七十三頁。例二 while(1) { if(p_map->no2==1) { time(&timep); gmtime(&timep); p=localtime(&timep); printf("A:%s%d:%d:%d\n",p_map->str1,p->tm_hour,p->tm_min,p->tm_sec);

溫馨提示

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

評論

0/150

提交評論