您的位置:首页 > 其它

IPC之共享内存(1)

2016-07-14 11:28 148 查看
                                                   共享内存

      
共享内存区是可用的IPC形式中最快的。一旦这样的内存区映射到共享他的进程的地址空间,这些进程间的数据传递就不再涉及内核。然而往共享内存区存放信息或者从共享内存区取走信息通常需要某种形式的同步。互斥锁,条件变量,读写锁,记录上锁和信号量都可以用于这种同步。


       
一般的进程间通信与共享内存区的区别:


       



       



       通过管道、FIFO和消息队列传递信息都需要经由内核,并且上图中需要四次数据复制。通过让两个或者多个进程共享一个共享内存区。这种形式的进程间通信只需要两次数据复制。共享内存区的对象同时出现在客户和服务器的地址空间中。

       默认情况下通过fork派生的子进程并不与其父进程共享内存区,之前自己写的例子中定义了一个全局变量然后让父子进程同时对这个全局变量循环加1操作结果,结果父子进程各有各的count变量互相没有任何影响。

       mmap函数

       函数功能:把一个文件或者POSIX共享内存区对象映射到调用进程的地址空间。

       使用mmap的目的:

       (1)使用普通文件以提供内存映射IO

       (2)使用特殊文件以提供匿名内存映射

       (3)使用shm_open以提供无亲缘关系进程间的POSIX共享内存区

       void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);

       addr指定描述符fd被映射到进程内空间的起始地址。被指定为空指针是指高速内核自己去选择起始地址。

       len指映射到调用进程地址空间中的字节数,

       内存映射区的保护由prot参数指定,分为四种可读、可写、可执行、不可访问

       flags有两个MAP_SHARED和MAP_PRIVATE,如果指定了PRIVATE则调用进程对被映射数据所做的修改只对该进程可见,而不改变其底层支持对象。如果指定了SHARED则调用进程对被映射数据所做的修改对于共享该对象的所有进程可见,而且确实改变了其底层支持对象

       父子进程之间共享内存区的方法之一是父进程在调用fork前先指定SHARED调用mmap.POSIX.1保证父进程中的映射关系存留到子进程中。

       int munmap(void *addr, size_t len);

       addr参数是由mmap函数返回的地址,len是映射区的大小。再次访问这些地址将导致向调用进程产生一个SIGSEGV信号。如果mmap函数是指定PRIVATE调用的那么调用进程对他所做的修改都将被丢弃。

       int msync(void *addr, size_t len, int flags);

       如果我们修改了处于内存映射到某个文件的内存区中某个位置的内容那么内核将在稍后的某个时刻相应的更新文件。然而有时候我们希望确信硬盘上的文件内容与内存映射区中的一致,于是调用msync来执行这种同步

       
为什么要使用mmap呢?


       我们open他之后调用mmap把它映射到调用进程地址空间的某个文件。使用内存映射文件所得到的特性是所有的IO都在内核的掩盖下完成,我们只需要编写存取内存映射区中各个值的代码。我们可以不调用read,write,lseek等。

       mmap的另一个用途是在无亲缘关系的进程间提供共享的内存区。这种情况下所映射的文件的实际内容成了被共享内存区的初始内容,而且这些进程对该共享内存区所做的任何变动都复制回所映射的文件。这里假设指定了SHARED标志,他是进程间共享内存所需求的。 

       

        

       
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: