您的位置:首页 > 运维架构 > Linux

Linux进程间通信 -- mmap函数的使用

2016-02-11 15:29 369 查看

mmap/munmap函数

函数原型

#include <sys/mman.h>

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
int munmap(void *addr, size_t length);


函数功能

mmap可以把磁盘文件的一部分直接映射到内存,这样文件中的位置直接就有对应的内存 地址,对文件的读写可以直接用指针来做而不需要read/write函数。

munmap()用来取消参数start所指的映射内存起始地址,参数length则是欲取消的内存大小。当进程结束或利用exec相关函数来执行其他程序时,映射内存会自动解除,但关闭对应的文件描述符时不会解除映射。

mmap参数说明

addr


mmap函数中如果
addr
参数为NULL,内核会自己在进程地址空间中选择合适的地址建立映射。如果addr不是NULL,则给内核一个提示,应该从什么地址开始映射,内核会选择addr之上的某个合适的地址开始映射。建立映射后,真正的映射首地址通过返回值可以得到。

len


len参数是需 要映射的那一部分文件的长度。

off


off参数是从文件的什么位置开始映射,必须是页大小的整数倍(在32位体系统结构上通常是4K)。

filedes


filedes
是代表该文件的描述符。

prot


prot
参数有四种取值:

PROT_EXEC
表示映射的这一段可执行,例如映射共享库

PROT_READ
表示映射的这一段可读

PROT_WRITE
表示映射的这一段可写

PROT_NONE
表示映射的这一段不可访问

flag


flag参数有很多种取值,常用的两种如下,其它取值可查看mmap(2):

MAP_SHARED
多个进程对同一个文件的映射是共享的,一个进程对映射的内存做了修 改,另一个进程也会看到这种变化。

MAP_PRIVATE
多个进程对同一个文件的映射不是共享的,一个进程对映射的内存做了修改,另一个进程并不会看到这种变化,也不会真的写到文件中去。

函数返回值

如果
mmap
成功则返回映射首地址,如果出错则返回常数
MAP_FAILED


当进程终止时,该进程的映射内存会自动解除,也可以调用
munmap
解除映射。

munmap
成功返回0,出错返回-1。

mmap
操作修改hello文件:

yu@ubuntu:~/Linux/211$ vi hello
yu@ubuntu:~/Linux/211$ cat hello
hello
yu@ubuntu:~/Linux/211$ od -tx1 -tc hello
0000000  68  65  6c  6c  6f  0a
h   e   l   l   o  \n
0000006


mmap.c源码:

/*mmap.c*/
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <stdio.h>

int main()
{
int *p;
int fd = open("hello", O_RDWR);
if(fd < 0){
perror("open hello");
exit(1);
}
/* 将文件映射至进程的地址空间 */
p = mmap(NULL, 6, PROT_WRITE, MAP_SHARED, fd, 0);
if(p == MAP_FAILED){
perror("mmap");
exit(1);
}
/* 映射完后, 关闭文件也可以操纵内存 */
close(fd);
printf("%c\n", p[0]);
p[0] = 'A';
p[1] = '\0';
printf("%c\n", p[0]);
munmap(p, 6);

return 0;
}


编译及执行测试:

yu@ubuntu:~/Linux/211$ vi hello
yu@ubuntu:~/Linux/211$ cat hello
hello
yu@ubuntu:~/Linux/211$ gcc mmap.c
yu@ubuntu:~/Linux/211$ ./a.out
h
A
yu@ubuntu:~/Linux/211$ cat hello
A
yu@ubuntu:~/Linux/211$ od -tx1 -tc hello
0000000  41  00  00  00  00  00  0a
A  \0  \0  \0  \0  \0  \n
0000007


如上所示,成功修改了hello文件。

注意事项:

* 用于进程间通信时,一般设计成结构体,来传输通信的数据

* 进程间通信的文件,应该设计成临时文件

* 当报总线错误时,优先查看共享文件是否有存储空间

具体通信案例请见(Linux进程共享通信 – mmap实现):

/article/10907690.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: