日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

IPC之IPC_PRIVATE与ftok比较

發(fā)布時(shí)間:2025/3/15 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 IPC之IPC_PRIVATE与ftok比较 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在Linux中,可以使用IPC對(duì)象來(lái)進(jìn)行進(jìn)程間通信。IPC對(duì)象存在于內(nèi)核中,多進(jìn)程可以操作同一個(gè)IPC對(duì)象。

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

方法一:通過(guò)ftok函數(shù),產(chǎn)生相同的鍵值。

假設(shè),進(jìn)程p1創(chuàng)建了共享內(nèi)存。可以在創(chuàng)建時(shí),調(diào)用ftok函數(shù),得到一個(gè)key值,調(diào)用shmget函數(shù),該函數(shù)會(huì)返回所創(chuàng)建共享內(nèi)存的編號(hào),并將key和編號(hào)關(guān)聯(lián)起來(lái)。若進(jìn)程p2想利用這個(gè)共享內(nèi)存和p1進(jìn)程通信,也可以調(diào)用ftok函數(shù),得到同樣的key,再根據(jù)key值,調(diào)用shmget函數(shù),就可以獲得該共享內(nèi)存的編號(hào)。該過(guò)程可以通過(guò)下面的圖來(lái)表達(dá)。

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

第一個(gè)參數(shù)pathname,是一個(gè)存在的文件或目錄名;

第二個(gè)參數(shù)proj_id,是非0整數(shù)(一般用i節(jié)點(diǎn)號(hào))

該函數(shù)會(huì)返回一個(gè)key值,先運(yùn)行的進(jìn)程根據(jù)key來(lái)創(chuàng)建對(duì)象,后運(yùn)行的進(jìn)程根據(jù)key來(lái)打開(kāi)對(duì)象。示意圖如下:

使用 ftok創(chuàng)建共享內(nèi)存,毫無(wú)關(guān)系的進(jìn)程,可以通過(guò)得到同樣的key,來(lái)操作同一個(gè)共享內(nèi)存,對(duì)共享內(nèi)存進(jìn)行讀寫(xiě)時(shí),需要利用信號(hào)量進(jìn)行同步或互斥。

方法二:使用IPC_PRIVATE對(duì)象

使用IPC_PRIVATE創(chuàng)建的IPC對(duì)象, key值屬性為0,和IPC對(duì)象的編號(hào)就沒(méi)有了對(duì)應(yīng)關(guān)系。這樣毫無(wú)關(guān)系的進(jìn)程,就不能通過(guò)key值來(lái)得到IPC對(duì)象的編號(hào)(因?yàn)檫@種方式創(chuàng)建的IPC對(duì)象的key值都是0)。因此,這種方式產(chǎn)生的IPC對(duì)象,和無(wú)名管道類(lèi)似,不能用于毫無(wú)關(guān)系的進(jìn)程間通信。但也不是一點(diǎn)用處都沒(méi)有,仍然可以用于有親緣關(guān)系的進(jìn)程間通信。示例程序如下:

#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, "hello\n");
????????????????????????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("%s\n", (char *)p);
????????????????????????if (shmctl(shmid, IPC_RMID, NULL) == -1)
????????????????????????{
????????????????????????????????perror("RM");
????????????????????????????????exit(-1);
????????????????????????}
????????????????}
????????????????return 0;
????????}

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

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

3.使用IPC_PRIVATE方式注意

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

?因?yàn)橥ㄟ^(guò)IPC_PRIVATE這個(gè)key獲得的id不一樣,其他通過(guò)ftok獲得的key來(lái)shmget獲得的id在程序每次運(yùn)行中是一樣的。ftok參數(shù)一樣的話每次程序運(yùn)行中返回值都一樣。

4.ipcs -m status 欄

nattch?是連接數(shù)目,dest?表示共享內(nèi)存段已經(jīng)被刪除,但是仍然有程序在連接著它。

“status欄中列出當(dāng)前共享內(nèi)存的狀態(tài),當(dāng)該段內(nèi)存的mode字段設(shè)置了SHM_DEST位時(shí)就會(huì)顯示"dest"字樣,
當(dāng)用戶(hù)調(diào)用shmctl的IPC_RMID時(shí),內(nèi)核首先看有多少個(gè)進(jìn)程還和這段內(nèi)存關(guān)聯(lián)著,如果關(guān)聯(lián)數(shù)為0,就會(huì)銷(xiāo)毀(釋放)這段內(nèi)存,否則就設(shè)置這段內(nèi)存的mode位SHM_DEST,”


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

? ? ? ? ?并且共享內(nèi)存被置dest后可以成功調(diào)用shmctl(shmID,IPC_RMID,NULL)或者shell 命令 ipcrm -m ,但是當(dāng)關(guān)聯(lián)數(shù)為0,共享內(nèi)存被刪除后,再調(diào)用 ? 這些命令就會(huì)出錯(cuò)。

shmctl(shmID,IPC_RMID,NULL)可以被每個(gè)使用共享內(nèi)存的進(jìn)程內(nèi)調(diào)用多次,但至少由一個(gè)進(jìn)程來(lái)調(diào)用一次,否則不能刪除共享的內(nèi)存,但是shmdt只能對(duì)應(yīng)相應(yīng)的shmget調(diào)用一次。

3.4.5部分的代碼如下:

[cpp]?view plaincopy print?
  • //shmem.cpp???
  • //g++?shmem.cpp?-lpthread?-o?shmem??
  • #include?<sys/types.h>??
  • #include?<sys/ipc.h>??
  • #include?<sys/shm.h>??
  • #include<unistd.h>??
  • #include<iostream>??
  • #include<cstdlib>??
  • #include<pthread.h>??
  • #include?<string.h>??
  • #include?<signal.h>??
  • #include?<errno.h>??
  • #include?<stdio.h>??
  • 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"<<std::endl;??
  • ????????strcpy(addr,"Hello");??
  • ????}??
  • ????std::cout<<"thread?:threadID="<<pthread_self()<<",pid="<<getpid()<<",parent?pid?="<<getppid()<<std::endl;??
  • ??????
  • ????????/*if(-1==shmctl(tmp.shmID,IPC_RMID,NULL)){?
  • ????????????????std::cout<<"remove?shared?memory?error:"<<errno<<std::endl;//error<<std::endl;?
  • ????????????????perror(strerror(errno));?
  • ????????}else{?
  • ????????????????std::cout<<"remove?shared?memory?ok"<<std::endl;?
  • ????????}*/??
  • ??
  • }??
  • ??
  • int?main(int?argc,char**?argv){??
  • ????pthread_t?thid;??
  • ????pthread_attr_t?attr;??
  • ????pthread_attr_init(&attr);??
  • ????pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);??
  • ??
  • ????argv_t?arg;??
  • ????pid_t?pid;??
  • ????int?len=5;??
  • ????int?shmID=shmget(IPC_PRIVATE,len,IPC_CREAT|0600);???
  • ????if((pid=fork())==0){??
  • ????????sleep(5);??
  • ????????????char?*?addr=(char?*)shmat(shmID,0,SHM_RDONLY);??
  • ????????for(int?i=0;i<5;i++){??
  • ????????????std::cout<<"sub?process?pid="<<getpid()<<",parent?pid"<<getppid()<<std::endl;??
  • ????????????std::cout<<"begin?read?sharedMem"<<std::endl;??
  • ????????????std::cout<<"s1"<<std::endl;??
  • ????????????std::cout<<"s2"<<std::endl;??
  • ????????????//if(i<=2)??
  • ????????????????system("ipcs?-m");??
  • ????????????std::cout<<"-----"<<i<<std::endl;??
  • ??????????????
  • ????????????if(i==2){??
  • ???????????????char?*cmd=new?char[50];??
  • ???????????????sprintf(cmd,"ipcrm?-m?%d\0",shmID);??
  • ???????????????system(cmd);??
  • ????????????}??
  • ????????????std::cout<<addr<<std::endl;??
  • ????????????//shmdt(addr);??
  • ????????????sleep(3);??
  • ????????}//for??
  • ????????std::cout<<"reveive?end"<<std::endl;??
  • ????????if(-1==shmctl(shmID,IPC_RMID,NULL)){??
  • ????????????std::cout<<"remove?shared?memory?error:"<<errno<<std::endl;//error<<std::endl;??
  • ????????????perror(strerror(errno));??
  • ????????}else{??
  • ????????????std::cout<<"remove?shared?memory?ok"<<std::endl;??
  • ????????}??
  • ????}else?if(pid>0){??
  • ????????//shmID=shmget(IPC_PRIVATE,len,IPC_CREAT|0600);???
  • ????????std::cout<<"shmID="<<shmID<<std::endl;??
  • ????????arg.shmID=shmID;??
  • ????????std::cout<<"I?am?the?parent?,pid="<<getpid()<<",parent?pid"<<getppid()<<std::endl;??
  • ????????if((pthread_create(&thid,&attr,thread,(void*)&arg))!=0)??
  • ????????????std::cout<<"create?thread?failed"<<std::endl;??
  • ????????else??
  • ????????????std::cout<<"create?thread?successed"<<std::endl;??
  • ????????sleep(10);??
  • ????????pthread_exit(0);//in?main?for?wait??
  • ????}else{??
  • ????????std::cout<<"fork?sub?process?failed"<<std::endl;??
  • ????}??
  • ????return?EXIT_SUCCESS;??
  • }??

  • 部分輸出結(jié)果:


    6.信號(hào)量中IPC_PRIVATE類(lèi)似于共享內(nèi)存中,同樣semget(IPC_PRIVATE,1,0666 | IPC_CREAT)需要在父子進(jìn)程都可見(jiàn)的地方調(diào)用(即在創(chuàng)建子進(jìn)程之前),否則不能實(shí)現(xiàn)內(nèi)存的共享。

    信號(hào)量中的semctl(semID[index],0,IPC_RMID,sem_union)刪除是立即刪除,不同于共享內(nèi)存

    總結(jié)

    以上是生活随笔為你收集整理的IPC之IPC_PRIVATE与ftok比较的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。