【发布时间】:2026-01-31 02:15:01
【问题描述】:
我正在为学校制作一个程序,其中我有一个多进程程序,其中每个进程读取文件的一部分,它们一起工作以计算文件中的单词数。我遇到了一个问题,如果有超过 2 个进程,那么所有进程在读取文件的一部分之前从文件中读取 EOF。以下是相关代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
int main(int argc, char *argv[]) {
FILE *input_textfile = NULL;
char input_word[1024];
int num_processes = 0;
int proc_num = 0; //The index of this process (used after forking)
long file_size = -1;
input_textfile = fopen(argv[1], "r");
num_processes = atoi(argv[2]);
//...Normally error checking would go here
if (num_processes > 1) {
//...create space for pipes
for (proc_num = 0; proc_num < num_processes - 1; proc_num++) {
//...create pipes
pid_t proc = fork();
if (proc == -1) {
fprintf(stderr,"Could not fork process index %d", proc_num);
perror("");
return 1;
} else if (proc == 0) {
break;
}
//...link up the pipes
}
}
//This code taken from http://*.com/questions/238603/how-can-i-get-a-files-size-in-c
//Interestingly, it also fixes a bug we had where the child would start reading at an unpredictable place
//No idea why, but apparently the offset wasn't guarenteed to start at 0 for some reason
fseek(input_textfile, 0L, SEEK_END);
file_size = ftell(input_textfile);
fseek(input_textfile, proc_num * (1.0 * file_size / num_processes), 0);
//read all words from the file and add them to the linked list
if (file_size != 0) {
//Explaination of this mess of a while loop:
// if we're a child process (proc_num < num_processes - 1), then loop until we make it to where the next
// process would start (the ftell part)
// if we're the parent (proc_num == num_processes - 1), loop until we reach the end of the file
while ((proc_num < num_processes - 1 && ftell(input_textfile) < (proc_num + 1) * (1.0 * file_size / num_processes))
|| (proc_num == num_processes - 1 && ftell(input_textfile) < file_size)){
int res = fscanf(input_textfile, "%s", input_word);
if (res == 1) {
//count the word
} else if (res == EOF && errno != 0) {
perror("Error reading file: ");
exit(1);
} else if (res == EOF && ftell(input_textfile) < file_size) {
printf("Process %d found unexpected EOF at %ld.\n", proc_num, ftell(input_textfile));
exit(1);
} else if (res == EOF && feof(input_textfile)){
continue;
} else {
printf("Scanf returned unexpected value: %d\n", res);
exit(1);
}
}
}
//don't get here anyway, so no point in closing files and whatnot
return 0;
}
使用 3 个进程运行文件时的输出:
All files opened successfully
Process 2 found unexpected EOF at 1323008.
Process 1 found unexpected EOF at 823849.
Process 0 found unexpected EOF at 331776.
导致错误的测试文件:https://dl.dropboxusercontent.com/u/16835571/test34.txt
编译:
gcc main.c -o wordc-mp
并运行为:
wordc-mp test34.txt 3
值得注意的是,只有那个特定的文件给我带来了问题,但错误的偏移量不断变化,所以它不是文件的内容。
【问题讨论】:
-
Jonathan 的猜测可能是正确的,但在寻求调试帮助时,您应该始终发帖 Minimal Complete Verifiable Example。
-
好的,我会努力完成的
-
@user3386109 完成。链接在编辑文本中。
-
我不喜欢成为坏消息的承担者,但是......您需要edit问题,并将所有必要信息放在问题中本身。因此,我将删除您当前拥有的代码,并将其替换为 MCVE 代码。至于文本文件,可能没有必要把它放在问题中。我假设任何旧文本文件(包含单词)都可以。所以留下一个文本文件的链接是可以的。
-
看起来即使我们在课堂上进行了测试,但问题实际上是在分叉之前打开了文件。我想我们在测试期间很幸运,因为文件太小了。无论如何,将打开文件移到程序的后面就足以解决我的问题(尽管代码仍然不起作用,但现在有其他原因)。谢谢你们的帮助。