Re: [问题] 两个process写入同一个档案的疑问

楼主: hth9494 (hth9494)   2022-07-11 12:25:20
※ 引述《hth9494 (掰掰惹 仙度瑞拉)》之铭言:
: 开发平台(Platform): (Ex: Win10, Linux, ...)
: Linux kali 5.18.0-kali2-amd64 #1 SMP PREEMPT_DYNAMIC Debian 5.18.5-1kali1
: (2022-06-20) x86_64 GNU/Linux
: 编译器(Ex: GCC, clang, VC++...)+目标环境(跟开发平台不同的话需列出)
: gcc (Debian 11.3.0-3) 11.3.0
: 额外使用到的函数库(Library Used): (Ex: OpenGL, ...)
: 问题(Question):
: 我有两个process开启同一个file,且两个process同时向file写入字串
: 一个写入"a",一个写入"b",各自重复写入200次
: 每一次写入,两个process就会printf出当前ftell的值
: 问题:
: 我期待看到file中ab会交替出现
: 但并没有,而是a全部出现完才换b,或者b出现完才换a
: 不过从console上印出的ftell值却又显示
: 这两个process显然是交替执行着,并不是一个执行完才换另一个
: 既然如此,为什么file的内容不是交替的显示a和b呢
: 请问要如何做才能看到ab交替的结果
: 谢谢
: 喂入的资料(Input):
: 预期的正确结果(Expected Output):
: file中a和b交替显示
: 错误结果(Wrong Output):
: 200个a全部显示完才换b,或者200个b显示完才换a
: 程式码(Code):(请善用置底文网页, 记得排版,禁止使用图档)
: #include <stdio.h>
: #include <stdlib.h>
: #include <string.h>
: int main()
: {
: FILE *pfile;
: int id = fork();
: if (id == 0) {
: char *str = "a";
: pfile = fopen("testfile", "a");
: if (pfile) {
: int i;
: for (i = 0; i < 200; i++) {
: printf("a = %d\n", ftell(pfile));
: fwrite(str, 1, strlen(str), pfile);
: }
: }
: }
: else if (id > 0) {
: printf("id = %d\n", id);
: char *str = "b";
: pfile = fopen("testfile", "a");
: if (pfile) {
: int i;
: for (i=0;i<200;i++) {
: printf("b = %d\n", ftell(pfile));
: fwrite(str, 1, strlen(str), pfile);
: }
: }
: }
: fclose(pfile);
: return 0;
: }
: 补充说明(Supplement):
抱歉,我原先的问题描述不准确
我原文所谓的交替是指,我预期a和b会有不规则穿插的效果
像是aaabbaaaaaabbbbbabababaaa
而非abababababababababababab
因为本来只是想练习fork()和感受一下race condition的效果
结果因为用fwrite导致档案内容不如预期才上来发问
但看了板友的推文,我就也想练习一下要怎么做才能abababababababab
因为目前还不会IPC或condition variable之类的观念
所以只想到笨方法
现在变成有两个档案,原先的testfile和一个新的check
当process a写入testfile后,会在check写下一个属于a的标记,表示已经写入testfile
当process b写入testfile后,亦然
process a 在写入档案前
先不断去判断check,看看b是否有写入标记了
如果确认b已写入,才会写入testfile
process b 也做一样的动作
我执行后这样就能达成ababab的效果
前提要先建立check并且给一个初始的标记
我大概知道这样会有一些问题,像是a跟b要不停去检查check,而非等待通知再执行
导致浪费CPU资源等等
但我这个作法除了这个问题外,是否已能保证执行结果一定是abababab呢
是否要给check加锁什么的,否则在check上也会发生race condition的问题
导致结果不是abababab?
谢谢各位
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *pfile = NULL;
int id = fork();
if (id == 0) {
// process a, keep writting a
char *str = "a";
pfile = fopen("testfile", "a");
if (pfile) {
int fd = fileno(pfile);
int i;
for (i = 0; i < 200; i++) {
// keep checking until b is written
char c = 0;
while (c != 'b') {
FILE *pcheck = fopen("check", "r");
int fdcheck = fileno(pcheck);
read(fdcheck, &c, 1);
fclose(pcheck);
}
// write a
printf("a = %d\n", ftell(pfile));
write(fd, str, 1);
// update check
FILE *pcheck = fopen("check", "w");
int fdcheck = fileno(pcheck);
write(fdcheck, str, 1);
fclose(pcheck);
}
}
}
else if (id > 0) {
// process b , keep writting b
char *str = "b";
pfile = fopen("testfile", "a");
if (pfile) {
int fd = fileno(pfile);
int i;
for (i=0;i<200;i++) {
// keep checking until a is written
char c = 0;
while (c != 'a') {
FILE *pcheck = fopen("check", "r");
int fdcheck = fileno(pcheck);
read(fdcheck, &c, 1);
fclose(pcheck);
}
// write b
printf("b = %d\n", ftell(pfile));
write(fd, str, 1);
// update check
FILE *pcheck = fopen("check", "w");
int fdcheck = fileno(pcheck);
write(fdcheck, str, 1);
fclose(pcheck);
}
}
}
if (pfile)
fclose(pfile);
return 0;
}
作者: qscgy4 (有点厉害)   2022-07-11 13:45:00
如果只是想看 abbababbbaa 那你直接printf或cout都能看如果想要在档案看到,那就多写一个thread来接收那个thread就按接收顺序写入这样应该最简单
作者: wulouise (在线上!=在电脑前)   2022-07-12 07:50:00
你的实作在两个producer的时候没事,多个的时候不好处理
作者: longlongint (华哥尔)   2022-07-12 14:08:00
有试过 sync write 吗
作者: WPC001 (好闷, 迷惘~~)   2022-07-15 21:23:00
要不规则穿插... 除非写入内容很长... 或是每写一个byte就主动睡下去...基本上你有fclose... 应该是已经被flush了,多加个sleep吧
作者: choosin (秋心)   2022-07-19 11:49:00
file本身就是IPC的一种 要abab更简单 开档检查结尾写回就好 依照你本来想写200a跟200b 那最后如果没有200a+200b那也可以看到race condition的发生

Links booklink

Contact Us: admin [ a t ] ucptt.com