网站建设的落地页,怎么让wordpress挂掉,网站服务器如何更改解析,wordpress 指定文章链接写在前面#xff1a; 在进程间通信中#xff0c;有一种方式内存映射。内存映射也是进程间通信的方式之一#xff0c;其效率高#xff0c;可以直接对内存进行操作。本节我们对内存映射进行学习#xff0c;并结合案例进行实践。 1、基本理论 内存映射#xff1a;是将磁盘文… 写在前面 在进程间通信中有一种方式内存映射。内存映射也是进程间通信的方式之一其效率高可以直接对内存进行操作。本节我们对内存映射进行学习并结合案例进行实践。 1、基本理论 内存映射是将磁盘文件中的数据映射到内存用户通过修改内存就能修改磁盘文件。 那通过内存映射如何实现进程之间的通信呢简单来说就是将同一个文件存储映射部分分别映射到不同的进程中两个进程通过改变文件的内容读写内存来实现通信不必再使用read和write函数等系统调用加快文件的读取和写入。 内存映射相关函数
#include sys/mman.h
void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);//用于文件或者设备映射到内存中去
int munmap(void *addr, size_t length);//释放内存映射 1、mmap函数 涉及头文件#include sys/mman.h 函数原型void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset); 功能将一个文件或者设备的数据映射到内存中去 参数 - void *adder:NULL;由内核指定。 -lenth:要映射的内存的长度这个值不能为0建议使用文件的长度 获取文件的长度stat lseek 没有达到分页的大小按照分页大小进行所以是分页的整数倍。 所以一般情况下申请的内存区域大于等于文件的大小。 -prot:对申请的内存区的操作权限 PROT_EXEC 可执行的权限 PROT_READ 读的权限 PROT_WRITE 写的权限 PROT_NONE 没有权限 要操作映射内存必须要读的权限-PROT_READ、PROT_READ|PROT_WRITE -flags MAP_SHARED映射区的数据会自动和磁盘文件进行同步如果要完成进程间通信必须设置这个选项 MAP_PRIVATE不同步内存映射区的数据改变了对原来的文件不会修改会重新创建一个新的文件。copy on write. -fd: 需要操作的文件描述符通过open得到打开的是一个磁盘文件。 注意文件的大小不能为0 open指定的权限不能和prot冲突 portPROT_READ open只读/读写 portPROT_READ|PROT_WRITE open读写 总的来说port的权限要小于open的权限必须要有读的权限。 -offset偏移量一般不用必须要指定的是4k的整数倍。0表示不偏移。 返回值 -成功返回创建内存的首地址 -失败返回MAP_FAILED (void *)-1; 2、munmap函数 涉及头文件#includesys/mman.h 函数原型int munmap(void *addr, size_t length); 功能释放内存映射 参数 void *addr释放的内存的首地址 length:要释放的内存的大小要和mmap函数中的length的值一样。 2、案例一通过内存映射实现父子进程间的通信 实现方案 在没有子进程的时候通过唯一的父进程创建内存映射区 有了内存映射区再创建子进程 父子进程共享内存映射区 实现流程 1、打开一个文件 2、获取文件大小用于mmap函数的参数 3、创建内存映射区fork()之后父子进程共享内存映射区。 4、创建子进程 父进程读取数据子进程发送数据因为子进程发送完成后可以被父进程进行回收避免僵尸进程的产生。 #include stdio.h
#include fcntl.h
#include sys/types.h
#include sys/wait.h
#include unistd.h
#include sys/mman.h
#include string.h
#include stdlib.hint main()
{//1、打开一个文件int fd open(text.txt,O_RDWR);//2、获取大小int sizelseek(fd,0,SEEK_END);//3、创建内存映射区void *ptr mmap(NULL,size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);if(ptrMAP_FAILED){perror(mmap);exit(0);}//4、创建子进程pid_t pid fork();if(pid0){wait(NULL);//父进程char buf[64];strcpy(buf,(char *)ptr );printf(read data:%s\n,buf);}else if(pid0){//子进程strcpy((char *)ptr,nihao,sun!!);}//关闭内存映射区munmap(ptr,size);return 0;
}运行结果 3、案例二通过内存映射实现没有关系进程之间的通信 实现方案 准备一个大小不为0的磁盘文件 进程1 通过磁盘文件(与进程2的文件相同)创建内存的映射区 得到一个操作这块内存的指针。 进程2 通过磁盘文件(与进程1的文件相同)创建内存映射区 得到一个操作这块内存的指针。 使用内存映射区进行通信。 注意内存映射区通信没有阻塞 进程1写内容
#include stdio.h
#include fcntl.h
#include sys/types.h
#include sys/wait.h
#include unistd.h
#include sys/mman.h
#include string.h
#include stdlib.hint main()
{// 1、准备一个磁盘文件。// 2、通过磁盘文件创建内存的映射区int fd open(test.txt,O_RDWR);int size lseek(fd,0,SEEK_END);void * prtmmap(NULL,size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);if( prt MAP_FAILED){perror(mmap);exit(0);}strcpy((char *)prt,sixsixsix);munmap(prt,size);return 0;
}
进程2读文件
#include stdio.h
#include fcntl.h
#include sys/types.h
#include sys/wait.h
#include unistd.h
#include sys/mman.h
#include string.h
#include stdlib.hint main()
{// 1、准备一个磁盘文件。// 2、通过磁盘文件创建内存的映射区int fd open(test.txt,O_RDWR);int size lseek(fd,0,SEEK_END);void * prtmmap(NULL,size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);if( prt MAP_FAILED){perror(mmap);exit(0);}char buf[64];strcpy(buf,(char *)prt);printf(read data:%s\n,buf);munmap(prt,size);return 0;
}
运行结果 4、内存映射的注意事项 1、如果对mmap的返回值ptr做操作,munmap能够成功吗 void * ptr mmap(...) 可以对其进行操作但是不建议因为释放的时候需要把最开始的地址记录下来。 2、如果open时O_RDONLY,mmap时prot参数指定 PROT_READ|PROT_WRITE 会怎么样 错误会返回宏MAP_FAILED open()权限建议和prot参数保持一致更准确的说open()的权限要大于prot参数的权限 3、如果文件偏移量为1000会怎么样 偏移量必须是4k的整数倍否则 错误会返回宏MAP_FAILED 4、mmap什么情况下会调用失败 -第二个参数length0 -第三个参数prot权限 -只是指定了写权限 -prot参数权限为PROT_READ|PROT_WRITE,第5个参数文件描述符fd通过open函数打开时O_RDONLY、O_WRONLY 5、可以open的时候O_CREAT一个新文件来创建映射区。 可以的但是创建的文件的大小如果为0肯定不行 -lseek -truncate 进行扩展 6、mmap后关闭文件描述符对mmap映射有没有影响 int fdopen(xxx); mmap(,,,,fd,0); close(fd); 映射区还存在创建映射区的fd被关闭没有任何影响 7、对ptr进行越界操作会怎么 void *ptrmmap(NULL,100..); 4k 越界操作操作的是非法内存-段错误。 5、使用内存映射实现文件的拷贝 使用内存映射实现文件拷贝的功能 /* 1、对原始的文件进行内存映射 2、创建一个新的文件新文件进行扩展 3、把新文件的数据映射到内存中 4、通过内存拷贝将第一个文件的内存数据拷贝到新的文件内存中 5、释放资源 */ #include stdio.h
#include sys/mman.h
#include sys/types.h
#include sys/stat.h
#include fcntl.h
#include unistd.h
#include string.h
#include stdlib.h
int main()
{// 1、对原始的文件进行内存映射int fd open(english.txt,O_RDWR);if(fd-1){perror(open);exit(0);}//获取原始文件的大小int lenlseek(fd,0,SEEK_END);// 2、创建一个新的文件新文件进行扩展int fd1 open(cpy.txt,O_RDWR|O_CREAT,0664);if(fd1-1){perror(open);exit(0);}//对新创建的文件进行拓展truncate(cpy.txt,len);write(fd, ,1);//3、分别做内存映射void * ptr mmap(NULL,len,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);void * ptr1 mmap(NULL,len,PROT_READ|PROT_WRITE,MAP_SHARED,fd1,0);if(ptr MAP_FAILED){perror(mmap);exit(0);}if(ptr1 MAP_FAILED){perror(mmap);exit(0);}//内存拷贝memcmp(ptr1,ptr,len);//释放资源munmap(ptr1,len);munmap(ptr,len);close(fd1);close(fd);return 0;
} 运行结果 6、父子进程间匿名内存映射 匿名映射不需要文件实体直接进行内存映射。在父子进程中可以使用匿名映射。没有关系的进程不能进行没有关联了。 void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset); 关键在于port需要用到MAP_ANONYMOUS此参数是匿名映射所需要的。 #define _DEFAULT_SOURCE
#include stdio.h
#include fcntl.h
#include sys/types.h
#include sys/wait.h
#include unistd.h
#include sys/mman.h
#include string.h
#include stdlib.hint main()
{//1、创建匿名内存映射区int len 4096;void *ptr mmap(NULL,len,PROT_READ|PROT_WRITE ,MAP_SHARED | MAP_ANONYMOUS,-1,0);//if(ptrMAP_FAILED){perror(mmap);exit(0);}//2、父子进程通信pid_t pidfork();if(pid0){//父进程strcmp((char*)ptr,hello,world);wait(NULL);}else if(pid0){//子进程sleep(1);printf(%s\n,(char*)ptr);}//释放内存映射区int retmunmap(ptr,len);if(ret-1){perror(munmap);exit(0);}int ret1munmap(ptr,len);if(ret1-1){perror(munmap);exit(0);}}
运行结果 以上便是进程间内存映射的相关知识结合案例进行了分析大家学习后一定要多多练习
创作不易还请多多点赞支持