/*共享内存允许两个或多个进程进程共享同一块内存(这块内存会映射到各个进程自己独立的地址空间)
  从而使得这些进程可以相互通信。
  在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>
#define MY_SHM_ID 67483
int main(  )
    {
        //获得系统中页面的大小
        printf( "page size=%d/n",getpagesize(  ) );
        //创建一个共享内存区段
        int shmid,ret;
        shmid=shmget( MY_SHM_ID,4096,0666|IPC_CREAT );
        //创建了一个4KB大小共享内存区段。指定的大小必须是当前系统架构
        //中页面大小的整数倍
        if( shmid>0 )
            printf( "Create a shared memory segment %d/n",shmid );
        //获得一个内存区段的信息
        struct shmid_ds shmds;
        //shmid=shmget( MY_SHM_ID,0,0 );//示例怎样获得一个共享内存的标识符
        ret=shmctl( shmid,IPC_STAT,&shmds );
        if( ret==0 )
            {
                printf( "Size of memory segment is %d/n",shmds.shm_segsz );
                printf( "Numbre of attaches %d/n",( int )shmds.shm_nattch );
            }
        else
            {
                printf( "shmctl(  ) call failed/n" );
            }
        //删除该共享内存区
        ret=shmctl( shmid,IPC_RMID,0 );
        if( ret==0 )
            printf( "Shared memory removed /n" );
        else
            printf( "Shared memory remove failed /n" );
        return 0;
    }

//共享内存区段的挂载,脱离和使用
//理解共享内存区段就是一块大内存
#include <stdio.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <errno.h>
#define MY_SHM_ID 67483
int main(  )
    {
        //共享内存区段的挂载和脱离
        int shmid,ret;
        void* mem;
        shmid=shmget( MY_SHM_ID,0,0 );
        if( shmid>=0 )
            {
                mem=shmat( shmid,( const void* )0,0 );
                //shmat()返回进程地址空间中指向区段的指针
                if( ( int )mem!=-1 )
                    {
                        printf( "Shared memory was attached in our address space at %p/n",mem );
                        //向共享区段内存写入数据
                        strcpy( ( char* )mem,"This is a test string./n" );
                        printf( "%s/n",(char*)mem );
                        //脱离共享内存区段
                        ret=shmdt( mem );
                        if( ret==0 )
                            printf( "Successfully detached memory /n" );
                        else
                            printf( "Memory detached failed %d/n",errno );
                    }
                else
                    printf( "shmat(  ) failed/n" );

            }
        else
            printf( "shared memory segment not found/n" );
        return 0;
    }
/*内存共享区段与旗语和消息队列不同,一个区段可以被锁定。
  被锁定的区段不允许被交换出内存。这样做的优势在于,与其
  把内存区段交换到文件系统,在某个应用程序调用时再交换回内存,
  不如让它一直处于内存中,且对多个应用程序可见。从提升性能的角度
  来看,很重要的。
 */
int shmid;
//...
shmid=shmget( MY_SHM_ID,0,0 );
ret=shmctl( shmid,SHM_LOCK,0 );
if( ret==0 )
    printf( "Locked!/n" );
////////////////////////////////////////////////////////////////////////
/*使用旗语协调共享内存的例子
  使用和编译命令
  gcc -Wall test.c -o test
  ./test create
  ./test use a &
  ./test use b &
  ./test read &
  ./test remove
 */
#include <stdio.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define MY_SHM_ID 34325
#define MY_SEM_ID 23234
#define MAX_STRING 200
typedef struct
{
    int semID;
    int counter;
    char string[ MAX_STRING+1 ];
}MY_BLOCK_T;
int main(int argc,char** argv)
    {
        int shmid,ret,i;
        MY_BLOCK_T* block;
        struct sembuf sb;
        char user;
        //make sure there is a command
        if( argc>=2 )
            {
                //create the shared memory segment and init it
                //with the semaphore
              if( !strncmp(argv[ 1 ],"create",6) )
                    {
                        //create the shared memory segment and semaphore
                        printf( "Creating the shared memory/n" );
                        shmid=shmget( MY_SHM_ID,sizeof( MY_BLOCK_T ),( IPC_CREAT|0666 ) );
                        block=( MY_BLOCK_T* )shmat( shmid,( const void* )0,0 );
                        block->counter=0;
                        //create the semaphore and init
                        block->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 );
                        //now detach the segment
                        shmdt( ( void* )block );
                        printf( "Create the shared memory and semaphore successuflly/n" );

                    }
                else if( !strncmp(argv[ 1 ],"use",3) )
                    {
                        /*use the segment*/
                        //must specify  also a letter to write to the buffer
                        if( argc<3 ) exit( -1 );
                        user=( char )argv[ 2 ][ 0 ];
                        //grab the segment
                        shmid=shmget( MY_SHM_ID,0,0 );
                        block=( MY_BLOCK_T* )shmat( shmid,( const void* )0,0 );

                        /*##########重点就是使用旗语对共享区的访问###########*/
                        for( i=0;i<100;++i )
                        {
                            sleep( 1 ); //设置成1s就会看到 a/b交替出现,为0则a和b连续出现
                        //grab the semaphore
                        sb.sem_num=0;
                        sb.sem_op=-1;
                        sb.sem_flg=0;
                        if( semop( block->semID,&sb,1 )!=-1 )
                            {
                                //write the letter to the segment buffer
                                //this is our CRITICAL SECTION
                                block->string[ block->counter++ ]=user;

                                sb.sem_num=0;
                                sb.sem_op=1;
                                sb.sem_flg=0;
                                if( semop( block->semID,&sb,1 )==-1 )
                                    printf( "Failed to release the semaphore/n" );

                            }
                        else
                            printf( "Failed to acquire the semaphore/n" );
                        }

                       //do some clear work
                        ret=shmdt(( void*)block);

                    }
                else if( !strncmp(argv[ 1 ],"read",4) )
                    {
                        //here we will read the buffer in the shared segment
                        shmid=shmget( MY_SHM_ID,0,0 );
                        if( shmid!=-1 )
                            {
                                block=( MY_BLOCK_T* )shmat( shmid,( const void* )0,0 );
                                block->string[ block->counter+1 ]=0;
                                printf( "%s/n",block->string );
                                printf( "Length=%d/n",block->counter );
                                ret=shmdt( ( void*)block );
                             }
                        else
                            printf( "Unable to read segment/n" );

                    }
                else if( !strncmp(argv[ 1 ],"remove",6) )
                    {
                        shmid=shmget( MY_SHM_ID,0,0 );
                        if( shmid>=0 )
                            {
                                block=( MY_BLOCK_T* )shmat( shmid,( const void* )0,0 );
                                //remove the semaphore
                                ret=semctl( block->semID,0,IPC_RMID );
                                if( ret==0 )
                                    printf( "Successfully remove the semaphore /n" );
                                //remove the shared segment
                                ret=shmctl( shmid,IPC_RMID,0 );
                                if( ret==0 )
                                    printf( "Successfully remove the segment /n" );
                            }
                    }
                else
                    printf( "Unkonw command/n" );
            }
        return 0;

    }

Linux共享内存编程实例的更多相关文章

  1. Linux 共享内存编程

    共享内存允许系统内两个或多个进程共享同一块内存空间,并且数据不用在客户进程和服务器进程间复制,因此共享内存是通信速度最快的一种IPC. 实现的机制简单描述如下:一个进程在系统中申请开辟了一块共享内存空 ...

  2. Linux共享内存(二)

    Linux共享内存编程实例 原文链接:http://blog.csdn.net/pcliuguangtao/article/details/6526119 /*共享内存允许两个或多个进程进程共享同一块 ...

  3. linux下socket编程实例

    linux下socket编程实例一.基本socket函数Linux系统是通过提供套接字(socket)来进行网络编程的.网络的socket数据传输是一种特殊的I/O,socket也是一种文件描述符.s ...

  4. linux 共享内存shm_open实现进程间大数据交互

    linux 共享内存shm_open实现进程间大数据交互 read.c #include <sys/types.h> #include <sys/stat.h> #includ ...

  5. Linux 程序设计1:深入浅出 Linux 共享内存

    笔者最近在阅读Aerospike 论文时,发现了Aerospike是利用了Linux 共享内存机制来实现的存储索引快速重建的.这种方式比传统利用索引文件进行快速重启的方式大大提高了效率.(减少了磁盘 ...

  6. Windows进程间共享内存通信实例

    Windows进程间共享内存通信实例 抄抄补补整出来 采用内存映射文件实现WIN32进程间的通讯:Windows中的内存映射文件的机制为我们高效地操作文件提供了一种途径,它允许我们在WIN32进程中保 ...

  7. linux 共享内存

    共享内存是最高效的IPC机制,因为它不涉及进程之间的任何数据传输.这种高效带来的问题是,我们必须用其他手段来同步进程对共享内存的访问,否则会产生竞态条件.所以,共享内存通常和其他进程间通信方式一起使用 ...

  8. Linux共享内存(一)

    inux系统编程我一直看 <GNU/LINUX编程指南>,只是讲的太简单了,通常是书和网络上的资料结合着来掌握才比较全面 .在掌握了书上的内容后,再来都其他资料 . 原文链接 http:/ ...

  9. linux 共享内存实现

    说起共享内存,一般来说会让人想起下面一些方法:1.多线程.线程之间的内存都是共享的.更确切的说,属于同一进程的线程使用的是同一个地址空间,而不是在不同地址空间之间进行内存共享:2.父子进程间的内存共享 ...

随机推荐

  1. Canvas实现3D效果-可旋转的立方体

    摘要:Canvas画布是一个二维平面,如何展示出3D效果?通过将三维空间中的Z轴抽取出来,将图像的点投影到与Z轴垂直的平面上,在通过旋转等变换效果,我们就能实现3D效果. 一.建立坐标系 1)立方体坐 ...

  2. 重载equals方法时要遵守的通用约定--自反性,对称性,传递性,一致性,非空性

    本文涉及到的概念 1.为什么重载equals方法时,要遵守通用约定 2.重载equals方法时,要遵守哪些通用约定   为什么重载equals方法时,要遵守通用约定 Object类的非final方法都 ...

  3. 论文答辩ppt要怎么写

    1.总体原则: 字大.字少.图多.要有重点 字体建议:正文要用黑体(如微软雅黑),标题可使用宋体或者黑体(如微软雅黑) 2. 主要分为两大部分: 2.1系统介绍 系统概述:概述自己系统主要是做了些什么 ...

  4. Java程序员的现代RPC指南

    Java程序员的现代RPC指南 1.前言 1.1 RPC框架简介 最早接触RPC还是初学Java时,直接用Socket API传东西好麻烦.于是发现了JDK直接支持的RMI,然后就用得不亦乐乎,各种大 ...

  5. Bootstrap3 栅格系统-Less mixin 和变量

    除了用于快速布局的预定义栅格类,Bootstrap 还包含了一组 Less 变量和 mixin 用于帮你生成简单.语义化的布局. 变量 通过变量来定义列数.槽(gutter)宽.媒体查询阈值(用于确定 ...

  6. IntelliJ IDEA在Local模式下Spark程序消除日志中INFO输出

    在使用Intellij IDEA,local模式下运行Spark程序时,会在Run窗口打印出很多INFO信息,辅助信息太多可能会将有用的信息掩盖掉.如下所示 要解决这个问题,主要是要正确设置好log4 ...

  7. Xcode 调试技巧 --常用命令和断点

    Xcode 中的调试技巧与我们的日常开发息息相关,而这些调试技巧在我们解决Bug时,常常有事半功倍的作用,经常会用到的有各种断点 和 命令.而这些调试技巧也经常会在面试中问到,所以不知道的就来看看吧. ...

  8. OpenCV+OpenGL 双目立体视觉三维重建

    0.绪论 这篇文章主要为了研究双目立体视觉的最终目标--三维重建,系统的介绍了三维重建的整体步骤.双目立体视觉的整体流程包括:图像获取,摄像机标定,特征提取(稠密匹配中这一步可以省略),立体匹配,三维 ...

  9. GC真正的垃圾:强、软、弱、和虚 对象

    垃圾回收的基本思想就是判断一个对象是否可触及性,说白了就是判断一个对象是否可以访问,如果对象对引用了,说明对象正在被使用,如果发现对象没有被引用,说明对象已经不再使用了,不再使用的对象可以被回收,但是 ...

  10. qq侧滑

    上一篇博客带大家实现了:Android 自定义控件打造史上最简单的侧滑菜单 ,有兄弟看了以后说,你这滑动菜单过时了呀~QQ5.0的效果还不错~~嗯,的确,上一篇也承诺过,稍微修改上一篇的代码,实现QQ ...