在Unix-like系统中,fork()
系统调用用于创建一个新的进程,这个新进程几乎是父进程的一个完整副本,包括代码、数据、堆栈以及打开的文件描述符等。mmap()
系统调用则用于将文件或设备映射到内存中,这样可以像访问普通内存一样访问文件内容,通常用于高效地处理大文件。
如果在调用fork()
之前使用mmap()
将文件映射到内存,那么父进程和新创建的子进程将会共享这个内存映射。这意味着对映射区域的任何修改都会反映在两个进程中,因为它们实际上是在访问同一块物理内存。
优势:
应用场景:
如果在调用fork()
之后使用mmap()
,那么只有调用mmap()
的那个进程会有新的内存映射,而另一个进程不会有这个映射。
优势:
应用场景:
fork()
之前映射,父子进程共享内存区域;在fork()
之后映射,只有调用mmap()
的进程有映射。fork()
之前映射,需要注意同步访问共享内存,以避免竞态条件;如果在fork()
之后映射,则无需担心这个问题。如果在fork()
前后使用mmap()
遇到了问题,可能的原因包括:
mmap()
映射的内存没有被正确释放,可能会导致内存泄漏。解决方法是确保在进程结束前调用munmap()
来解除映射。mmap()
会失败。解决方法是检查文件权限和进程的权限设置。#include <sys/mman.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
int main() {
int fd = open("example.txt", O_RDWR);
if (fd == -1) {
perror("open");
return 1;
}
// 获取文件大小
off_t size = lseek(fd, 0, SEEK_END);
// 在fork之前调用mmap
void *addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (addr == MAP_FAILED) {
perror("mmap");
close(fd);
return 1;
}
pid_t pid = fork();
if (pid == -1) {
perror("fork");
munmap(addr, size);
close(fd);
return 1;
} else if (pid == 0) {
// 子进程
printf("Child process: %s\n", (char *)addr);
// 修改共享内存
strcpy((char *)addr, "Hello from child!");
} else {
// 父进程
wait(NULL); // 等待子进程结束
printf("Parent process: %s\n", (char *)addr);
}
munmap(addr, size);
close(fd);
return 0;
}
在这个示例中,父进程和子进程共享了通过mmap()
映射的内存区域,并且可以看到子进程对共享内存的修改也反映在了父进程中。
领取专属 10元无门槛券
手把手带您无忧上云