Re: [問題] 兩個process寫入同一個檔案的疑問
※ 引述《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;
}
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 125.229.74.160 (臺灣)
※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1657513524.A.C18.html
推
07/11 13:45,
2年前
, 1F
07/11 13:45, 1F
→
07/11 13:45,
2年前
, 2F
07/11 13:45, 2F
→
07/11 13:46,
2年前
, 3F
07/11 13:46, 3F
→
07/11 13:47,
2年前
, 4F
07/11 13:47, 4F
推
07/12 07:50,
2年前
, 5F
07/12 07:50, 5F
→
07/12 14:08,
2年前
, 6F
07/12 14:08, 6F
討論串 (同標題文章)
本文引述了以下文章的的內容:
完整討論串 (本文為第 2 之 2 篇):
C_and_CPP 近期熱門文章
PTT數位生活區 即時熱門文章