排列5走势图首页    注册   登录
排列5走势图 = way to explore
排列5走势图 是一个排列5走势图关于 分享和探索的地方
现在注册
已注册用户请  登录
排列5走势图  ›  程序员

百度百科 mmap 示例代码有误?

  •  
  •   b00tyhunt3r · 7 天前 · 369 次点击

    百度 mmap ()函数: baike.baidu.com/item/mmap/1322217?fr=aladdin

    下面是通过 mmap ()映射普通文件实现进程间的通信的范例,排列5走势图排列5走势图我 们 通过该范例来说明 mmap()实现共享内存的特点及注意事项。   范例包含两个子程序:map_normalfile1.c 及 map_normalfile2.c。编译两个程序,可执行文件分别为 map_normalfile1 及 map_normalfile2。两个程序通过命令行参数指定同一个文件来实现共享内存方式的进程间通信。map_normalfile1 试图打开命令行参数指定的一个普通文件,把该文件映射到进程的排列5走势图地址 空间,并对映射后的排列5走势图地址 空间进行写操作。map_normalfile2 把命令行参数指定的文件映射到进程排列5走势图地址 空间,然后对映射后的排列5走势图地址 空间执行读操作。这样,两个进程通过命令行参数指定同一个文件来实现共享内存方式的进程间通信。

    /*-------------map_normalfile1.c-----------*/
    #include<sys/mman.h>
    #include<sys/types.h>
    #include<fcntl.h>
    #include<string.h>
    #include<stdio.h>
    #include<unistd.h>
    #include <errno.h>
    typedef struct{
        char name[4];
        int age;
    }people;
    void main(int argc,char **argv)//map a normal file as shared mem:
    {
        int fd,i;
        people *p_map;
        char temp;
        fd = open(argv[1],O_CREAT|O_RDWR|O_TRUNC,00777);
        lseek(fd,sizeof(people)*5-1,SEEK_SET);
        write(fd,"",1);
        p_map=(people*)mmap(NULL,sizeof(people)*10,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
        if (p_map == (void *)-1)
        {
            fprintf(stderr, "mmap: %s\n", strerror(errno));
            return ;
        }
        close(fd);
        temp='a';
        for(i=0;i<10;i++)
        {
            temp+=1;
            (*(p_map+i)).name[1] = '\0';
            memcpy((*(p_map+i)).name,&temp,1);
            (*(p_map+i)).age=20+i;
        }
        printf("initializeover\n");
        sleep(10);
        munmap(p_map,sizeof(people)*10);
        printf("umapok\n");
    }
     
    /*-------------map_normalfile2.c-----------*/
    #include<sys/mman.h>
    #include<sys/types.h>
    #include<fcntl.h>
    #include<stdio.h>
    #include<unistd.h>
    #include <errno.h>
    typedef struct{
        char name[4];
        int age;
    }people;
    void main(int argc,char **argv)//map a normal file as shared mem:
    {
        int fd,i;
        people *p_map;
        fd=open(argv[1],O_CREAT|O_RDWR,00777);
        p_map=(people*)mmap(NULL,sizeof(people)*10,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
        if (p_map == (void *)-1)
        {
            fprintf(stderr, "mmap: %s\n", strerror(errno));
            return ;
        }
        for(i=0;i<10;i++)
        {
            printf("name:%s age%d;\n",(*(p_map+i)).name,(*(p_map+i)).age);
        }
        munmap(p_map,sizeof(people)*10);
    }
    
    

    代码解释: map_normalfile1.c 首先定义了一个 people 数据结构,(在这里采用数据结构的方式是因为,共享内存区的数据往往是有固定格式的,这由通信的各个进程决定,采用结构的方式有普遍代表性)。map_normfile1 首先打开或创建一个文件,并把文件的长度设置为 5 个 people 结构大小。然后从 mmap()的返回排列5走势图地址 开始,设置了 10 个 people 结构。然后,进程睡眠 10 秒钟,等待其他进程映射同一个文件,最后解除映射。    map_normfile2.c 只是简单的映射一个文件,并以 people 数据结构的格式从 mmap()返回的排列5走势图地址 处读取 10 个 people 结构,并输出读取的值,然后解除映射。   分别把两个程序编译成可执行文件 map_normalfile1 和 map_normalfile2 后,在一个终端上先运行./map_normalfile1 /tmp/test_shm,程序输出结果如下:    initialize over    umap ok   在 map_normalfile1 输出 initialize over 之后,输出 umap ok 之前,在另一个终端上运行 map_normalfile2 /tmp/test_shm,将会产生如下输出(为了节省空间,输出结果为稍作整理后的结果):

      name: b age 20;
      name: c age 21;
      name: d age 22;
      name: e age 23;
      name: f age 24;
      name: g age 25;
      name: h age 26;
      name: I age 27;
      name: j age 28;
      name: k age 29;
    

    在 map_normalfile1 输出 umap ok 后,运行 map_normalfile2 则输出如下结果:

      name: b age 20;
      name: c age 21;
      name: d age 22;
      name: e age 23;
      name: f age 24; 
      name: age 0;
      name: age 0;
      name: age 0;
      name: age 0;
      name: age 0;
    

    ===================以上引用自百度百科 mmap 页面=====================================

    本小白有三个疑问 1 )截断文件之后再使用 lseek 有意义吗?

    fd = open(argv[1],O_CREAT|O_RDWR|O_TRUNC,00777);
        lseek(fd,sizeof(people)*5-1,SEEK_SET);
        write(fd,"",1);
    

    按照排列5走势图我 的理解 open 添附 O_TRUNC 参数形成截断后,文件长度不是被截为 0 了吗? 为什么这个时候还可以接着使用 lseek 重新定位光标呢

    2 )还是这句 lseek(fd,sizeof(people)*5-1,SEEK_SET); 其中 sizeof(people)*5-1 那个-1 起什么作用?

    3 ) file1.c 在最后执行 munmap 之后,讲道理此时 file1 映射到内存中的 fd 应该已经被消除了, 但运行 file2 仍然可以得到输出。且输出总是:

        name: b age 20;
        name: c age 21;
        name: d age 22;
        name: e age 23;
        name: f age 24;
        name: g age 25;
        name: h age 26;
        name: I age 27;
        name: j age 28;
        name: k age 29;
        ```
        并不能得到百科中记载的第二种结果(其实根本不明白为什么会得到这个结果
         ```
        name: b age 20;
        name: c age 21;
        name: d age 22;
        name: e age 23;
        name: f age 24; 
        name: age 0;
        name: age 0;
        name: age 0;
        name: age 0;
        name: age 0;
    

    排列5走势图我 理解是 file1 munmap 后,file2 再将文件映射进内存读取,但相同内存区域已经被 munmap 了,难道 file2 不是该什么都读取不出来吗?

    问题有点多,但愿都讲清楚了,谢谢大佬解答。

    1 回复  |  直到 2019-10-09 23:03:30 +08:00
        1
    b00tyhunt3r   7 天前 via iPhone
    哈哈 系统编程果然在 v2 没市场🤤
    排列5走势图关于   ·   FAQ   ·   API   ·   排列5走势图排列5走势图我 们 的愿景   ·   广告投放   ·   感谢   ·   实用小排列5走势图工具   ·   1375 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 23ms · UTC 17:27 · PVG 01:27 · LAX 10:27 · JFK 13:27
    ♥ Do have faith in what you're doing.