• 共享内存(ShareMemory)


       进程间通信方式: socket、管道(pipe)、信箱(MailSlot)、共享内存(ShareMemory)

      共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式。两个不同进程A、B共享内存的意思是,同一块物理内存被映射到进程A、B各自的进程地址空间。进程A可以即时看到进程B对共享内存中数据的更新,反之亦然。由于多个进程共享同一块内存区域,必然需要某种同步机制,互斥锁和信号量都可以。

      Windows上共享内存是通过FileMapping实现的;

      1、创建FileMapping内核对象:CreateFileMapping;

      2、打开FileMapping内核对象;

      3、MapViewOfFile映射到当前进程的虚拟地址上;

      4、UnmapViewOfFile 回收内存地址空间(一旦用完共享内存);

    示例代码:

    #ifndef _IPCDEMO_SHAREMEMORY_H_
    #define _IPCDEMO_SHAREMEMORY_H_
    
    #include <windows.h>
    #include <stdio.h>
    #include <conio.h>
    
    static TCHAR	szName[] = TEXT("MyFileMapping");
    #define BUF_SIZE 1024
    
    LPTSTR CreateShareMemory(HANDLE &hHandle, LPCTSTR pszKey)
    {
    	HANDLE	hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, szName);
    	if (!hMapFile)
    	{
    		hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, BUF_SIZE, pszKey);
    		if (!hMapFile)
    		{
    			return NULL;
    		}
    	}
    
    	hHandle = hMapFile;
    	LPVOID	lpMapAddress = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
    	return (TCHAR*)lpMapAddress;
    }
    
    #endif
    

    云风的博客Windows 下的进程间通讯及数据共享

      Linux上共享内存的实现实通过shmget来实现的;

      1、shmget:created shared-memory

      2、shmat:attached shared-memory

      3、shmdt:deattached shared-memory

      4、shmctl: delete shared-memory

    linux上比较有价值的文章Linux进程间通信---共享内存(shmget)

    #include <sys/ipc.h>

    #include <sys/shm.h>
    int shmget(key_t key, size_t size, int shmflg);

    key_t key
    -----------------------------------------------
        key标识共享内存的键值: 0/IPC_PRIVATE。 当key的取值为IPC_PRIVATE,则函数shmget()将创建一块新的共享内存;如果key的取值为0,而参数shmflg中设置了IPC_PRIVATE这个标志,则同样将创建一块新的共享内存。
        在IPC的通信模式下,不管是使用消息队列还是共享内存,甚至是信号量,每个IPC的对象(object)都有唯一的名字,称为“键”(key)。通过“键”,进程能够识别所用的对象。“键”与IPC对象的关系就如同文件名称之于文件,通过文件名,进程能够读写文件内的数据,甚至多个进程能够共用一个文件。而在IPC的通讯模式下,通过“键”的使用也使得一个IPC对象能为多个进程所共用。
        Linux系统中的所有表示System V中IPC对象的数据结构都包括一个ipc_perm结构,其中包含有IPC对象的键值,该键用于查找System V中IPC对象的引用标识符。如果不使用“键”,进程将无法存取IPC对象,因为IPC对象并不存在于进程本身使用的内存中。
        通常,都希望自己的程序能和其他的程序预先约定一个唯一的键值,但实际上并不是总可能的成行的,因为自己的程序无法为一块共享内存选择一个键值。因此,在此把key设为IPC_PRIVATE,这样,操作系统将忽略键,建立一个新的共享内存,指定一个键值,然后返回这块共享内存IPC标识符ID。而将这个新的共享内存的标识符ID告诉其他进程可以在建立共享内存后通过派生子进程,或写入文件或管道来实现。


    int size(单位字节Byte)
    -----------------------------------------------
        size是要建立共享内存的长度。所有的内存分配操作都是以页为单位的。所以如果一段进程只申请一块只有一个字节的内存,内存也会分配整整一页(在i386机器中一页的缺省大小PACE_SIZE=4096字节)这样,新创建的共享内存的大小实际上是从size这个参数调整而来的页面大小。即如果size为1至4096,则实际申请到的共享内存大小为4K(一页);4097到8192,则实际申请到的共享内存大小为8K(两页),依此类推。


    int shmflg
    -----------------------------------------------
        shmflg主要和一些标志有关。其中有效的包括IPC_CREAT和IPC_EXCL,它们的功能与open()的O_CREAT和O_EXCL相当。
        IPC_CREAT   如果共享内存不存在,则创建一个共享内存,否则打开操作。
        IPC_EXCL    只有在共享内存不存在的时候,新的共享内存才建立,否则就产生错误。

        如果单独使用IPC_CREAT,shmget()函数要么返回一个已经存在的共享内存的操作符,要么返回一个新建的共享内存的标识符。如果将IPC_CREAT和IPC_EXCL标志一起使用,shmget()将返回一个新建的共享内存的标识符;如果该共享内存已存在,或者返回-1。IPC_EXEL标志本身并没有太大的意义,但是和IPC_CREAT标志一起使用可以用来保证所得的对象是新建的,而不是打开已有的对象。对于用户的读取和写入许可指定SHM_RSHM_W,(SHM_R>3)和(SHM_W>3)是一组读取和写入许可,而(SHM_R>6)和(SHM_W>6)是全局读取和写入许可。


    返回值
    -----------------------------------------------
    成功返回共享内存的标识符;不成功返回-1,errno储存错误原因。
        EINVAL        参数size小于SHMMIN或大于SHMMAX。
        EEXIST        预建立key所致的共享内存,但已经存在。
        EIDRM         参数key所致的共享内存已经删除。
        ENOSPC        超过了系统允许建立的共享内存的最大值(SHMALL )。
        ENOENT        参数key所指的共享内存不存在,参数shmflg也未设IPC_CREAT位。
        EACCES        没有权限。
        ENOMEM        核心内存不足。

    补:

    linux下共享内存查看命令:

    ipcs -m(ipcs命令打印出所有共享内存/信号量/消息,-m只打印共享内存)。

    共享内存删除命令:

    ipcrm shmid(shmid是ipcs -m打印出来的第二列)。

  • 相关阅读:
    Java设计模式(Design Patterns)
    P2213 [USACO14MAR]懒惰的牛The Lazy Cow_Sliver
    P3120 [USACO15FEB]牛跳房子(金)Cow Hopscotch (Gold)
    P4818 [USACO15DEC]Bessie's Dream 贝西的梦
    P3667 [USACO17OPEN]Bovine Genomics
    P4379 [USACO18OPEN]Lemonade Line
    P4378 [USACO18OPEN]Out of Sorts S
    P4089 [USACO17DEC]The Bovine Shuffle
    P4269 [USACO18FEB]Snow Boots G
    P4086 [USACO17DEC]My Cow Ate My Homework
  • 原文地址:https://www.cnblogs.com/coderyoyo/p/1876958.html
Copyright © 2020-2023  润新知