2011-08-29 60 views

回答

10

雖然OS不會崩潰,並且文件系統不會被破壞,呼籲write()保證的廣告是原子,除非有問題的文件描述符是一個管道,數據量是寫入的是PIPE_MAX字節或更少。的the standard相關部分:

嘗試寫一個管道或FIFO有幾個主要特點:

  • 原子/非原子:寫是原子的,如果寫在一個操作中的全部金額不與來自任何其他進程的數據交錯。當有多個寫入者將數據發送給單個閱讀器時,這非常有用。應用程序需要知道有多大的寫入請求可以被期望以原子方式執行。這個最大值被稱爲{PIPE_BUF}。 IEEE Std 1003.1-2001的這一卷沒有說明大於{PIPE_BUF}字節的寫請求是否是原子的,但是要求{PIPE_BUF}或更少字節的寫入是原子的。

[...]

因此,在原則上,你必須同時鎖定的作家,或者你寫入的數據可能會混淆和亂序(甚至相同的寫入內)或你可能有多個寫入相互覆蓋。然而,有一個例外 - 如果你通過O_APPEND,你寫將得到有效原子:

如果文件狀態標誌的O_APPEND標誌設置,文件偏移應被設置爲文件結束前對於每次寫入,在改變文件偏移和寫入操作之間不會發生中間文件修改操作。

雖然這並不一定是原子相對於非O_APPEND寫,或同時讀取,如果所有的作家使用O_APPEND,和你做一個read前莫名其妙地同步,你應該沒問題。

+0

我不認爲'O_APPEND'使寫入原子化。您所引用的所有內容都表明,寫入將始終發生在文件末尾。與'O_APPEND'同時寫入的兩個進程不會破壞對方的寫入,但它們仍然可以交錯進行。 –

+0

@R ..這是真的,但是如果兩個進程每個都發出一個單獨寫入PIPE_BUF字節或更少的字節到與O_APPEND打開的同一個文件(兩端),那麼這些寫入將不會交織 – bdonlan

+0

O_APPEND文本沒有任何內容與管道有關。管道總是附加的。該文本是關於普通文件的,PIPE_BUF文本不適用於普通文件。 –

1

當然,內核會正確處理它,因爲內核的正確性 - 這是正確的定義。

如果你有一套coöperatingflockers,那麼你可以使用內核來排隊大家。但請記住,羣與I/O無關:它不會阻止其他人寫入文件。它至多隻會干擾其他植物。

2

write(和writev)也保證原子性。

這意味着如果兩個線程或進程同時寫入,則不能保證哪一個先寫入。 但是你確實保證一個系統調用中的任何內容都不會與另一個系統調用的數據混合在一起。

只要始終正常工作,但不一定如您所期望的那樣(如果您認爲過程A出現在過程B之前)。

+0

我唯一的要求是,如果線程-A寫入一堆線(比如線-A)並且線程-B寫入一組線(比如線-B),則輸出是整行-A後跟線-B或整行-B後面跟着-A。我不想讓一半的行-A寫在行間-B。只要A線和B線完全承諾,而其他線程不會在其中間輸出它,我不在乎。我不關心線-A和線-B之間的相關順序的順序。 (線A,線B)是可以接受的。 (line-B,lines-A)也是可以接受的 – user855

+0

'write'和'writev'保證原子性只有管道或FIFO小於'PIPE_MAX'的寫入,我相信 - 除非您另有引用。 – bdonlan

+1

@bdonlan:例如'writev'的這個措辭(沒有爲'write'搜索):_「由readv()和writev()執行的數據傳輸是原子的:writev )被寫爲一個單獨的塊,與其他進程中的寫入輸出不混合(但請參閱管道(7)中的例外情況)「@ – Damon

1

當然,它會正常工作。它不會使操作系統或進程崩潰。

它是否有意義取決於應用程序的寫入方式和文件的用途。

如果文件被所有進程打開爲append-only,則每個進程(在概念上)在每次寫入之前執行原子對齊操作;這些保證不會覆蓋彼此的數據(但當然,順序是不確定的)。

在任何情況下,如果您使用一個可能會將單個邏輯寫入分割爲多個寫入系統調用的庫,可能會出現問題。

0

write()writev()read()readv()可以生成部分寫入/讀出,其中所傳送的數據量小於被請求的是什麼小。

報價爲writev() Linux手冊頁:

注意,這並不是一個成功的調用比傳輸的字節數更少的錯誤要求

引述POSIX手冊頁:

如果write()在成功寫入一些數據後被信號中斷,它將返回寫入的字節數。

AFAIU,O_APPEND幫助在這方面,因爲它沒有阻止部分寫道:它不僅保證,無論數據被寫入到文件的末尾附加。

看到這個bug report from the Linux kernel

一種方法是寫一個消息文件。 [...]寫入可以分成兩部分。 [...]所以如果信號到達,寫入被中斷。 [...]這是完全合法的行爲,儘可能規範(POSIX,SUS,...)而言

FIFO和PIPE寫入小於PIPE_MAX但保證是原子的。

相關問題