zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    课堂作业04 2017.10.27
    课程作业 03 动手动脑 2017.10.20
    课程作业 03 2017.10.20
    HDU 3974 Assign the task
    POJ 2155 Matrix
    POJ 2481 Cows
    HDU 3038 How Many Answers Are Wrong
    CS Academy Array Removal
    POJ_1330 Nearest Common Ancestors LCA
    CF Round 427 D. Palindromic characteristics
  • 原文地址:https://www.cnblogs.com/linzizhang/p/4548564.html
Copyright © 2011-2022 走看看