Linux 上面讀取檔案發生超奇怪問題

看板Programming作者 (眠月)時間16年前 (2009/04/13 14:27), 編輯推噓8(8036)
留言44則, 4人參與, 最新討論串1/1
※ [本文轉錄自 C_and_CPP 看板] 作者: yoco315 (眠月) 看板: C_and_CPP 標題: Linux 上面讀取檔案發生超奇怪問題 時間: Mon Apr 13 14:26:36 2009 我遭遇到一個很奇怪的問題,希望有經驗的人可以給我一點建議。 敝人服務的單位現在有個程式,讓我們叫他 master 好了。 這個 master 會透過 lsf/grid 在內部網路上的其他機器建立 slave 程式執行。 有點像 client/server 架構(根本就是嘛)。 這中間,master 跟 slave 需要交換資料, 交換的資料,我們都是透過 data 檔案的讀寫來完成。 而 master 跟 slave 的同步化,也是透過檔案來完成。 當 master 要告訴 slave 可以開始的時候,就會寫一個特殊的 flag 檔案, 這段時間 slave 就是不斷的 polling 去看那個檔案能不能讀了。 當然 slave 中間每一次會 sleep(1) 以避免 CPU 一直在工作。 當需要接受資料的那一方,發現一個特殊檔案已經存在了, 那表示他需要讀取的檔案已經備妥了,他就會去開啟那個檔案來讀取需要的資料。 以時間軸來畫圖的話大概就是這樣 Master Slave(s) 可能有好幾個 --------------------------------------------------------- 寫資料檔 (polling檢查flag檔案) 寫 flag ↓ (polling) 發現 flag 檔案 ↓ 開啟 data 檔案讀取資料 ↓ (進行計算...) ↓ 寫 data 檔案 ↓ 寫 flag 檔通知 master 發現 flag 檔案 (polling) 開檔,讀取 ↓ (計算) ↓ sync 的時候我們可以說平均每次會浪費掉 0.5 秒在等待, 因為中間的 sync 次數不少,所以累積起來就是一段時間, 為了改善這個部份,所以 sync 的部份就想改成用 socket 來做。 這部分我已經完成了。 果然省掉 pooling 的等待時間,效率就上升了, Master Slave(s) 可能有好幾個 --------------------------------------------------------- 寫資料檔 (block read() 接封包) 送封包 ↓ (polling) 收到封包 (block read() 接封包) 開啟 data 檔案讀取資料 ↓ (進行計算...) ↓ 寫 data 檔案[1] ↓ 送封包 收到封包 (block read() 接封包) 開檔,讀取[2] ↓ (計算) ↓ (只有把用檔案做同步化的地方改成用 socket) 問題是現在遇到一個超奇怪的問題。 當 [1] 的地方,已經把檔案寫好了,而且也 fclose() 關閉檔案了。 在 [2] 的地方,fopen 有拿到東西,不是 NULL,但是當我要讀取的時候,卻什麼也讀不到。 我呼叫 perror(),系統給的錯誤訊息是「No such file or directory.」 問題是我開檔的時候明明開到了! 事情真的很奇怪, 這個現象不是永遠都發生,只有「有時候」發生。 如果我在 [2] 之前 sleep() 一段時間, 那我就可以順利讀取到檔案。 又, 我發現這個現象只有在我的 slave 是透過 system() 啟動的時候才會發生, (因為我要派到那台機器上的 slave 可能有好幾個, 所以會有一個主要的 slave 去用 system("... %") 把其他的叫起來) 我曾經想過是不是沒有 flush() 的關係, 但是 flush() 的也沒用。 我也懷疑過是不是 fork() 導致導致兩個人搶同一個封包, 導致同步失敗,後來想一想根本不會,因為本來的程式碼用的是 system("... %")。 回頭再看看,問題真的很奇怪, fp = fopen(...) ; if (fp) { fread() // 這邊竟然就死了 } 而且竟然只要等久一點,這邊就會過, 是不是我哪邊觀念有不對,或是忽略了什麼東西? 我想了兩天已經想破頭了,但是還是想不到原因。 有沒有人有類似的經驗,或是有任何建議, 任何建議都是受到歡迎的,因為我真的想不到啦 O_Q 如果我有哪邊描述的不夠清楚,也請告訴我。 謝謝。 我的 OS: 2.6.9-67.ELsmp #1 SMP Wed Nov 7 13:56:44 EST 2007 x86_64 x86_64 x86_64 GNU/Linux Compiler: gcc version 3.4.6 20060404 (Red Hat 3.4.6-9) PS. 大概有的人會問:你為什麼不把傳資料的部份改成用 socket? 1. 因為已經有很多既有的程式碼,傳送資料的部份太多了, 同步化的程式碼被封裝起來,只需要改很少地方。 2. 交換的資料量大約是 100~200 MB, 實際存取需要的時間大概是 1~2 秒, 但是整個程式的執行時間超過十分鐘, 所以修改這邊不符合效益。 -- To iterate is human, to recurse, divine. 遞迴只應天上有, 凡人該當用迴圈.   L. Peter Deutsch -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 203.160.254.105 yoco315:轉錄至看板 LinuxDev 04/13 14:27 -- To iterate is human, to recurse, divine. 遞迴只應天上有, 凡人該當用迴圈.   L. Peter Deutsch -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 203.160.254.105

04/13 15:23, , 1F
讀或寫檔案過程前後做鎖和開鎖,你覺得如何?
04/13 15:23, 1F

04/14 00:09, , 2F
用flag做同步...您是小學生嗎
04/14 00:09, 2F

04/14 00:09, , 3F
Linux上2個process可用semaphor來做同步
04/14 00:09, 3F

04/14 00:09, , 4F
可以用message queue、named pipe
04/14 00:09, 4F

04/14 00:10, , 5F
socket來做資料傳輸,檔案很沒效率
04/14 00:10, 5F

04/14 00:44, , 6F
..原來所謂flag控制流程是小學生作法 (筆記)
04/14 00:44, 6F

04/14 00:49, , 7F
process之間的semaphor當然是變數,但你想:
04/14 00:49, 7F

04/14 00:49, , 8F
二台電腦之間semaphore是什麼? 不是在共用
04/14 00:49, 8F

04/14 00:50, , 9F
記憶體,就是在檔案裏,所以flag沒錯啊;
04/14 00:50, 9F

04/14 00:50, , 10F
當然你用message queue維護共用變數也很好.
04/14 00:50, 10F

04/14 17:35, , 11F
如果是透過NFS,試著用flock去測試看看.
04/14 17:35, 11F

04/14 17:37, , 12F
fclose可能沒有保護到nfs同步的問題
04/14 17:37, 12F

04/14 22:13, , 13F
如果你知道什麼叫做atomic、reentrant是
04/14 22:13, 13F

04/14 22:13, , 14F
什麼 再來討論吧~~
04/14 22:13, 14F

04/14 22:45, , 15F
囂張勒,比人慢推文卻強調別人沒資格跟你討論
04/14 22:45, 15F

04/14 22:45, , 16F
去去去,根本不希罕
04/14 22:45, 16F

04/14 22:46, , 17F
我沒說非用flag不可,原po也沒說非用flag不可
04/14 22:46, 17F

04/14 22:47, , 18F
卻因為flag被你嗆聲,好像你很了不起,滾開吧
04/14 22:47, 18F

04/14 22:54, , 19F
在別人沒犯錯的情況下,你不必逼人選邊站,ok?
04/14 22:54, 19F

04/14 22:58, , 20F
而且你懂reentrant也只不過是知道一個特定的
04/14 22:58, 20F

04/14 22:58, , 21F
實作法,並且知道此法的名字而已.
04/14 22:58, 21F

04/14 22:59, , 22F
需要做的時候,我也會查,然後學會怎麼實作.
04/14 22:59, 22F

04/14 23:00, , 23F
抽象來講,也還不就是廣義的flag,那你還打壓
04/14 23:00, 23F

04/14 23:00, , 24F
flag打壓得這麼爽. 你爽你自己的就好.
04/14 23:00, 24F

04/14 23:00, , 25F
干我屁事.
04/14 23:00, 25F

04/14 23:46, , 26F
而且我覺得你根本嗆錯重點了. 若我談到flag,
04/14 23:46, 26F

04/14 23:47, , 27F
我所說的flag就包含在你提到的semaphore,
04/14 23:47, 27F

04/14 23:47, , 28F
message queue, atomic,和reentrant中.
04/14 23:47, 28F

04/14 23:48, , 29F
但你一定要說"不能用flag",就讓我很不能理解
04/14 23:48, 29F

04/14 23:49, , 30F
你再會嗆,我根本不知道你嗆什麼和為什麼要嗆
04/14 23:49, 30F

04/14 23:49, , 31F
這樣就不是溝通. 事實上,我也不必跟你溝通.
04/14 23:49, 31F

04/14 23:50, , 32F
只想問,你也會像這樣嗆自己公司的同事嗎?
04/14 23:50, 32F

04/14 23:58, , 33F
我覺得平白無故在網路上互相引起血氣,這不好
04/14 23:58, 33F

04/15 00:39, , 34F
哇喔~~生氣了~好吧~~我跟你解釋一下
04/15 00:39, 34F

04/15 00:39, , 35F
我覺得你應該不知道os能夠在任何時候切換
04/15 00:39, 35F

04/15 00:40, , 36F
thread或process,就算是這樣的一個flag:
04/15 00:40, 36F

04/15 00:40, , 37F
flag =1,OS也能夠在之中切換。我想你應該
04/15 00:40, 37F

04/15 00:41, , 38F
知道race condition吧,那如果你設flag的
04/15 00:41, 38F

04/15 00:41, , 39F
時候發生context switch的時候怎麼辦呢?
04/15 00:41, 39F

04/15 00:42, , 40F
只有用semaphor或mutex才能阻止OS去存取
04/15 00:42, 40F

04/15 00:42, , 41F
這樣...這位大大應該可以消氣了吧
04/15 00:42, 41F

04/15 00:55, , 42F
樓上根本就沒看清楚原po問什么
04/15 00:55, 42F

04/15 01:01, , 43F
sem和mutex可以用來同步不同電腦上
04/15 01:01, 43F

04/15 01:01, , 44F
的兩個prcess嗎?
04/15 01:01, 44F
文章代碼(AID): #19ujjhJT (Programming)