在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
mmap将一个文件或者其它对象映射进内存。文件被映射到多个页上,如果文件的大小不是所有页的大小之和, 最后一个页不被使用的空间将会清零。mmap在用户空间映射调用系统中作用很大。 条件mmap()必须以PAGE_SIZE为单位进行映射,而内存也只能以页为单位进行映射,若要映射非PAGE_SIZE整数倍 的地址范围,要先进行内存对齐,强行以PAGE_SIZE的倍数大小进行映射。 设备操作mmap操作提供了一种机制,让用户程序直接访问设备内存,这种机制,相比较在用户空间和内核空间 互相拷贝数据,效率更高。在要求高性能的应用中比较常用。mmap映射内存必须是页面大小的整数倍, 面向流的设备不能进行mmap,mmap的实现和硬件有关。
以下是一个把普遍文件映射到用户空间的内存区域的示意图。
系统调用mmap()系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后, 进程可以像访问普通内存一样对文件进行访问,不必再调用read(),write()等操作。 普通文件的访问方式,进程可以像读写内存一样对普通文件的操作。而Posix或System V的共享内存IPC则 纯粹用于共享目的,当然mmap()实现共享内存也是其主要应用之一。 指定flags参数中的MAP_ANON,表明进行的是匿名映射(不涉及具体的文件名,避免了文件的创建及打开, 很显然只能用于具有亲缘关系的进程间通信)。len是映射到调用进程地址空间的字节数,它从被映射文件 开头offset个字节开始算起。prot 参数指定共享内存的访问权限。可取如下几个值的或:PROT_READ(可读) , PROT_WRITE (可写), PROT_EXEC (可执行), PROT_NONE(不可访问)。flags由以下几个常值指定: MAP_SHARED , MAP_PRIVATE , MAP_FIXED,其中,MAP_SHARED , MAP_PRIVATE必选其一, 而MAP_FIXED则不推荐使用。offset参数一般设为0,表示从文件头开始映射。参数addr指定文件应被映射到 进程空间的起始地址,一般被指定一个空指针,此时选择起始地址的任务留给内核来完成。函数的返回值为最后 文件映射到进程空间的地址,进程可直接操作起始地址为该值的有效地址。这里不再详细介绍mmap()的参数, 读者可参考mmap()手册页获得进一步的信息。 然后再调用mmap();典型调用代码如下: 通过mmap()实现共享内存的通信方式有许多特点和要注意的地方,我们将在范例中进行具体说明。 在父进程中先调用mmap(),然后调用fork()。那么在调用fork()之后,子进程继承父进程匿名映射后的地址空间, 同样也继承mmap()返回的地址,这样,父子进程就可以通过映射区域进行通信了。注意,这里不是一般的继承关系。 一般来说,子进程单独维护从父进程继承下来的一些变量。而mmap()返回的地址,却由父子进程共同维护。 只要设置相应的标志即可,参见范例2。 当映射关系解除后,对原来映射地址的访问将导致段错误发生。 头文件:#include <unistd.h> #include <sys/mman.h> 定义函数:void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offsize); 函数说明:mmap()用来将某个文件内容映射到内存中,对该内存区域的存取即是直接对该文件内容的读写。 参数说明:
返回值:若映射成功则返回映射区的内存起始地址,否则返回MAP_FAILED(-1),错误原因存于errno 中。 错误代码:
#include <unistd.h> #include <sys/mman.h> 当进程结束或利用exec 相关函数来执行其他程序时,映射内存会自动解除,但关闭对应的文件描述词时不会解除映射。 范例:利用mmap()来读取/etc/passwd 文件内容。
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/mman.h> void main(){ int fd; void *start; struct stat sb; fd = open("/etc/passwd", O_RDONLY); /*打开/etc/passwd */ fstat(fd, &sb); /* 取得文件大小 */ start = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if(start == MAP_FAILED) /* 判断是否映射成功 */ return; printf("%s", start); munmap(start, sb.st_size); /* 解除映射 */ closed(fd); }执行结果: root : x : 0 : root : /root : /bin/bash bin : x : 1 : 1 : bin : /bin : daemon : x : 2 : 2 :daemon : /sbin adm : x : 3 : 4 : adm : /var/adm : lp : x :4 :7 : lp : /var/spool/lpd : sync : x : 5 : 0 : sync : /sbin : bin/sync : shutdown : x : 6 : 0 : shutdown : /sbin : /sbin/shutdown halt : x : 7 : 0 : halt : /sbin : /sbin/halt mail : x : 8 : 12 : mail : /var/spool/mail : news : x :9 :13 : news : /var/spool/news : uucp : x :10 :14 : uucp : /var/spool/uucp : operator : x : 11 : 0 :operator : /root: games : x : 12 :100 : games :/usr/games: gopher : x : 13 : 30 : gopher : /usr/lib/gopher-data: ftp : x : 14 : 50 : FTP User : /home/ftp: nobody : x :99: 99: Nobody : /: xfs :x :100 :101 : X Font Server : /etc/xll/fs : /bin/false gdm : x : 42 :42 : : /home/gdm: /bin/bash kids : x : 500 :500 :/home/kids : /bin/bash 参考: http://baike.baidu.com/link?url=tcSRXGB3PlbSKmvNzUNrZQ4aa_dMqOASGg_m9yANgdIYZnmbfOSzx8celjRHULiSei2vQrsPAMNwQv428wkHWa http://c.biancheng.net/cpp/html/139.html |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论