首页 > 解决方案 > 使用 mmap() 的复制命令变体中的问题

问题描述

我有一个程序,它是 linux 中复制程序的另一种变体(实际上我在 Mac OSX 上)。为了支持复制大文件,我写了这样的东西:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/mman.h>
#define BUFFSIZE 65535
#define PAGESIZE 4096
int main(int argc, char **argv){
  char *source, *destination;
  int src_fd, dst_fd;
  unsigned long long bytes_read;
  int bytes = BUFFSIZE;
  struct timeval start, end;
  int overall_time = 0;
  unsigned long long offset = 0;
  struct stat statbuf;
  if(argc < 3){
    printf("copy <source> <destination>\n");
    exit(EXIT_FAILURE);
  }
source = argv[1];
  destination = argv[2];

  src_fd = open(source, O_RDONLY, 0777);
  if(src_fd < 0){
    perror("src_fd");
    exit(EXIT_FAILURE);
  }
  //bytes_read = lseek(src_fd, 0, SEEK_END);
  fstat(src_fd, &statbuf);
  bytes_read = statbuf.st_size;
  dst_fd = open(destination, O_RDWR | O_CREAT, 0777);
  if(dst_fd < 0){
    perror("dst_fd");
    exit(EXIT_FAILURE);
  }
  lseek(dst_fd, bytes_read -1, SEEK_SET);
  write(dst_fd, "", 1);

  gettimeofday(&start, NULL);
  while(bytes_read > 0){
    if(bytes_read < BUFFSIZE){
      bytes = bytes_read;
      bytes_read = 0;
    }
    else{
      bytes_read -= bytes;
    }
    void *src_map = mmap(NULL, bytes, PROT_READ, MAP_SHARED, src_fd, (off_t)offset);
    if(src_map == (void*) MAP_FAILED){
      perror("src_map");
      exit(EXIT_FAILURE);
    }

    void *dst_map = mmap(NULL, bytes, PROT_WRITE, MAP_SHARED, dst_fd, (off_t)offset);
    if(dst_map == (void*) MAP_FAILED){
      perror("dst_map");
      exit(EXIT_FAILURE);
    }

    memcpy(dst_map, src_map, bytes);

    int src_unmp = munmap(src_map, bytes);
    if(src_unmp == -1){
      perror("src_unmap");
      exit(EXIT_FAILURE);
    }
    int dst_unmp = munmap(dst_map, bytes);
    if(dst_unmp == -1){
      perror("dst_unmap");
      exit(EXIT_FAILURE);
    }
    offset += 4096;
    bytes_read -= bytes;
  }
  gettimeofday(&end, NULL);
  printf("overall = %d\n", (end.tv_usec - start.tv_usec));
  close(src_fd);
  close(dst_fd);
  return 0;
}

目标是测量使用 mmap() 复制大文件所用的时间量。

上述代码不适用于传输 1GB 文件。

有什么提示吗?

谢谢

标签: cshared-memorymmap

解决方案


是的。问题在于偏移值。偏移值应该是页面大小的倍数。


推荐阅读