两个进程写入同一个文件
Two processes writing on the same file
我知道这是灾难的根源。我实际上使用共享变量让它工作。
但这是作业,老师肯定希望我们把许多进程使用不同的文件指针写入同一个文件。我一整天都在尝试,但收效甚微,但我就是找不到失败的原因。
我已经通过以下方式解决了这个问题:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int status;
int process_count = 0;
do
{
int from = (n / np) * (process_count) + 1;
int to = (n / np) * (process_count + 1);
if (fork() == 0)
{
FILE *aux;
aux = fopen("./parciais.txt", "w");
fseek(aux, sizeof(int) * process_count, SEEK_SET);
int sum = 0;
int i = from;
while (i <= to)
{
int square = i * i;
sum += square;
i++;
}
long int where_am_i = ftell(aux);
printf("I am process %i writing %i on byte: %li\n", process_count, sum, where_am_i);
fwrite(&sum, sizeof(int), 1, aux);
fclose(aux);
exit(1);
}
else
{
wait(&status);
process_count++;
}
} while (process_count < np);
FILE *aux;
aux = fopen("./parciais.txt", "r");
int sum;
for (int i = 0; i <= np - 1; i++)
{
fseek(aux, sizeof(int) * i, SEEK_SET);
long int where_am_i = ftell(aux);
int read;
fread(&read, sizeof(int), 1, aux);
printf("I am reading %i at byte: %li\n", read, where_am_i);
sum += read;
}
}
我希望输出是这样的:
I am process 0 writing 98021 on byte: 0
I am process 1 writing 677369 on byte: 4
I am process 2 writing 1911310 on byte: 8
I am reading 98021 at byte: 0
I am reading 677369 at byte: 4
I am reading 1911310 at byte: 8
但我得到:
I am process 0 writing 98021 on byte: 0
I am process 1 writing 677369 on byte: 4
I am process 2 writing 1911310 on byte: 8
I am reading 0 at byte: 0
I am reading 0 at byte: 4
I am reading 1911310 at byte: 8
这意味着,出于某种原因,只写入了最后一个值。
我一直在为此苦思冥想,但我就是找不到问题所在...有人可以帮帮我吗?
问题是由于 fopen("./parciais.txt", "w")
:
"w" : "Creates an empty file for writing. If a file with the same name already exists, its content is erased and the file is considered as a new empty file."
试试 "a"!
("Appends to a file. Writing operations, append data at the end of the file. The file is created if it does not exist.")
正如另一个答案中提到的, "a" 参数也不够。该文件必须创建一次,因此在主进程中创建,然后以 "r+b" 模式访问以使 fseek 正常工作!
正如@B.Go 已经回答的那样,主要问题是您正在使用 "w"
模式打开文件,如果它已经存在,t运行 会将其归为零长度。每个子进程都这样做,破坏前一个进程写入的内容。
您想要文件的这种行为组合:
- 如果它尚不存在(或者我想你至少想要这个),则创建它
- 它不是 t运行如果它确实已经存在
- 你可以给它写信
- 从当前文件偏移量开始写入,而不是自动转到文件的当前末尾
- 该文件是二进制文件,不受任何类型的字符转换或写入时尾部 t运行阳离子
不幸的是,没有提供所有这些的标准模式:各种 r
模式要求文件已经存在,w
模式 t运行cate 文件如果它确实已经存在,并且 a
模式将所有写入定向到文件的当前末尾,而不管流的当前偏移量如何。如果您可以假设该文件已经存在,那么模式 "r+b"
(也可以拼写为 "rb+"
)具有所有需要的特征,但如果文件不存在则创建该文件:
aux = fopen("./parciais.txt", "r+b");
这也允许读取,但仅仅因为您 可以 从文件中读取并不意味着您必须这样做。此外,在符合 Linux 和 POSIX 的系统上,二进制文件和文本文件之间没有区别,因此如果您确信您的程序需要 [=54],则可以省略 b
=] 仅在 POSIX 系统上。您正在使用 fork()
表明此条件可能适用于您。
如果您也必须提供创建文件的功能,则在程序的最开始打开它一次,使用 w
或 a
模式中的任何一种,具体取决于您是否想要t运行编辑文件,然后立即再次关闭:
FILE *aux = fopen("./parciais.txt", "a");
if (aux) {
fclose(aux);
} else {
// handle error ...
}
我知道这是灾难的根源。我实际上使用共享变量让它工作。
但这是作业,老师肯定希望我们把许多进程使用不同的文件指针写入同一个文件。我一整天都在尝试,但收效甚微,但我就是找不到失败的原因。
我已经通过以下方式解决了这个问题:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int status;
int process_count = 0;
do
{
int from = (n / np) * (process_count) + 1;
int to = (n / np) * (process_count + 1);
if (fork() == 0)
{
FILE *aux;
aux = fopen("./parciais.txt", "w");
fseek(aux, sizeof(int) * process_count, SEEK_SET);
int sum = 0;
int i = from;
while (i <= to)
{
int square = i * i;
sum += square;
i++;
}
long int where_am_i = ftell(aux);
printf("I am process %i writing %i on byte: %li\n", process_count, sum, where_am_i);
fwrite(&sum, sizeof(int), 1, aux);
fclose(aux);
exit(1);
}
else
{
wait(&status);
process_count++;
}
} while (process_count < np);
FILE *aux;
aux = fopen("./parciais.txt", "r");
int sum;
for (int i = 0; i <= np - 1; i++)
{
fseek(aux, sizeof(int) * i, SEEK_SET);
long int where_am_i = ftell(aux);
int read;
fread(&read, sizeof(int), 1, aux);
printf("I am reading %i at byte: %li\n", read, where_am_i);
sum += read;
}
}
我希望输出是这样的:
I am process 0 writing 98021 on byte: 0
I am process 1 writing 677369 on byte: 4
I am process 2 writing 1911310 on byte: 8
I am reading 98021 at byte: 0
I am reading 677369 at byte: 4
I am reading 1911310 at byte: 8
但我得到:
I am process 0 writing 98021 on byte: 0
I am process 1 writing 677369 on byte: 4
I am process 2 writing 1911310 on byte: 8
I am reading 0 at byte: 0
I am reading 0 at byte: 4
I am reading 1911310 at byte: 8
这意味着,出于某种原因,只写入了最后一个值。
我一直在为此苦思冥想,但我就是找不到问题所在...有人可以帮帮我吗?
问题是由于 fopen("./parciais.txt", "w")
:
"w" : "Creates an empty file for writing. If a file with the same name already exists, its content is erased and the file is considered as a new empty file."
试试 "a"!
("Appends to a file. Writing operations, append data at the end of the file. The file is created if it does not exist.")
正如另一个答案中提到的, "a" 参数也不够。该文件必须创建一次,因此在主进程中创建,然后以 "r+b" 模式访问以使 fseek 正常工作!
正如@B.Go 已经回答的那样,主要问题是您正在使用 "w"
模式打开文件,如果它已经存在,t运行 会将其归为零长度。每个子进程都这样做,破坏前一个进程写入的内容。
您想要文件的这种行为组合:
- 如果它尚不存在(或者我想你至少想要这个),则创建它
- 它不是 t运行如果它确实已经存在
- 你可以给它写信
- 从当前文件偏移量开始写入,而不是自动转到文件的当前末尾
- 该文件是二进制文件,不受任何类型的字符转换或写入时尾部 t运行阳离子
不幸的是,没有提供所有这些的标准模式:各种 r
模式要求文件已经存在,w
模式 t运行cate 文件如果它确实已经存在,并且 a
模式将所有写入定向到文件的当前末尾,而不管流的当前偏移量如何。如果您可以假设该文件已经存在,那么模式 "r+b"
(也可以拼写为 "rb+"
)具有所有需要的特征,但如果文件不存在则创建该文件:
aux = fopen("./parciais.txt", "r+b");
这也允许读取,但仅仅因为您 可以 从文件中读取并不意味着您必须这样做。此外,在符合 Linux 和 POSIX 的系统上,二进制文件和文本文件之间没有区别,因此如果您确信您的程序需要 [=54],则可以省略 b
=] 仅在 POSIX 系统上。您正在使用 fork()
表明此条件可能适用于您。
如果您也必须提供创建文件的功能,则在程序的最开始打开它一次,使用 w
或 a
模式中的任何一种,具体取决于您是否想要t运行编辑文件,然后立即再次关闭:
FILE *aux = fopen("./parciais.txt", "a");
if (aux) {
fclose(aux);
} else {
// handle error ...
}