• Linux 共享内存编程


    共享内存允许系统内两个或多个进程共享同一块内存空间,并且数据不用在客户进程和服务器进程间复制,因此共享内存是通信速度最快的一种IPC。

    实现的机制简单描述如下:一个进程在系统中申请开辟了一块共享内存空间,然后使用这个共享内存空间的各个进程分别打开这个共享内存空间,并将这个内存空间映射到自己的进程空间上,这样各个进程就可以共同使用这个共享内存空间,就如同使用自己进程地址空间的内存一样。

    要实现共享内存空间,内核做了许多工作:比如给每个共享内存块分发一个“身份证”、允许用户进程将共享内存映射到各自的地址空间上、在进程提出申请以后将共享内存和进程地址空间脱离,并在适当的时候讲共享内存删除,让其回到可以被创建的状态。

    用户利用共享内存实现进程间的通信,实际上就是使用内核提供的服务完成对共享内存的建立、映射、脱离、删除等。当建立并映射成功以后,进程间就能通过共享内存实现数据的交互。下面就分别介绍内核提供的服务:

    int shmget(key_t key, size_t size, int shmflg)

    void *shmat(int shmid,const void* shmaddr,int shmflg);

    int shmdt(const void* shmaddr);

    int shmctl(int shmid, int cmd, struct shmid_ds *buf);

    shmget 函数

    shmget 函数实现共享内存的建立或者打开。当共享内存的键值key 尚未存在时,调用这个函数并且指定shmflg 参数为IPC_CREAT 可以创建一个大小为 size 的共享内存空间。假设key指定的共享内存已经存在,调用这个函数可以打开这个共享内存,但不会创建。键值的获取可以利用 ftok(),该函数的使用在博主的另一篇文章里http://www.cnblogs.com/linzizhang/p/4544794.html中有介绍。

    shmat 函数

    该函数将一个共享内存空间映射到调用进程的地址空间上,并且返回在进程地址空间中的地址。用户拿到改地址后就可以通过这个地址间接的访问共享内存。shmid 参数就是shmget 函数的返回值,shmaddr 参数实际上是指出了共享内存映射到进程地址空间上的位置,但是我们一般不会指定这个地址,而是令其为NULL ,让内核选择一个合适的地址。shmflg 参数是配合着shmaddr 参数使用的,在shmaddr 为NULL时就变得没有实际意义,因此通常指定为0。

    shmdt 函数

    这个函数将一个进程已经映射了的共享内存脱离进程地址空间。shmaddr 参数就是在进程地址空间的地址,实际就是shmat 函数的返回值。

    shmctl 函数

    此函数实际上有很多的功能,但是我们通长用它将一个已经创建了的共享内存删除,所谓删除实际就是将它放回可以被创建的共享内存队列中。指定cmd 参数为IPC_RMID,就可以将shmid键值指定的共享内存删除,而buf实际上是可以获取这共享内存在内核中的状态,如果不想了解可以指定为0。

    共享内存通信使用到的系统服务就这么多,下面给出一个测试范例。该范例由两个进程组成,进程write将键盘上输入的字符串存储到共享内存,read进程将共享内存中的数据读出来,再西融入显示器显示。

    write进程代码:

    #include <sys/ipc.h>
    #include <sys/shm.h>
    #include <stdio.h>
    #include <sys/types.h>
    #include <string.h>
    
    #define TEXT_SZ 2048
    
    struct shared_use_st
    {
        int written_by_you;
        char some_text[TEXT_SZ];      
    };
    
    int main(int argc,char **argv)
    {
         
        key_t key;
        int shmid;  
        struct shared_use_st *space;
        int running  = 1;
        char buffer[TEXT_SZ];
        //creat shared memory
        key = ftok("/home/application/shared_memory",2);
    
        shmid = shmget(key,sizeof(struct shared_use_st),IPC_CREAT);
    
        //attach share memory to space
        space = (struct shared_use_st *)shmat(shmid,NULL,0);          
    
        //write datas to space
        while(running)
        {
            while(space->written_by_you==1)
            {
                sleep(1);    
            }
            printf("Input strings:");
            fgets(buffer,TEXT_SZ,stdin);
            strncpy(space->some_text,buffer,TEXT_SZ);
            space->written_by_you = 1;
            if(strncmp(buffer,"end",3)==0)
            {
                running = 0;    
            }
           
        }
        
        
        //dis_attach to space
        shmdt((const void *)space);
        //distroy shared memory
      //  shmctl(shmid,IPC_RMID);
    
        return 0;
    }
    View Code

    read进程代码:

    #include <sys/ipc.h>
    #include <sys/shm.h>
    #include <stdio.h>
    #include <sys/types.h>
    #include <string.h>
    
    #define TEXT_SZ 2048
    struct shared_use_st
    {
        int written_by_you;    //标志用来标明write进程是否写入了数据 written_by_you==1,写入数据,且read进程还没读走
        char some_text[TEXT_SZ];      
    };
    
    int main()
    {
        key_t key;
        int shmid;
        struct shared_use_st *space;
        int running = 1;
        char buffer[TEXT_SZ];
        //打开共享内存
        key = ftok("/home/application/shared_memory",2);
    
        shmid = shmget(key,sizeof(struct shared_use_st),IPC_CREAT);
        
        //映射共享内存
        space = (struct shared_use_st *)shmat(shmid,NULL,0);    
        
        //读取数据
        while(running)
        {
            if(space->written_by_you==1)
            {
                strncpy(buffer,space->some_text,TEXT_SZ);
                space->written_by_you = 0;
                printf("Recieved string :%s",buffer);    
            }    
            if(strncmp(buffer,"end",3)==0)
            {
                running = 0;    
            }
            
        }
        
        //断开映射
        shmdt((const void *)space);
        
        //删除共享内存
        shmctl(shmid,IPC_RMID,0);
        
        return 0;
            
    }
    View Code
  • 相关阅读:
    git使用记录
    【转】话说我打算一天学完object c语法,系列1--------来自书Objective-c程序设计
    【转】看源代码那些事
    中英文对照 —— 数学定律定理(公式及其描述)
    CUDA+OpenGL混合编程
    简明欧洲史
    简明欧洲史
    CUDA一维纹理内存
    CUDA中的常量内存__constant__
    CUDA线程协作之共享存储器“__shared__”&&“__syncthreads()”
  • 原文地址:https://www.cnblogs.com/linzizhang/p/4548564.html
Copyright © 2020-2023  润新知