用户层调用一个模块,叫MMAP。memory map socket
会给我们申请一块内存空间,这块空间叫:映射内存。
但是要用mmap,先要要求本地磁盘有一个文件:映射文件。例如testdate
映射内存大小与映射文件一致。内容也是一致的。映射可以理解为拷贝。
通过mmap,将映射文件,映射到映射内存里。
有两种方式来进行映射:私有、共享。通过两种方式的任意一种,来映射到映射内存当中。
将映射文件原封不动的拷贝一份,给映射内存。单纯的拷贝,采用简单的拷贝。
互不影响了,互相独立。某一份修改,不会影响其他内容。
sync同步机制。
无论对其中的哪一份修改,都会全部修改。同步给数据块。
A做mmap映射,b也是一样的操作,都进行sync共享映射。
因此,两个映射内存和映射文件,三者都是相同的,这就是进程间通信。
void * ptr = mmap(void * ptr, int size, int prot, int how, int fd, ssize_t offset);六个参数
munmap(void* ptr, int size)用于销毁释放映射内存。
对测试文件进行共享映射,映射成功后修改映射内存,实现同步修改映射文件。
将mapfile文件中的前四个字节(int*)的内容变为1234,而字符串1234的十六进制表示就是ptr[0]。
可以利用od -tcx 来拆分文本。
一个用户,想去篡改文件,一个重要的系统文件,首先对文件要有权限。
other用户,对这个文件只有最低权限,-rw-rw-r--,仅有只读权限。
那么,通过mmap共享映射系统文件,然后修改共享内存,能否实现其他用户修改系统文件?
如果能成,系统就无安全可言了,系统权限变得没有意义,权限保护形同虚设。
mmap不是看用户是谁,而是看如何打开。
如果一个用户想对一个文件进行映射,映射的权限参考打开权限。
就是看你是只读还是写的方式打开的。
假设写端的映射内存是结构体。
对于映射文件,做一个空文件拓展。
写端每隔一秒,编辑一次映射内存的结构体。
修改之后马上同步至映射文件和读端映射内存。
这样读端就间隔一秒读出。
就是在写端设置空文件,然后通过截断的方式拓展文件。
然后以mmap形式进行通信,对于结构体中的id每隔一秒进行一次修改。
读端不需要截断,并且不需要赋初值。
而例如id从0开始,读的结果也不一定是从0开始,因为:映射文件大小为一个结构体大小,所以不能缓存多个数据包。
一边写一边读。
unlink函数:使用之后,删除映射文件。
例如用户要定义一个buffer缓冲区,然后读取一个文件(其实在磁盘中)
首先通过探针寻址的方式,硬盘外部有一个DMA快速缓存设备,用来读取缓存。
DMA读取磁盘里文件内容,读取之后,进行第一次拷贝:DMA中拷贝至内核缓冲区。
第二次拷贝:内核缓冲区拷贝至buffer的用户缓冲区。用户read磁盘的文件过程。
mmap零拷贝,相比传统读取数据,速度更快,开销更小。
mmap没有内核缓冲区到用户缓冲区的过程的,mmap使用之后,直接是内核缓冲区向内核缓冲区进行映射。节省了开销。比较受欢迎。
读取网络数据用的也多。
磁盘位置就变成了网卡,网络设备。
还是DMA,然后就变成了socket缓冲区。
处理大文件,mmap合适。
大文件可能存不下,不可能一次读到缓冲区里,可以采用:分段映射。
一次映射文件的一部分。block分块,每次映射一块。
采用mmap偏移映射,进行分段映射。
void* ptr=mmap(NULL, 4096, READ, PRIVATE, int fd, 0);第一次是0,下一次就是4096往上加了。
如果觉得太慢,可以用多线程。