python多进程读取文件,php确保多个进程同时写入一个文件

  python多进程读取文件,php确保多个进程同时写入一个文件

  内容1。mmap使用2。mmap阅读3。mmap写作4。mmap多进程写作5。笔记

  Mmap通过内存映射的方式将磁盘上的文件直接映射到内存(确切的说是虚拟内存),不需要任何额外的空间。内存映射区的修改可以和磁盘文件保持同步,所以mmap的读写速度非常快。

  使用mmap时应注意以下两点:

  仅支持linux系统

  mmap映射区域大小必须是物理页面大小的整数倍(在32位系统中通常为4k字节)。

  1.mmap使用# includes ys/mman . h # includes fcntl . h//打开映射void * mmap (void * start,size _ tlength,intprot,intflags,intfd,off _ toff set);//关闭映射intmunmap (void * start,size _ t length);功能参数含义:

  *start:指要映射的内存的起始地址,通常设置为NULL,表示映射成功后系统会自动选择地址并返回。

  Length:表示有多少文件被映射到内存中,也就是映射区域的长度。

  Prot:映射区域的保护模式不能与文件打开模式冲突。Or组合(“”)可以以下列一种或多种方式使用。

  PROT执行:映射区域可以被执行。PROT_READ:映射区域可以读取。PROT_WRITE:可以写映射区域。PROT _无:映射区域不能访问标志:影响映射区域的各种特征,指定映射对象的类型,映射选项以及映射页面是否可以共享。调用mmap()时必须指定MAP_SHARED或MAP_PRIVATE。标志可以是下列一个或多个值:

  MAP_FIXED:如果由参数start指示的地址不能被成功映射,映射将被放弃,并且地址将不会被纠正。通常不鼓励设置MAP_SHARED:写入映射区域的数据将被复制回文件,并由映射该文件的其他进程共享。与映射此对象的所有其他进程共享映射空间。写入共享区域相当于输出到文件。在调用msync()或munmap()之前,文件实际上不会被更新。MAP_PRIVATE:写入映射区域会产生映射文件的副本,也就是说,私有的“写入时复制”对这个区域所做的任何修改都不会写回原文件内容,写入也不会影响原文件。这个标志和MAP_SHARED是互斥的,其中只有MAP_ANONYMOUS:一个可以用来建立匿名映射。此时,参数fd被忽略,不涉及任何文件,并且映射区域不能与其他进程共享。MAP_DENYWRITE:只允许对映射区域进行写操作,其他对文件的直接写操作将被拒绝。MAP_LOCKED:映射的区域被锁定,这意味着该区域不会被交换,从而防止页面被交换出内存。MAP_NORESERVE:没有为这个映射保留交换空间。当交换空间被保留时,可以保证对映射区域的修改。当交换空间没有预留,内存不足时,映射区的修改会引起段违规信号MAP_LOCKED:锁定映射区的页面,从而防止页面被换出内存MAP_GROWSDOWN:用于堆栈,告诉内核VM系统映射区可以向下扩展MAP_POPULATE:通过预读为文件映射准备页表。对映射区域的后续访问不会被页面冲突MAP_NONBLOCK阻塞:它只有在与MAP_POPULATE一起使用时才有意义。没有预读,只有页表条目fd:为已经在存储器中的页建立要映射到存储器的文件描述符。

  Offset:文件映射的偏移量,通常设置为0,表示对应文件的起始位置。偏移量必须是页面大小的整数倍。

  返回值:

  如果映射成功,mmap()返回映射区的内存起始地址,munmap()返回0;如果映射失败,mmap()返回MAP_FAILED,值为(void *)-1,munmap()返回-1 2。mmap读取intfd=open (file _ name.c _ str(),o _//读取文件长度int len=lseek(fd,0,SEEK _ END);//建立映射char * buffer=(char *) mmap (null,len,prot _ read,map _ private,fd,0);关闭(FD);//做点什么//关闭映射munmap(buffer,len);3.mmap写int len=data . length();//打开文件intfd=open (file _ name.c _ str(),o _ rdwr o _ create,00777);//lseek将文件指针后移len-1位lseek(fd,len-1,SEEK _ END);//预先写一个空字符;Mmap不能扩展文件长度,相当于提前给定文件长度,准备一个空架写(fd, ,1);//建立映射char * buffer=(char *) mmap (null,len,prot _ read prot _ write,map _ shared,FD,0);//关闭文件Close(FD);//将数据复制到buffer中的memcpy(buffer,data,len)中;//关闭映射munmap(buffer,len) 4。mmap多进程写作。无论是父子进程还是无关进程,都可以将自己的用户空间映射到同一个文件,或者匿名映射到同一个区域。从而分别通过改变映射区域来达到进程间通信和进程间共享的目的。

  以这里的8个流程为例。

  #包含位/标准数据。h # include unistd . h # include sys/mman . h # include fcntl . husing命名空间stdconst int PROCESS _ COUNT=8;const int RESULT _ SIZE=20000void work(const string file_name,int PID){ int FD=open(file _ name . c _ str(),O_RDWR O_CREAT,0666);char *buffer=(char *) mmap(NULL,RESULT_SIZE * 2,PROT_READ PROT_WRITE,MAP_SHARED,fd,0);关闭(FD);int start=pid *结果大小/进程计数;int end=开始结果_大小/进程_计数;for(int I=start;我结束;i) { buffer[i 1]=(i % 2!=0 ?1 : 0);buffer[I 1 1]= \ n ;} munmap(buffer,RESULT _ SIZE * 2);} int main(){ string predict _ file= result . txt ;//Fill file intfd=open(predict _ file . c _ str(),o _ rdwr o _ create,0666);lseek(fd,RESULT_SIZE * 2 - 1,SEEK _ SET);write(fd, ,1);关闭(FD);//mmap多进程写int idpid _ t pidvectorpid _ t pidsfor(int I=1;i PROCESS _ COUNTI){ id=I;PID=fork();if (pid=0)中断;pids . push _ back(PID);} if (pid==-1) { cerr 启动过程失败 endl} else { if(PID==0){ work(predict _ file,id);//子进程退出(0);} else { work(predict_file,0);//主进程}}退出(0);} 5.注意mmap映射区域的大小必须是物理页面大小的整数倍(在32位系统中通常是4k字节)。原因是内存的最小粒度是页,进程虚拟地址空间和内存的映射是基于页的。为了匹配内存的操作,从磁盘到虚拟地址空间的mmap映射也必须是基于页的。

  但是我们要读写的文件大小往往不是4k的整数倍,所以在建立映射时一定要准确把握文件大小和映射区的长度大小。

  如果文件不是4k的整数倍,实际映射区域还是4k的整数倍,其余的用0填充。剩下的部分虽然不在文件范围内,但仍然可以正常读写,这部分内容的改变并不影响原文件。(比如文件大小为8000字节,实际映射的区域大小为8192字节,8000 ~ 8192字节用0填充,区域可以正常访问)

  如果映射区域的大小设置为远大于文件大小,比如文件大小为8000字节,长度为100000字节,那么只有文件对应的物理页可以有效读写,即只有前两页可以有效读写,对于8192到100000的区域和100000以上的区域,进程无法读写。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: