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

来源:互联网 发布:javascript基础教程 编辑:程序博客网 时间:2024/05/21 21:41

Attention:打开相关代码区


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       复制后的映射存储区
           待复制的映射存储区的大小
   返回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
      
   
   

原创粉丝点击