您的位置:首页 > 其它

进程通信----共享内存以及mmap函数实现共享内存

2016-10-25 14:02 537 查看
进程间通信----共享内存
最底层的原理:让不同的进程看到相同的物理资源(将不同进程的 虚拟内存地址 映射到 同一块相同的物理内存上)

对共享内存的操作没有进行检测 PV操作需要用户自己来完成

对共享内存的操作 执行向上取整 按页申请 (如一页不够就用两页 但用户可以使用的 还是他自己申请的那么大 如申请4097B 实际申请8kB 但用户只能用4097B【一页4096B】)

生命周期随内核 不随进程(进程退出 进程不主动删除 共享内存  则共享内存还在)




1、用到的函数
int shmget(key_t key, size_t size, int shmflg);                                                          【创建共享内存 | 获得共享内存】

                    key: 由ftok()函数返回的标识符
                    size:字节为单位所需的共享内存容量
                    shmflg:IPC_CREAT
                                  IPC_EXCL
                                   IPC_CREAT|IPC_EXCL
                                    IPC_CREAT|IPC_EXCL|0666
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

          [ 控制共享内存]
          shm_id:shmget返回的共享内存标识符
          cmd:
                    IPC_STAT:把shmid_ds结构中的数据设置为共享内存的当前关联值,即把共享内存的当前设置值保存在shmid_ds中。
                    IPC_SET:如果进程有足够权限,把共享内存的当前关联值设置为shmid_ds结构中给出的值
                    IPC_RMID :删除共享内存

void *shmat(int shmid, const void *shmaddr, int shmflg);  

          at是attach
          [挂接*(将创建的共享内存与进程的虚拟内存相关联 让进程可以向操作malloc的空间一样操作共享内存) 使得ipcs -m 中nattch选项加1]
返回值可以理解为(当成)malloc申请的资源地址 【其实两个是完全不一样的】  
     成功返回指向共享内存的指针,失败返回-1
const void *shmaddr在哪开辟  可以让系统自己决定(NULL)
int shmflg 开辟的属性读写权限 可以让系统自己决定(NULL)
 int shmdt(const void *shmaddr);                

      dt是detach[删除挂接 使得ipcs -m 中nattch选项减去1]
注意: 对共享内存的操作没有进行 先后顺序检测 任何进程都可以操作 要实现互斥 就要自己用信号量进行加锁的 PV操作
2、查看的命令:
ipcs -m
写一个监视的脚本
while :; do ipcs -m|grep "root"; sleep 1; echo "###########"; done




3、练习程序
------------------------------shm.h--------------------------------------
 = 'X';
            i++;
        }
        buf[4095] = '\0';
        sleep(3);
        delete_shm(buf);
        sleep(3);
    }
    else
    {
        // father
        sleep(4);
        char* buf = at_shm(shm_id);
        sleep(2);
        printf("%s\n", buf);
        delete_shm(buf);
        sleep(2);
        //waitpid(id, NULL, 0);
        wait(NULL);
        rm_shm(shm_id);
    }
    return 0;
}
-------------------------------------运行截图---------------------------------


监视脚本:[root@localhost bozi]#  while :; do ipcs -m | grep root; sleep 1;echo "##########";done
0xd200649e 1802257    root       666        4096       0                       
##########
0xd200649e 1802257    root       666        4096       0                       
##########
0xd200649e 1802257    root       666        4096       1                       
##########
0xd200649e 1802257    root       666        4096       1                       
##########
0xd200649e 1802257    root       666        4096       2                       
##########
0xd200649e 1802257    root       666        4096       2                       
##########
0xd200649e 1802257    root       666        4096       1                       
##########
0xd200649e 1802257    root       666        4096       1                       
##########
0xd200649e 1802257    root       666        4096       1                       
##########
0xd200649e 1802257    root       666        4096       0 首先由父进程创建共享内存,父进程创建子进程,父子进程都关联了共享内存,关联的个数由0变为2,因父进程休息时间短,取消关联,关联个数变为1,最后子进程也取消关联,关联个数变为0,最后将共享内存销毁。
 
4、mmap函数
http://baike.baidu.com/link?url=GW7f3zIQ2_5TJEhowcqp8ABwpt45EqZaEZIJpfRxRsvjoXne8790ebjZ4sDQ6g-J2DFqy3gk3tnI6UsNoUIRwq
mmap将一个文件或者其他对象映射进内存。mmap也可以实现共享内存。mmap函数调用使得进程之间通过映射同一个文件实现共享内存。文件被映射到进程地址空间后,进程可以像读写内存一样对文件进行操作。
函数:
[code=cpp;toolbar:false">       #include <sys/mman.h>
       void *mmap(void *addr, size_t length, int prot, int flags,  int fd, off_t offset);
       void *mmap64(void *addr, size_t length, int prot, int flags,int fd, off64_t offset);
       int munmap(void *addr, size_t length);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: