/*共享内存允许两个或多个进程进程共享同一块内存(这块内存会映射到各个进程自己独立的地址空间)
  从而使得这些进程可以相互通信。
  在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. 巧用第三方快速开发Android App 热门第三方SDK及框架

    巧用第三方快速开发Android App 热门第三方SDK及框架 历经大半年的时间,终于是把这门课程给录制出来了,也就在今天,正式在慕课网上上线了 项目地址:巧用第三方快速开发Android App ...

  2. DISC社交风格测试题--老虎 孔雀 考拉 猫头鹰

    凭直觉,迅速回答 "我是谁",而不是"我应该是谁,或我想我是谁". 1.关于人生观,我的内心其实是: A 希望能够有尽量多的人生体验,所以会有非常多样化的想法. ...

  3. PGM:图模型学习概述

    http://blog.csdn.net/pipisorry/article/details/52571640 动机 前面我们讨论的问题出发点是给定一个图模型.如在独立性和推理讨论中,假定模型--结构 ...

  4. ubuntu垃圾清理命令

    ubuntu的空间莫名不够用了 通过系统自带的工具磁盘使用分析器,发现var文件下面的log100多个g,这个日志文件是可以删除的,然后tmp文件也是可以删除的. 1.sudo rm -rf /tmp ...

  5. 制作pypi上的安装库

    下载地址 如何制作分发工具呢 setuppy 源码包 其他文件 制作过程 首先上场的肯定是setuppy了如下 然后是LICENCE 注册 测试 总结 自从接触Python以来也有几个月了,虽然主要的 ...

  6. Python 文本转语音

    文本转语音,一般会用在无障碍开发.下面介绍如何使用Python实现将文本文件转换成语音输出. 准备 使用Speech API 原理 示例代码 小总结 pyttsx方式 原理 示例代码 小总结 pytt ...

  7. HDFS的写数据过程分析

    HDFS的写数据过程分析 我们通过FileSystem类可以操控HDFS, 那我们就从这里开始分析写数据到HDFS的过程. 在我们向 HDFS 写文件的时候,调用的是 FileSystem.creat ...

  8. shell test和find命令实例解析

    shell test和find命令实例解析 下面以\build\core\product.mk相关部分来学习 define _find-android-products-files $(shell t ...

  9. FFmpeg与libx264接口源代码简单分析

    ===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...

  10. hbase高性能读取数据

    有时需要从hbase中一次读取大量的数据,同时对实时性有较高的要求.可以从两方面进行考虑:1.hbase提供的get方法提供了批量获取数据方法,通过组装一个list<Get> gets即可 ...