ITKeyword,专注技术干货聚合推荐

注册 | 登录

Linux 多线程编程( POSIX )( 六 )----->共享内存区

shanshanpt 分享于 2012-03-21

推荐:Posix多线程编程(6)—共享内存

一、什么是共享内存区 共享内存区是最快的可用IPC形式。它允许多个不相关的进程去访问同一部分逻辑内存。如果需要在两个运行中的进程之间传输数据,共享内存将是

2020腾讯云共同战“疫”,助力复工(优惠前所未有!4核8G,5M带宽 1684元/3年),
地址https://cloud.tencent.com/act/cps/redirect?redirect=1053

2020阿里云最低价产品入口,含代金券(新老用户有优惠),
地址https://www.aliyun.com/minisite/goods


Attention:打开相关代码区

推荐:Linux 多线程编程( POSIX )( 二 )----->代码区 ( pthread_attr_t 线程属性实例 )

1.detach实例: //!> detach #include <stdio.h> #include <stdlib.h> #include <pthread.h> void * entrance( void * arg ) {       int                     


1. 介绍 


    POSIX 共享内存和SYSTEMV的共享内存的框架是差不多的,细节有区别!
      在前面的SYSTEM V的共享内存区我们已经知道共享内存区是最快的IPC形式!
      例如在两个进程之间传输data,那么此方法将会是非常高效的!、
     
      共享内存是由IPC为一个进程创建的一个特殊的地址范围,它将出现在进程的地址
      空间中。其他进程可以把同一段共享内存段“连接到”它们自己的地址空间里去。所
      有进程都可以访问共享内存中的地址。如果一个进程向这段共享内存写了数据,所
      做的改动会立刻被有访问同一段共享内存的其他进程看到。
     
      但是我们知道同时可以有多个进程访问,那么要控制一段时间内只能有一个,所以
      为了同步,那么必须要用到前面的信号量,互斥量,条件量之类的可以同步的机
      制!
     
2.   mmap函数:
      mmap函数把一个文件或一个POSIX共享内存区对象映射到调用进程的地址空间。使
      用该函数的目的:
      >: 1.使用普通文件以提供内存映射I/O
      >: 2.使用特殊文件以提供匿名内存映射。
      >: 3.使用shm_open以提供无亲缘关系进程间的Posix共享内存区。
     
      #include<sys/mman.h>
      void * mmap(void * addr, size_t len, int prot, int flag, int filedes, off_t off)
      参数:
      addr          指向映射存储区的起始地址
      len                  映射的字节
      prot                对映射存储区的保护要求
      flag                flag标志位
      filedes            要被映射文件的描述符
      off                  要映射字节在文件中的起始偏移量

      若成功则返回映射区的起始地址,若出错则返回MAP_FAILED

      注意:
      >:      addr参数用于指定映射存储区的起始地址。通常将其设置为NULL,这表示由系
                统选择该映射区的起始地址。
      >:      prot参数说明对映射存储区的保护要求。可是PROT_READ(映射区可
                读),PROT_WRITE(映射区可写),PROT_EXEC(映射区可执行)任意组合的按位
                或,也可以是PROT_NONE(映射区不可访问)。对指定映射存储区的保护要求不
                能超过文件open模式访问权限。
      >:      flag参数影响映射区的多种属性:     
            >:MAP_FIXED: 返回值必须等于addr.因为这不利于可移植性,所以不鼓励使用此标
            志。
            >:MAP_SHARED: 这一标志说明了本进程对映射区所进行的存储操作的配置。
            此标志指定存储操作修改映射文件。
            >:MAP_PRIVATE: 本标志导致对映射区建立一个该映射文件的一个私有副本。所有
            后来对该映射区的引用都是引用该副本,而不是原始文件。
           
            要注意的是必须指定MAP_FIXED或MAP_PRIVATE标志其中的一个,指定前者是对存储
            映射文件本身的一个操作,而后者是对其副本进行操作。
     
      >:      filedes指要被映射文件的描述符。在映射该文件到一个地址空间之前,先要打开该文
                件。len是映射的字节数。

      >:      off是要映射字节在文件中的起始偏移量。通常将其设置为0。
     
      注意:mmap成功返回后,fd参数可以关闭。
     
3.   munmap函数
      删除一个映射关系
     
      #include<sys/mman.h>
      int munmap(caddr_t addr, size_t len );
      参数:
      addr                指向映射存储区的起始地址
      len                  映射的字节

      成功返回0,失败返回-1
     
      注意:
                  >:      addr是由mmap返回的地址,len是映射区大小,if已经被删除后再次访问这些
                            地址,那么会返回给进程一个SIGSEGV信号!
                  >:      同时注意,if flag是MAP_PRIVATE,那么对映射区所做的都无效,仅仅是对其
                        产生的一个副本进行的操作!
     
      对于映射文件和内存映射区来说,通常会有一个同步的需求!这就是说,如果我们修改
      了内存映射到某个文件的内存区中某个位置的内容,那么内核将在稍后某个时刻相应地
      更新文件。然而有时候我们希望确信硬盘上的文件内容与内存映射区中的文件内容一
      致,于是调用msync来执行这种同步。
     
3.   文件与内存同步函数:
      #include<sys/mman.h>     
      int msync(void * addr, size_t len, int flags );
      参数:
            addr                指向映射存储区的起始地址
            len                  映射的字节
            flags            修改方式标志
     
      成功返回0,失败返回-1;
     
      flags取值:
                        MS_ASYNC:异步写
                        MS_SYNC:同步写
                        MS_INVALIDATE:使高速缓存的数据实效
      注意:前两个必须指定且只能指定一个!!!
      区别:MS_ASYNC:一旦写操作由内核排入队列,立即返回!
                  MS_SYNC:等到写操作完成后才返回!
      if还指定了MS_INVALIDATE,那么最终拷贝不一致的文件数据的所有内存中拷贝都失效!
      后续的引用将从文件中取得~!
                       
4.   memcpy函数
      复制映射存储区
      #include<string.h>
      void *memcpy( void * dest, const void * src, size_t n );
      参数:
      dest            待复制的映射存储区
      src              复制后的映射存储区
      n                  待复制的映射存储区的大小
      返回dest的首地址
     
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.     
      下面讨论POSIX的共享内存函数
           
      1、指定一个名字参数调用shm_open,以创建一个新的共享内存区对象或打开一个以存在的
            共享内存区对象。
      2、调用mmap把这个共享内存区映射到调用进程的地址空间。传递给shm_open的名字参数
            随后由希望共享该内存区的任何其他进程使用。
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>     
     
5.   打开或创建一个共享内存区
      #include<sys/mman.h>
      intshm_open( const char * name, int oflag, mode_t mode );
      参数:
                  name            共享区名称
                  oflag            标志位
                  mode            权限位
      成功返回ID,失败返回-1。
     
      oflag取值:      必须有O_RDONLY 或者 O_RDWR
                              还可以有O_CREAT,O_EXCL, O_TRUNC
      mode:只有指定O_CREAT标志时才有效
      shm_open返回整数描述符,随后可以用作mmap的第五个参数
     
6.   删除一个共享区

      #include<sys/mman.h>     
      intshm_unlink( const char * name );
      shm_unlink函数删除一个共享内存区对象的名字,删除一个名字仅仅防止后续的
      open,msq_open或sem_open调用取得成功。
     
7.   ftruncate 和 fstat 函数
      普通文件或共享内存区对象的大小都可以通过调用ftruncate修改。
     
      ftruncate:调整文件或共享内存区大小
      #include<unistd.h>
      intftruncate( int fd, off_t len );
      参数:
                  fd            描述符
                  len            修改的大小
      成功返回0,出错返回-1;
     
      当打开一个已存在的共享内存区对象时,我们可调用fstat来获取有关该对象的信息。
      //!> 其实所有的内存都是可以描述为文件的,只要是文件系统都是可以fstat获取信息的!
      #include<unistd.h>
      #include<sys/types.h>
      #include<sys/stat.h>
      int fstat(const char * filename, struct stat * buf );
      成功返回0,失败返回-1;
     
      但是要注意的是:
      对于普通的文件而言,fstat获得的结构体成员有12个,但是对于共享区而言,只有4个信息
      structstat
      {
            mode_t      st_mode;      //!> 模式
            uid_t            st_uid;            //!> 用户ID
            gid_t            st_gid;            //!> 全局ID
            off_t            st_size;      //!> 文件大小
      };
     
8.   共享内存区的写入和读出
            见CODE http://blog.sina.com.cn/s/blog_6dc9e4cf0100xeuq.html
           
     
     

推荐:Posix thread 多线程编程

====本文系本站原创,欢迎转载! 转载请注明出处:http://blog.csdn.net/yyplc==== 用Posix thread进行多线程设计,就不怕跨平台了,因为很多OS都兼容Posix thread,

Attention:打开相关代码区 1. 介绍      POSIX 共享内存和SYSTEMV的共享内存的框架是差不多的,细节有区别!       在前面的SYSTEM V的共享内存区我们已经知道共享内存区是最快的IPC形式!    

相关阅读排行


相关内容推荐

最新文章

×

×

请激活账号

为了能正常使用评论、编辑功能及以后陆续为用户提供的其他产品,请激活账号。

您的注册邮箱: 修改

重新发送激活邮件 进入我的邮箱

如果您没有收到激活邮件,请注意检查垃圾箱。