最近学习了 mmap 函数来完成进程之间的通信, 故有此案例:
文件大小为: 351486000 byte
时间对比:
1. 单进程拷贝: 0.915s
2. 多进程拷贝: 0.001ms
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
// 检查错误
void check(int ret, const char *msg)
{
if(-1 == ret)
{
perror(msg);
exit(1);
}
}
// 将内存buffer开始得size字节数据拷贝到文件fd当中, 从off的指定偏移位置开始拷贝
void copy(char *buffer, int size, int fd, off_t off)
{
//1. 将文件读写指针移动到指定位置上去.
lseek(fd, off, SEEK_SET);
//2. 开始向里面写入内容
write(fd, buffer, size);
}
int main()
{
int ret = 0;
// 1.打开文件 dat
int fd = open("./dat", O_RDONLY);
check(fd, "打开./dat失败\n");
// 2.获取文件的大小
struct stat s;
ret = stat("./dat", &s);
check(ret, "stat('./dat')失败\n");
off_t size = s.st_size;
// 3.判断目标文件是否存在, 存在退出, 不存在则创建目标文件, 并将目标文件进行拓展
int fd1 = open("./dest", O_RDWR | O_CREAT | O_EXCL, 0777);
if(fd1 == -1 && errno & EEXIST)
{
perror("file exists!");
exit(1);
}
ret = ftruncate(fd1, size);
check(ret, "truncate error");
ret = close(fd1);
check(ret, "close fd1 failure!\n");
// 4.为此文件创建内存的映射区
char * ptr = (char *)mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
if(ptr == MAP_FAILED)
{
printf("mmap error!\n");
exit(1);
}
// 创建5个进程
int each = size / 5, i;
for(i = 0; i != 5; ++i)
{
pid_t id = fork();
if(id == 0)
{
int fd1 = open("./dest", O_RDWR);
int rest = 0;
if(i == 4) rest = size % 5;
copy(ptr + i * each, each + rest, fd1, i * each);
close(fd1);
break;
}
}
if(i == 5)
{
close(fd);
munmap(ptr, size);
}
return 0;
}