关闭

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

标签: 多线程linux编程存储structsystem
1790人阅读 评论(2) 收藏 举报
分类:

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
      
   
   

3
0
查看评论

linux--posix多线程编程----第一篇

一   线程创建 1.1 线程与进程 相对进程而言,线程是一个更加接近于执行体的概念,它可以与同进程中的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。在串行程序基础上引入线程和进程是为了提高程序的并发度,从而提高程序运行效率和响应时间。 线程...
  • u010358881
  • u010358881
  • 2015-09-25 14:14
  • 590

C++之多线程(POSIX多线程实例)

转载自:http://blog.csdn.net/hitwengqi/article/details/8015646 1.进程同时创建5个线程,各自调用同一个函数 #include #include //多线程相关操作头文件,可移植众多平台 using namespace std; #defi...
  • liuweiyuxiang
  • liuweiyuxiang
  • 2016-06-14 15:39
  • 863

使用POSIX Threads进行多线程编程(一)——pthread基本知识

使用POSIX Threads进行多线程编程——pthread基本知识说明: 本文是翻译自《MultiThreaded-Programming-With-POSIX》,作者Guy Kerens。本文预计翻译三章,主要涉及多线程基本知识、互斥量(锁)和条件变量,一是因为这已经能够引导读者入门,二是因为...
  • ai552368625
  • ai552368625
  • 2016-08-01 22:01
  • 817

Linux环境编程之共享内存区(二):Posix共享内存区

现在将共享内存区的概念扩展到将无亲缘关系进程间共享的内存区包括在内。Posix提供了两种在无亲缘关系进程间共享内存区的方法: 1、内存映射文件:由open函数打开,由mmap函数把得到的描述符映射到当前进程地址空间中的一个文件。(上一节就是这种技术) 2、共享内存区对象:由shm_open打开一...
  • To_Be_IT_1
  • To_Be_IT_1
  • 2014-06-08 15:49
  • 938

《posix多线程编程》笔记(六)

26 多线程和信号
  • yxtxiaotian
  • yxtxiaotian
  • 2017-02-03 16:12
  • 82

Posix共享内存区

1、概述  Posix提供了两种在无亲缘关系进程间共享内存区的方法: (1)内存映射文件:先有open函数打开,然后调用mmap函数把得到的描述符映射到当前进程地址空间中的一个文件(上一篇笔记所用到的就是)。 (2)共享内存区对象:先有shm_open打开一个Posix IPC名字(也可以是文件系统...
  • wangwenwen
  • wangwenwen
  • 2014-10-26 11:57
  • 572

Linux系统下的多线程遵循POSIX线程接口

Linux系统下的多线程遵循POSIX线程接口,称为pthread。编写Linux下的多线程程 序,需要使用头文件pthread.h,连接时需要使用库libpthread.a。顺便说一下,Linux下pthread的实现是通过系统调用 clone()来实现的。clone()是Linux所特有的...
  • laobai1015
  • laobai1015
  • 2016-12-14 15:29
  • 500

Linux下C语言多线程编程

一、多线程的创建 1、Linux系统下的多线程遵循POSIX线程接口,称为pthread。编写Linux下的多线程程序,需要使用头文件pthread.h,连 接时需要使用库libpthread.a。因此,后面的编译必须在选项中加入 -lpthread 选项,否则提...
  • edonlii
  • edonlii
  • 2014-07-18 09:50
  • 1648

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

注意:以下编译加上  -lrt 例如:gcc  -o server  server.c  -lrt 1.创建一个共享内存区的例子 #include #include #include #include int mai...
  • shanshanpt
  • shanshanpt
  • 2012-03-21 06:48
  • 1101

Posix共享内存区基础知识

1. 基本信息 共享内存区是可用IPC中最快的,一旦其映射到共享它的进程的地址空间,进程间的数据场地就不再涉及内核(无需系统调用传递数据)。 普通的客户-服务程序涉及的步骤: 服务端读文件—》服务端写入IPC—》客户端读IPC—》客户端写入文件 而使用共享内存: 服务端将文件读入共享内存对象—》客户...
  • zhoushuaiyin
  • zhoushuaiyin
  • 2014-12-22 23:08
  • 297
    个人资料
    • 访问:635442次
    • 积分:7123
    • 等级:
    • 排名:第3804名
    • 原创:182篇
    • 转载:36篇
    • 译文:0篇
    • 评论:84条
    博客专栏