繁体   English   中英

mmap 参数无效 - 从命令行读取多个文件并写入一个 output 文件

[英]mmap invalid argument - reading multiple files from command line and writing to one output file

我正在编写一个 C 程序,它从命令行获取多个文件并将它们组合成一个 output 文件。 如果没有给出 output 文件,则创建它。 我使用 mmap 复制文件内容。

但是,当我运行以下代码时,我得到“mmap:无效参数”,我不知道为什么。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>

int main(int argc, char *argv[])
{
  int opt, output=0, len; 
  int fd_o, fd_i;
  char *addr=NULL;
  struct stat stat_input;
  const char *errmsg="Invalid argument:\n";
  const char *usage=
      "combine to one\n";

  while((opt = getopt(argc, argv, "o"))!= -1) {
      switch(opt){
      case 'o': 
        output=1;
        fd_o=open(argv[argc-1], O_WRONLY|O_CREAT|O_TRUNC, 0644);
        if (fd_o == -1){
          perror("open");
          exit(1);
        }
        break;
      case '?':
        write(2, errmsg, strlen(errmsg));
        write(2, usage, strlen(usage));
        exit(1);
    }
  }

  if (output==0){
    write(2, errmsg, strlen(errmsg));
    write(2, usage, strlen(usage));
    exit(1);
  }
 
  for(; optind < argc; optind++){
    fd_i=open(argv[optind], O_RDONLY);
    if (fd_i == -1){
      perror("open");
      exit(1);
}

    fstat(fd_i, &stat_input);
    len=stat_input.st_size;
    addr=mmap(0, len, PROT_READ, MAP_SHARED, fd_i, 0);
    if (addr == MAP_FAILED) {
      close(fd_i);
      perror("mmap");
      exit(1);
    }
    write(fd_o, *addr, len);
    close(fd_i);
    munmap(addr,len);
  }
  close(fd_o);
}

我认为问题实际上是您的选项解析。 就目前而言,如果完全指定了-o ,则始终使用最后一个参数作为 output 文件。 因此,如果您运行./myprog f1 f2 -o out ,则所有f1, f2, out都将用作输入文件。 如果你运行./myprog -o out f1 f2那么 all of out, f1, f2将是输入, output 将 go 到f2

我想您没想到会使用 output 文件作为输入,如果它是空的,您将尝试创建长度为 0 的 map,这将失败并显示“无效参数”。 我的猜测是这是你的问题的原因。

使用getopt处理带有参数的选项的正确方法是使用"o:"作为选项字符串,然后当getopt返回'o'时,变量optarg将指向选项的参数; 这就是您应该用作 output 文件名而不是argv[argc-1]的文件名。

其他几个错误:

  • write(fd_o, *addr, len); 应该是write(fd_o, addr, len); 因为write需要一个指向其数据的指针。 你应该得到一个关于这个的编译器警告。

  • 您需要在调用mmap之前测试len != 0 ,以防有人真的在空输入文件上运行程序。

  • 我不确定您为什么将write()用于使用消息,而不仅仅是fprintf(stderr, ...) 如果由于某种原因 stdio 函数不可接受(即使您在其他地方似乎对perror()没有问题),那么标准的 function dprintf可能会让您的生活更轻松一些。

从手册页mmap()

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

EINVAL(无效参数错误)的可能原因:

    1) We don't like addr, length, or offset (e.g., they are too large, or not aligned on a page boundary).

    2) (since Linux 2.6.12) length was 0.

    3) flags contained none of MAP_PRIVATE, MAP_SHARED or MAP_SHARED_VALIDATE.

我认为len in len = stat_input.st_size; 为零。 这可能是原因。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM