日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當前位置:首頁 > 芯聞號 > 充電吧
[導讀]linux進程通信IPC之IPC_PRIVATE與ftok比較 ? ? ?? 原文地址:http://www.xuebuyuan.com/2130544.html 在linux中,可以

linux進程通信IPC之IPC_PRIVATE與ftok比較 ? ? ?? 原文地址:http://www.xuebuyuan.com/2130544.html

在linux中,可以使用IPC對象來進行進程間通信。IPC對象存在于內核中,多進程可以操作同一個IPC對象。

每個IPC對象都有一個唯一的編號,該編號是由系統(tǒng)分配的。那么不同的進程如何知道這個編號,進而通過它進行通信呢?下面以共享內存為例,進行分析。

方法一:通過ftok函數,產生相同的鍵值。

假設,進程p1創(chuàng)建了共享內存??梢栽趧?chuàng)建時,調用ftok函數,得到一個key值,調用shmget函數,該函數會返回所創(chuàng)建共享內存的編號,并將key和編號關聯起來。若進程p2想利用這個共享內存和p1進程通信,也可以調用ftok函數,得到同樣的key,再根據key值,調用shmget函數,就可以獲得該共享內存的編號。該過程可以通過下面的圖來表達。

ftok函數原型如下:
????????????????#include < sys/types.h>
????????????????#include < sys/ipc.h>
????????????????key_t ftok(const char *pathname, int proj_id);

第一個參數pathname,是一個存在的文件或目錄名;

第二個參數proj_id,是非0整數(一般用i節(jié)點號)

該函數會返回一個key值,先運行的進程根據key來創(chuàng)建對象,后運行的進程根據key來打開對象。示意圖如下:

使用 ftok創(chuàng)建共享內存,毫無關系的進程,可以通過得到同樣的key,來操作同一個共享內存,對共享內存進行讀寫時,需要利用信號量進行同步或互斥。

方法二:使用IPC_PRIVATE對象

使用IPC_PRIVATE創(chuàng)建的IPC對象, key值屬性為0,和IPC對象的編號就沒有了對應關系。這樣毫無關系的進程,就不能通過key值來得到IPC對象的編號(因為這種方式創(chuàng)建的IPC對象的key值都是0)。因此,這種方式產生的IPC對象,和無名管道類似,不能用于毫無關系的進程間通信。但也不是一點用處都沒有,仍然可以用于有親緣關系的進程間通信。示例程序如下:

#include < stdio.h>
????????#include < stdlib.h>
????????#include < errno.h>
????????#include < sys/ipc.h>
????????#include < sys/types.h>
????????#include < sys/shm.h>
????????#include < string.h>
????????#define MAXSIZE 1024
????????int main()
????????{
????????????????int shmid;
????????????????????????char *p = NULL;
????????????????????????pid_t pid;
????????????????#if 0
????????????????????????key_t key;
????????????????????????if ((key = ftok(".", 'a')) == -1)
????????????????????????{
????????????????????????????????perror("ftok");
????????????????????????????????exit(-1);
????????????????????????}
????????????????#endif
????????????????if ((shmid = shmget(IPC_PRIVATE, MAXSIZE, 0666)) == -1)
????????????????{
????????????????????????perror("shmget");
????????????????????????exit(-1);
????????????????}
????????????????if ((pid = fork()) == -1)
????????????????{
????????????????????????perror("fork");
????????????????????????exit(-1);
????????????????}
????????????????if (pid == 0)
????????????????{
????????????????????????if ((p = shmat(shmid, NULL, 0)) == (void *)-1)
????????????????????????{
????????????????????????????????perror("shmat");
????????????????????????????????exit(-1);
????????????????????????}
????????????????????????????????strcpy(p, "hellon");
????????????????????????system("ipcs -m");
????????????????????????????????if (shmdt(p) == -1)
????????????????????????????????{
????????????????????????????????perror("shmdt");
????????????????????????????????exit(-1);
????????????????????????}
????????????????????????system("ipcs -m");
????????????????}
????????????????else
????????????????{
????????????????????????getchar();
????????????????????????????????if ((p = shmat(shmid, NULL, 0)) == (void *)-1)
????????????????????????{
????????????????????????????????perror("shmat");
????????????????????????????????exit(-1);
????????????????????????}
????????????????????????printf("%sn", (char *)p);
????????????????????????if (shmctl(shmid, IPC_RMID, NULL) == -1)
????????????????????????{
????????????????????????????????perror("RM");
????????????????????????????????exit(-1);
????????????????????????}
????????????????}
????????????????return 0;
????????}

該程序中,父進程使用IPC_PRIVATE方式創(chuàng)建了共享內存,然后fork產生了子進程,由于子進程是復制父進程的方式產生的,因此,子進程也可以操作共享內存。子進程往共享內存里寫了內容后,父進程可以讀到。

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

3.使用IPC_PRIVATE方式注意

(1)int shmID=shmget(IPC_PRIVATE,len,IPC_CREAT|0600);需要在父子進程都可見的地方調用(即在創(chuàng)建子進程之前),否則不能實現內存的共享

?因為通過IPC_PRIVATE這個key獲得的id不一樣,其他通過ftok獲得的key來shmget獲得的id在程序每次運行中是一樣的。ftok參數一樣的話每次程序運行中返回值都一樣。

4.ipcs -m status 欄

nattch?是連接數目,dest?表示共享內存段已經被刪除,但是仍然有程序在連接著它。

“status欄中列出當前共享內存的狀態(tài),當該段內存的mode字段設置了SHM_DEST位時就會顯示"dest"字樣,
當用戶調用shmctl的IPC_RMID時,內核首先看有多少個進程還和這段內存關聯著,如果關聯數為0,就會銷毀(釋放)這段內存,否則就設置這段內存的mode位SHM_DEST,”

5.調用shmctl(shmID,IPC_RMID,NULL)或者shell 命令 ipcrm -m 不是會立刻刪除共享內存,是向上面那樣先置dest,并且此時共享內存中的數據仍然可以使用(即不影響正在使用共享內存的部分,但是若置為dest后再通過shmget通過同樣的key來獲取shmID時,shmID和刪除前就不一樣了),然后等待關聯數為0才刪除。shmdt是用來釋放共享內存鏈接的,進程退出會調用shmdt。

? ? ? ? ?并且共享內存被置dest后可以成功調用shmctl(shmID,IPC_RMID,NULL)或者shell 命令 ipcrm -m ,但是當關聯數為0,共享內存被刪除后,再調用 ? 這些命令就會出錯。

shmctl(shmID,IPC_RMID,NULL)可以被每個使用共享內存的進程內調用多次,但至少由一個進程來調用一次,否則不能刪除共享的內存,但是shmdt只能對應相應的shmget調用一次。

3.4.5部分的代碼如下:

//shmem.cpp 
//g++ shmem.cpp -lpthread -o shmem
#include 
#include 
#include 
#include
#include
#include
#include
#include 
#include 
#include 
#include 
struct argv_t{
	int shmID;
};
void * thread(void * argv){
	argv_t tmp=*(argv_t*)argv;
	char * addr=(char*)shmat(tmp.shmID,0,0);
	for(int i=0;i<5;i++){
		//sleep(2);
		std::cout<<"thread sending"<