zoukankan      html  css  js  c++  java
  • 转:共享内存的编程实现

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

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

  • 相关阅读:
    tensorflow实践学习一
    计算CPU的MIPS
    计算机原理一
    SecureCRT连接虚拟机失败及虚拟机ping不通外网
    03.os
    02.random
    01.time
    01.面试过程中其他问题
    06.秒杀系统架构
    05.项目并发分析
  • 原文地址:https://www.cnblogs.com/watermoon/p/2690210.html
Copyright © 2011-2022 走看看