UNIX环境高级编程读书笔记(十二)—高级IO (4)

四、存储映射I/O

       存储映射I/O使一个磁盘文件与存储空间中的一个缓冲区相映射。于是当从缓冲区中取数据,就相当于读文件中的相应字节。与此类似,将数据存入缓冲区,则相应字节自动地写入文件。这样就可以在不使用read和write的情况下执行I/O。

 

6.

名称::

mmap

功能:

把I/O文件映射到一个存储区域中

头文件:

#include <sys/mman.h>

函数原形:

void *mmap(void *addr,size_t len,int prot,int flag,int filedes,off_t off);

参数:

addr      指向映射存储区的起始地址

len       映射的字节

prot      对映射存储区的保护要求

flag      flag标志位

filedes    要被映射文件的描述符

off       要映射字节在文件中的起始偏移量

返回值:

若成功则返回映射区的起始地址,若出错则返回MAP_FAILED

 addr参数用于指定映射存储区的起始地址。通常将其设置为0,这表示由系统选择该映射区的起始地址。

       filedes指要被映射文件的描述符。在映射该文件到一个地址空间之前,先要打开该文件。len是映射的字节数。

       off是要映射字节在文件中的起始偏移量。通常将其设置为0。

       prot参数说明对映射存储区的保护要求。可将prot参数指定为PROT_NONE,或者是PROT_READ(映射区可读),PROT_WRITE(映射区可写),PROT_EXEC(映射区可执行)任意组合的按位或,也可以是PROT_NONE(映射区不可访问)。对指定映射存储区的保护要求不能超过文件open模式访问权限。

       flag参数影响映射区的多种属性:    

MAP_FIXED 返回值必须等于addr.因为这不利于可移植性,所以不鼓励使用此标志。

MAP_SHARED 这一标志说明了本进程对映射区所进行的存储操作的配置。此标志指定存储操作修改映射文件。

MAP_PRIVATE 本标志导致对映射区建立一个该映射文件的一个私有副本。所有后来对该映射区的引用都是引用该副本,而不是原始文件。

要注意的是必须指定MAP_FIXED或MAP_PRIVATE标志其中的一个,指定前者是对存储映射文件本身的一个操作,而后者是对其副本进行操作。

 

7.

名称::

memcpy

功能:

复制映射存储区

头文件:

#include <string.h>

函数原形:

void *memcpy(void *dest,const void *src,size_t n);

参数:

dest       待复制的映射存储区

src        复制后的映射存储区

n          待复制的映射存储区的大小

返回值:

返回dest的首地址

 memcpy拷贝n个字节从dest到src。

 

8.

名称::

munmap

功能:

解除存储映射

头文件:

#include <sys/mman.h>

函数原形:

int munmap(caddr_t addr,size_t len);

参数:

addr      指向映射存储区的起始地址

len       映射的字节

返回值:

若成功则返回0,若出错则返回-1

  进程终止时,或调用了munmap之后,存储映射区就被自动解除映射。关闭文件描述符filedes并不解除映射区。

       munmap不会影响被映射的对象。

 

下面就是利用上面的两个函数实现的第二个版本的cp命令。

/*12_5.c*/

#include <unistd.h>

#include <fcntl.h>

#include <sys/mman.h>

#include <sys/stat.h>

#include <sys/types.h>

 

int main(int argc,char *argv[])

{

int fdin,fdout;

void *arc,dst;

struct stat statbuf;

 

if(argc!=3)

{

    printf(“please input two file!\n”);

    exit(1);

}

if((fdin=open(argv[1],O_RDONLY))<0) /*打开原文件*/

    perror(argv[1]);

if((fdout=open(argv[2],O_RDWR|O_CREAT|O_TRUNC))<0)/*创建并打开目标文件*/

    perror(argv[2]);

 

if(fstat(fdin,&statbuf)<0) /*获得文件大小信息*/

    printf(“fstat error”);

 

if(lseek(fdout,statbuf.st_size-1,SEEK_SET)==-1)/*初始化输出映射存储区*/

    printf(“lseek error”);

if(write(fdout,””1)!=1)

    printf(“write error”);

 

if((src=mmap(0,statbuf.st_size,PROT_READ,MAP_SHARED,fdin,0))==MAP_FAILED)

    /*映射原文件到输入的映射存储区*/

    printf(“mmap error);

if((dst=mmap(0,statbuf.st_size,PROT_READ|PROT_WRITE,MAP_SHARED,fdout,0)) ==MAP_FAILED) /*映射目标文件到输出的映射存储区*/

    printf(“mmap error);

memcpy(dst,src,statbuf.st_size);/*复制映射存储区*/

munmap(src,statbuf.st_size); /*解除输入映射*/

munmap(dst,statbuf.st_size); /*解除输出映射*/

close(fdin);

close(fdout);

}

 

9.

名称::

mprotect

功能:

改变映射存储区的权限

头文件:

#include <sys/mman.h>

函数原形:

int mprotect(void *addr,size_t len,int prot);

参数:

addr      指向映射存储区的起始地址

len       映射的字节

prot      对映射存储区的保护要求

返回值:

若成功则返回0,若出错则返回-1

       mprotect可以更改一个现存映射存储区的权限。

 

10.

名称::

msync

功能:

同步文件到存储器

头文件:

#include <sys/mman.h>

函数原形:

int msync(void *addr,size_t len,int flags);

参数:

addr      指向映射存储区的起始地址

len       映射的字节

prot      flags

返回值:

若成功则返回0,若出错则返回-1

       如果在共享映射区中的页已被修改,那么我们可以调用msync将该页冲洗到映射的文件中。flags参数使我们对如何冲洗存储区有某种程度的控制。我们可以指定MS_ASYNC标志以简被写页的调度。如果我们希望在返回之前等待写操作的完成,则可指定MS_SYNC标志。一定要制定MSASYNC或MS_SYNC中的一个。MS_INVALIDATE是一个可选的标志,使用它会通知操作系统丢弃与底层存储器没有同步的任何页。


你可能感兴趣的:(linux,读书笔记,apue)