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



我正在编写一个C程序,该程序从命令行获取多个文件,并将它们组合为一个输出文件。如果没有给出输出文件,则会创建它。我使用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 onen";
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,则始终使用最后一个参数作为输出文件。因此,如果运行./myprog f1 f2 -o out,那么所有f1, f2, out都将用作输入文件。如果运行./myprog -o out f1 f2,那么所有的out, f1, f2都将是输入,输出将转到f2

我想你没想到会使用输出文件作为输入,如果它是空的,你会尝试创建一个长度为0的映射,但会失败;无效的参数"。我想这就是你问题的原因。

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

其他几个错误:

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

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

  • 我不知道你为什么在使用消息中使用write(),而不仅仅是fprintf(stderr, ...)。如果由于某种原因stdio函数不可接受(即使您在其他地方似乎对perror()没有问题(,那么标准函数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 = stat_input.st_size;中的len为零。这可能就是原因。

最新更新