Linux共享内存编程实例

共享内存是LUNIX 系统中最底层的通信机制,也是最快速的通信机制。共享内存通过两个或多个进程共享同一块内存区域来实现进程间的通信。通常是由一个进程创建一块共享内存区域,然后多个进程可以对其进行访问,一个进程将要传出的数据存放到共享内存中,另一个或多个进程则直接从共享内存中读取数据。因此这种通信方式是最高效的进程间通信方式。但实际的问题在于,当两个或多个进程使用共享内存进行通信时,同步问题的解决显得尤为重要,否则就会造成因不同进程同时读写一块共享内存中的数据而发生混乱。在通常的情况下,通过使用信号量来实现进程的同步。

[cpp]view plaincopy

    /*共享内存允许两个或多个进程进程共享同一块内存(这块内存会映射到各个进程自己独立的地址空间)从而使得这些进程可以相互通信。在GNU/Linux中所有的进程都有唯一的虚拟地址空间,而共享内存应用编程接口API允许一个进程使用公共内存区段。但是对内存的共享访问其复杂度也相应增加。共享内存的优点是简易性。使用消息队列时,一个进程要向队列中写入消息,这要引起从用户地址空间向内核地址空间的一次复制,同样一个进程进行消息读取时也要进行一次复制。共享内存的优点是完全省去了这些操作。共享内存会映射到进程的虚拟地址空间,进程对其可以直接访问,避免了数据的复制过程。因此,共享内存是GNU/Linux现在可用的最快速的IPC机制。进程退出时会自动和已经挂接的共享内存区段分离,但是仍建议当进程不再使用共享区段时调用shmdt来卸载区段。注意,当一个进程分支出父进程和子进程时,父进程先前创建的所有共享内存区段都会被子进程继承。如果区段已经做了删除标记(在前面以IPC——RMID指令调用shmctl),而当前挂接数已经变为0,这个区段就会被移除。*//*shmget()创建一个新的共享内存区段取得一个共享内存区段的描述符shmctl()取得一个共享内存区段的信息为一个共享内存区段设置特定的信息移除一个共享内存区段shmat()挂接一个共享内存区段shmdt()于一个共享内存区段的分离*///创建一个共享内存区段,并显示其相关信息,然后删除该内存共享区#include<stdio.h>#include<unistd.h>//getpagesize()#include<sys/ipc.h>#include<sys/shm.h>#defineMY_SHM_ID67483intmain(){//获得系统中页面的大小printf("pagesize=%d/n",getpagesize());//创建一个共享内存区段intshmid,ret;shmid=shmget(MY_SHM_ID,4096,0666|IPC_CREAT);//创建了一个4KB大小共享内存区段。指定的大小必须是当前系统架构//中页面大小的整数倍if(shmid>0)printf("Createasharedmemorysegment%d/n",shmid);//获得一个内存区段的信息structshmid_dsshmds;//shmid=shmget(MY_SHM_ID,0,0);//示例怎样获得一个共享内存的标识符ret=shmctl(shmid,IPC_STAT,&shmds);if(ret==0){printf("Sizeofmemorysegmentis%d/n",shmds.shm_segsz);printf("Numbreofattaches%d/n",(int)shmds.shm_nattch);}else{printf("shmctl()callfailed/n");}//删除该共享内存区ret=shmctl(shmid,IPC_RMID,0);if(ret==0)printf("Sharedmemoryremoved/n");elseprintf("Sharedmemoryremovefailed/n");return0;}//共享内存区段的挂载,脱离和使用//理解共享内存区段就是一块大内存#include<stdio.h>#include<sys/shm.h>#include<sys/ipc.h>#include<errno.h>#defineMY_SHM_ID67483intmain(){//共享内存区段的挂载和脱离intshmid,ret;void*mem;shmid=shmget(MY_SHM_ID,0,0);if(shmid>=0){mem=shmat(shmid,(constvoid*)0,0);//shmat()返回进程地址空间中指向区段的指针if((int)mem!=-1){printf("Sharedmemorywasattachedinouraddressspaceat%p/n",mem);//向共享区段内存写入数据strcpy((char*)mem,"Thisisateststring./n");printf("%s/n",(char*)mem);//脱离共享内存区段ret=shmdt(mem);if(ret==0)printf("Successfullydetachedmemory/n");elseprintf("Memorydetachedfailed%d/n",errno);}elseprintf("shmat()failed/n");}elseprintf("sharedmemorysegmentnotfound/n");return0;}/*内存共享区段与旗语和消息队列不同,一个区段可以被锁定。被锁定的区段不允许被交换出内存。这样做的优势在于,与其把内存区段交换到文件系统,在某个应用程序调用时再交换回内存,不如让它一直处于内存中,且对多个应用程序可见。从提升性能的角度来看,很重要的。*/intshmid;//…shmid=shmget(MY_SHM_ID,0,0);ret=shmctl(shmid,SHM_LOCK,0);if(ret==0)printf("Locked!/n");/////////////////////////////////////////////////////////////////////////*使用旗语协调共享内存的例子使用和编译命令gcc-Walltest.c-otest./testcreate./testusea&./testuseb&./testread&./testremove*/#include<stdio.h>#include<sys/shm.h>#include<sys/ipc.h>#include<sys/sem.h>#include<string.h>#include<stdlib.h>#include<unistd.h>#defineMY_SHM_ID34325#defineMY_SEM_ID23234#defineMAX_STRING200typedefstruct{intsemID;intcounter;charstring[MAX_STRING+1];}MY_BLOCK_T;intmain(intargc,char**argv){intshmid,ret,i;MY_BLOCK_T*block;structsembufsb;charuser;//makesurethereisacommandif(argc>=2){//createthesharedmemorysegmentandinitit//withthesemaphoreif(!strncmp(argv[1],"create",6)){//createthesharedmemorysegmentandsemaphoreprintf("Creatingthesharedmemory/n");shmid=shmget(MY_SHM_ID,sizeof(MY_BLOCK_T),(IPC_CREAT|0666));block=(MY_BLOCK_T*)shmat(shmid,(constvoid*)0,0);block->counter=0;//createthesemaphoreandinitblock->semID=semget(MY_SEM_ID,1,(IPC_CREAT|0666));sb.sem_num=0;sb.sem_op=1;sb.sem_flg=0;semop(block->semID,&sb,1);//nowdetachthesegmentshmdt((void*)block);printf("Createthesharedmemoryandsemaphoresuccessuflly/n");}elseif(!strncmp(argv[1],"use",3)){/*usethesegment*///mustspecifyalsoalettertowritetothebufferif(argc<3)exit(-1);user=(char)argv[2][0];//grabthesegmentshmid=shmget(MY_SHM_ID,0,0);block=(MY_BLOCK_T*)shmat(shmid,(constvoid*)0,0);/*##########重点就是使用旗语对共享区的访问###########*/for(i=0;i<100;++i){sleep(1);//设置成1s就会看到a/b交替出现,为0则a和b连续出现//grabthesemaphoresb.sem_num=0;sb.sem_op=-1;sb.sem_flg=0;if(semop(block->semID,&sb,1)!=-1){//writethelettertothesegmentbuffer//thisisourCRITICALdivblock->string[block->counter++]=user;sb.sem_num=0;sb.sem_op=1;sb.sem_flg=0;if(semop(block->semID,&sb,1)==-1)printf("Failedtoreleasethesemaphore/n");}elseprintf("Failedtoacquirethesemaphore/n");}//dosomeclearworkret=shmdt((void*)block);}elseif(!strncmp(argv[1],"read",4)){//herewewillreadthebufferinthesharedsegmentshmid=shmget(MY_SHM_ID,0,0);if(shmid!=-1){block=(MY_BLOCK_T*)shmat(shmid,(constvoid*)0,0);block->string[block->counter+1]=0;printf("%s/n",block->string);printf("Length=%d/n",block->counter);ret=shmdt((void*)block);}elseprintf("Unabletoreadsegment/n");}elseif(!strncmp(argv[1],"remove",6)){shmid=shmget(MY_SHM_ID,0,0);if(shmid>=0){block=(MY_BLOCK_T*)shmat(shmid,(constvoid*)0,0);//removethesemaphoreret=semctl(block->semID,0,IPC_RMID);if(ret==0)printf("Successfullyremovethesemaphore/n");//removethesharedsegmentret=shmctl(shmid,IPC_RMID,0);if(ret==0)printf("Successfullyremovethesegment/n");}}elseprintf("Unkonwcommand/n");}return0;}

++++++++++++++++++++++++++++++++++++++++++

以下两个程序是一个进程间通信的例子。这两个程序分别在不同的进程中运行,使用了共享内存进行通信。b从键盘读入数据,存放在共享内存中。a则从共享内存中读取数据,显示到屏幕上。由于没有使两个进程同步,显示的内容将是杂乱无章的.实例b程序负责向共享内存中写入数据,a程序负责从内存中读出共享的数据,它们之间并没有添加同步操作。

b.c

#include <sys/types.h>   #include <sys/ipc.h>   #include <sys/shm.h>   #include <stdio.h>     #define BUF_SIZE 1024   #define MYKEY 25   int main()  {      int shmid;      char *shmptr;        if((shmid = shmget(MYKEY,BUF_SIZE,IPC_CREAT)) ==-1)      {      printf("shmget error \n");      exit(1);      }        if((shmptr =shmat(shmid,0,0))==(void *)-1)      {      printf("shmat error!\n");      exit(1);      }        while(1)      {      printf("input:");      scanf("%s",shmptr);      }        exit(0);  } 

=======================================

a.c

#include <stdio.h>   #include <sys/types.h>   #include <sys/ipc.h>   #include <sys/shm.h>     #define BUF_SIZE 1024   #define MYKEY 25   int  main()  {      int shmid;      char * shmptr;        if((shmid = shmget(MYKEY,BUF_SIZE,IPC_CREAT)) ==-1)      {      printf("shmget error!\n");      exit(1);      }        if((shmptr = shmat(shmid,0,0)) == (void *)-1)      {      printf("shmat error!\n");      exit(1);      }        while(1)      {      printf("string :%s\n",shmptr);      sleep(3);      }        exit(0);  }  

看了哪些风景,遇到哪些人。尽管同学说,去旅行不在于记忆,

Linux共享内存编程实例

相关文章:

你感兴趣的文章:

标签云: