Chinaunix首页 | 论坛 | 博客
  • 博客访问: 804674
  • 博文数量: 274
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 862
  • 用 户 组: 普通用户
  • 注册时间: 2015-10-24 15:31
个人简介

不合格的程序猿

文章分类

全部博文(274)

文章存档

2019年(3)

2018年(1)

2017年(4)

2016年(160)

2015年(106)

我的朋友

分类: C/C++

2015-10-27 20:54:42

Linux共享内存编程实例

原文链接:http://blog.csdn.net/pcliuguangtao/article/details/6526119



点击(此处)折叠或打开

  1. /*共享内存允许两个或多个进程进程共享同一块内存(这块内存会映射到各个进程自己独立的地址空间)
  2.   从而使得这些进程可以相互通信。
  3.   在GNU/Linux中所有的进程都有唯一的虚拟地址空间,而共享内存应用编程接口API允许一个进程使
  4.   用公共内存区段。但是对内存的共享访问其复杂度也相应增加。共享内存的优点是简易性。
  5.   使用消息队列时,一个进程要向队列中写入消息,这要引起从用户地址空间向内核地址空间的一次复制,
  6.   同样一个进程进行消息读取时也要进行一次复制。共享内存的优点是完全省去了这些操作。
  7.   共享内存会映射到进程的虚拟地址空间,进程对其可以直接访问,避免了数据的复制过程。
  8.   因此,共享内存是GNU/Linux现在可用的最快速的IPC机制。
  9.   进程退出时会自动和已经挂接的共享内存区段分离,但是仍建议当进程不再使用共享区段时
  10.   调用shmdt来卸载区段。
  11.   注意,当一个进程分支出父进程和子进程时,父进程先前创建的所有共享内存区段都会被子进程继承。
  12.   如果区段已经做了删除标记(在前面以IPC——RMID指令调用shmctl),而当前挂接数已经变为0,
  13.   这个区段就会被移除。
  14.  */
  15. /*
  16.   shmget( ) 创建一个新的共享内存区段
  17.               取得一个共享内存区段的描述符
  18.   shmctl( ) 取得一个共享内存区段的信息
  19.               为一个共享内存区段设置特定的信息
  20.               移除一个共享内存区段
  21.   shmat( ) 挂接一个共享内存区段
  22.   shmdt( ) 于一个共享内存区段的分离
  23.  */
  24. //创建一个共享内存区段,并显示其相关信息,然后删除该内存共享区
  25. #include <stdio.h>
  26. #include <unistd.h> //getpagesize( )
  27. #include <sys/ipc.h>
  28. #include <sys/shm.h>
  29. #define MY_SHM_ID 67483
  30. int main( )
  31.     {
  32.         //获得系统中页面的大小
  33.         printf( "page size=%d/n",getpagesize( ) );
  34.         //创建一个共享内存区段
  35.         int shmid,ret;
  36.         shmid=shmget( MY_SHM_ID,4096,0666|IPC_CREAT );
  37.         //创建了一个4KB大小共享内存区段。指定的大小必须是当前系统架构
  38.         //中页面大小的整数倍
  39.         if( shmid>0 )
  40.             printf( "Create a shared memory segment %d/n",shmid );
  41.         //获得一个内存区段的信息
  42.         struct shmid_ds shmds;
  43.         //shmid=shmget( MY_SHM_ID,0,0 );//示例怎样获得一个共享内存的标识符
  44.         ret=shmctl( shmid,IPC_STAT,&shmds );
  45.         if( ret==0 )
  46.             {
  47.                 printf( "Size of memory segment is %d/n",shmds.shm_segsz );
  48.                 printf( "Numbre of attaches %d/n",( int )shmds.shm_nattch );
  49.             }
  50.         else
  51.             {
  52.                 printf( "shmctl( ) call failed/n" );
  53.             }
  54.         //删除该共享内存区
  55.         ret=shmctl( shmid,IPC_RMID,0 );
  56.         if( ret==0 )
  57.             printf( "Shared memory removed /n" );
  58.         else
  59.             printf( "Shared memory remove failed /n" );
  60.         return 0;
  61.     }

  62. //共享内存区段的挂载,脱离和使用
  63. //理解共享内存区段就是一块大内存
  64. #include <stdio.h>
  65. #include <sys/shm.h>
  66. #include <sys/ipc.h>
  67. #include <errno.h>
  68. #define MY_SHM_ID 67483
  69. int main( )
  70.     {
  71.         //共享内存区段的挂载和脱离
  72.         int shmid,ret;
  73.         void* mem;
  74.         shmid=shmget( MY_SHM_ID,0,0 );
  75.         if( shmid>=0 )
  76.             {
  77.                 mem=shmat( shmid,( const void* )0,0 );
  78.                 //shmat()返回进程地址空间中指向区段的指针
  79.                 if( ( int )mem!=-1 )
  80.                     {
  81.                         printf( "Shared memory was attached in our address space at %p/n",mem );
  82.                         //向共享区段内存写入数据
  83.                         strcpy( ( char* )mem,"This is a test string./n" );
  84.                         printf( "%s/n",(char*)mem );
  85.                         //脱离共享内存区段
  86.                         ret=shmdt( mem );
  87.                         if( ret==0 )
  88.                             printf( "Successfully detached memory /n" );
  89.                         else
  90.                             printf( "Memory detached failed %d/n",errno );
  91.                     }
  92.                 else
  93.                     printf( "shmat( ) failed/n" );
  94.                 
  95.             }
  96.         else
  97.             printf( "shared memory segment not found/n" );
  98.         return 0;
  99.     }
  100. /*内存共享区段与旗语和消息队列不同,一个区段可以被锁定。
  101.   被锁定的区段不允许被交换出内存。这样做的优势在于,与其
  102.   把内存区段交换到文件系统,在某个应用程序调用时再交换回内存,
  103.   不如让它一直处于内存中,且对多个应用程序可见。从提升性能的角度
  104.   来看,很重要的。
  105.  */
  106. int shmid;
  107. //...
  108. shmid=shmget( MY_SHM_ID,0,0 );
  109. ret=shmctl( shmid,SHM_LOCK,0 );
  110. if( ret==0 )
  111.     printf( "Locked!/n" );
  112. ////////////////////////////////////////////////////////////////////////
  113. /*使用旗语协调共享内存的例子
  114.   使用和编译命令
  115.   gcc -Wall test.c -o test
  116.   ./test create
  117.   ./test use a &
  118.   ./test use b &
  119.   ./test read &
  120.   ./test remove
  121.  */
  122. #include <stdio.h>
  123. #include <sys/shm.h>
  124. #include <sys/ipc.h>
  125. #include <sys/sem.h>
  126. #include <string.h>
  127. #include <stdlib.h>
  128. #include <unistd.h>
  129. #define MY_SHM_ID 34325
  130. #define MY_SEM_ID 23234
  131. #define MAX_STRING 200
  132. typedef struct
  133. {
  134.     int semID;
  135.     int counter;
  136.     char string[ MAX_STRING+1 ];
  137. }MY_BLOCK_T;
  138. int main(int argc,char** argv)
  139.     {
  140.         int shmid,ret,i;
  141.         MY_BLOCK_T* block;
  142.         struct sembuf sb;
  143.         char user;
  144.         //make sure there is a command
  145.         if( argc>=2 )
  146.             {
  147.                 //create the shared memory segment and init it
  148.                 //with the semaphore
  149.               if( !strncmp(argv[ 1 ],"create",6) )
  150.                     {
  151.                         //create the shared memory segment and semaphore
  152.                         printf( "Creating the shared memory/n" );
  153.                         shmid=shmget( MY_SHM_ID,sizeof( MY_BLOCK_T ),( IPC_CREAT|0666 ) );
  154.                         block=( MY_BLOCK_T* )shmat( shmid,( const void* )0,0 );
  155.                         block->counter=0;
  156.                         //create the semaphore and init
  157.                         block->semID=semget(MY_SEM_ID,1,( IPC_CREAT|0666 ));
  158.                         sb.sem_num=0;
  159.                         sb.sem_op=1;
  160.                         sb.sem_flg=0;
  161.                         semop( block->semID,&sb,1 );
  162.                         //now detach the segment
  163.                         shmdt( ( void* )block );
  164.                         printf( "Create the shared memory and semaphore successuflly/n" );
  165.                         
  166.                     }
  167.                 else if( !strncmp(argv[ 1 ],"use",3) )
  168.                     {
  169.                         /*use the segment*/
  170.                         //must specify also a letter to write to the buffer
  171.                         if( argc<3 ) exit( -1 );
  172.                         user=( char )argv[ 2 ][ 0 ];
  173.                         //grab the segment
  174.                         shmid=shmget( MY_SHM_ID,0,0 );
  175.                         block=( MY_BLOCK_T* )shmat( shmid,( const void* )0,0 );
  176.                         
  177.                         /*##########重点就是使用旗语对共享区的访问###########*/
  178.                         for( i=0;i<100;++i )
  179.                         {
  180.                             sleep( 1 ); //设置成1s就会看到 a/b交替出现,为0则a和b连续出现
  181.                         //grab the semaphore
  182.                         sb.sem_num=0;
  183.                         sb.sem_op=-1;
  184.                         sb.sem_flg=0;
  185.                         if( semop( block->semID,&sb,1 )!=-1 )
  186.                             {
  187.                                 //write the letter to the segment buffer
  188.                                 //this is our CRITICAL SECTION
  189.                                 block->string[ block->counter++ ]=user;
  190.                                 
  191.                                 sb.sem_num=0;
  192.                                 sb.sem_op=1;
  193.                                 sb.sem_flg=0;
  194.                                 if( semop( block->semID,&sb,1 )==-1 )
  195.                                     printf( "Failed to release the semaphore/n" );
  196.                                 
  197.                             }
  198.                         else
  199.                             printf( "Failed to acquire the semaphore/n" );
  200.                         }
  201.                         
  202.                        //do some clear work
  203.                         ret=shmdt(( void*)block);
  204.                         
  205.                     }
  206.                 else if( !strncmp(argv[ 1 ],"read",4) )
  207.                     {
  208.                         //here we will read the buffer in the shared segment
  209.                         shmid=shmget( MY_SHM_ID,0,0 );
  210.                         if( shmid!=-1 )
  211.                             {
  212.                                 block=( MY_BLOCK_T* )shmat( shmid,( const void* )0,0 );
  213.                                 block->string[ block->counter+1 ]=0;
  214.                                 printf( "%s/n",block->string );
  215.                                 printf( "Length=%d/n",block->counter );
  216.                                 ret=shmdt( ( void*)block );
  217.                              }
  218.                         else
  219.                             printf( "Unable to read segment/n" );
  220.                 
  221.                     }
  222.                 else if( !strncmp(argv[ 1 ],"remove",6) )
  223.                     {
  224.                         shmid=shmget( MY_SHM_ID,0,0 );
  225.                         if( shmid>=0 )
  226.                             {
  227.                                 block=( MY_BLOCK_T* )shmat( shmid,( const void* )0,0 );
  228.                                 //remove the semaphore
  229.                                 ret=semctl( block->semID,0,IPC_RMID );
  230.                                 if( ret==0 )
  231.                                     printf( "Successfully remove the semaphore /n" );
  232.                                 //remove the shared segment
  233.                                 ret=shmctl( shmid,IPC_RMID,0 );
  234.                                 if( ret==0 )
  235.                                     printf( "Successfully remove the segment /n" );
  236.                             }
  237.                     }
  238.                 else
  239.                     printf( "Unkonw command/n" );
  240.             }
  241.         return 0;
  242.         
  243.     }

阅读(735) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~