Linux系统编程--第四章 高级文件IO

散布/聚集IO:   在单个系统调用中同时对多个缓冲区进行读取或者写入操作,适合聚集不同数据结构进行统一的IO操作。

epoll:poll() 和 select() 的改进版本,在一个程序需要处理数百个文件描述符的时候很有用

内存文件映射IO:将文件映射到内存,可以通过简单的内存管理方式来处理文件

文件IO提示: 允许进程将文件IO使用上的一些提示信息提供给内核,能提升IO性能

异步IO :允许进程发出多个IO请求而且不必等待其完成,适用于不使用线程情况下处理重负载IO的情况

散布/聚集IO(向量IO):

#include <sys/uio.h>
struct iovec {
void *iov_base;
size_t iov_len;
};
ssize_t readv (int fd, const struct iovec *iov, int count);
ssize_t writev (int fd, const struct iovec *iov, int count);

函数描述:按顺序读取或者写入每个segment(代表一个iovec 结构体),返回总共读取或者写入的字节个数。

Event Poll接口:

https://blog.csdn.net/weixin_38812277/article/details/90634146

存储映射:

文件内存映射:

通常文件的数据已经存在于内核的页高速缓存中,通过文件内存映射可以将一个线性区映射到该缓存,也即映射到某个文件的一部分。再通过透明的映射机制写入内存,用户进程可以直接通过对线性区的内存访问来访问文件数据。【这种操作绕过了内核,当取消映射的时候缓存中的修改并没有写入文件,要写入文件必须使用msync()来同步】

共享型(MAP_SHARED):线性区上的任何操作都会修改磁盘上的文件,如果进程对映射区进行修改,对其他映射到该文件的进程都是可见的。

私有型(MAP_PRIVATE):一般当创建的映射只为读取文件的时候,使用此种映射。对这种映射进行写操作,不会修改磁盘文件,而是停止映射该文件中的页,重新映射到新的一页,并对于其他进程不可见。

#include <sys/mman.h>
void * mmap (void *addr, size_t len, int prot, int flags, int fd, off_t offset);
int munmap (void *addr, size_t len);

int mprotect (const void *addr, size_t len, int prot);
int msync (void *addr, size_t len, int flags);
int madvise (void *addr, size_t len, int advice);/给内核提供mmap的实现建议,实现优化/

【注】页是内存中国具有不同权限和行为的最小单位。

匿名文件映射:(对于较大的内存分配,并不使用堆,而是使用匿名内存映射)

一个匿名内存映射只是一块已经使用0初始化的大内存块,以供用户使用。可以把它想象成单独为某次分配而使用的堆,但并不是堆,因此不会在堆内产生碎片。

优点:无需关心碎片,匿名映射大小可以调整,可以设置权限,还可以像普通映射一样接受建议,每个分配存在于独立的内存映射。

缺点(相对于堆来说):页面的证书倍,存在浪费;相对于从堆中分配,要复杂一些。

glibc中malloc函数使用堆来满足小内存的分配(使用系统调用sbrk或者brk),使用匿名内存映射来满足大内存分配(mmap)。

实现方法1    使用MAP_ANONYMOUS标志

p= mmap (NULL, /* do not care where */
512 * 1024, /* 512 KB */
PROT_READ | PROT_WRITE, /* read/write */
MAP_ANONYMOUS | MAP_PRIVATE, /*anonymous, private */
-1, /* fd (ignored) */
0); /* offset (ignored) */

ret = munmap (p, 512 * 1024);

通过匿名映射进行分配的一个好处是所有的页都已经用0初始化(可以将该内存块看成是一个“文件”,一切皆文件),由于内核使用写时复制机制将内存映射到了一个全0的页面上,因而避免使用额外的开销。同时也没有必要对获得的内存使用memset初始化。事实上calloc比使用malloc再使用memset效果好的原因。

实现方法2    :  映射到/dev/zero文件上(此设备文件提供了和匿名内存相同的语义)

fd = open (”/dev/zero”, O_RDWR);
p = mmap (NULL, /* do not care where */
getpagesize (), /* map one page */
PROT_READ | PROT_WRITE, /* map read/write */
MAP_PRIVATE, /* private mapping */
fd, /* map /dev/zero */
0); /* no offset */

【映射之后可以关掉fd 即close(fd),匿名存储映射同时可以用来给父子进程通信】

普通文件IO提示:

异步IO:用户发起IO操作,直接返回,内核负责将数据复制到用户内存,并通知进程。

执行异步IO需要内核底层的支持。

猜你喜欢

转载自blog.csdn.net/weixin_38812277/article/details/93318049