2013-08-23 29 views
3

當直接寫入/ dev中的設備時,我打開文件描述符並執行UNIX write(),然後執行read()。我可以讓多個線程在相同的文件描述符上執行write()/ read()序列,並且如果兩個線程同時進入write()函數,不會獲取混亂的數據嗎?將數據發送到設備時讀取()/寫入()的原子性

對std文檔的引用將非常有幫助。儘管如此,我還是無法找到任何東西。有人提到這種操作在內核中是原子的,但我很懷疑。

另外,爲了說明這是/ dev中的一個文件,所以對於「文件指針」概念在這裏適用的程度有所瞭解也很有幫助。

+0

[此問題](http://stackoverflow.com/q/5268307/315052)與您的相關。 – jxh

+0

是的,我明白在一個普通文件上這樣做會改變文件指針,並且可以混合使用。這不是一個文件,它是/ dev中的一個設備。 – wlformyd

+3

如果由多個線程輸入,設備驅動程序本身必須確保狀態保持一致。這就是文件系統'read' /'write'的功能。 – jxh

回答

1

文件指針(例如FILE *fp)是位於函數調用上方的用戶端代碼(例如write())中的一個圖層。對fp的訪問是由線程環境中的鎖控制的(您無需線程同時修改相同的結構)。

在內核中,我希望在文件描述符(和/或「打開文件描述」)上存在一個鎖,以防止它一次從兩個線程中使用。

你可以看一下在POSIX規範read()getchar_unlocked() 瞭解更多有關鎖定等 - 至少一個POSIX兼容的實現。

請注意,POSIX仍然使用C99。因此,它不瞭解C11線程的設施。 C11標準沒有read()等(使用文件描述符的文件I/O),所以它沒有提到這種系統調用。它也沒有提供getchar_unlocked()或它的任何親戚。

1

警告:我有一段時間沒有進入內核,但這是它用來工作的方式。

對於磁盤文件:
你可以打開追加模式的文件,寫塊大小<= BLKSIZE

在POSIX環境中,足夠小的塊大小可以保證在POSIX環境中進行原子寫入(實際上,限制可能會大於BLKSIZE ...我懶得搜索替代符號)。

附加保證尋求到文件的末尾......支持尋找的設備。結合原子寫入你應該是金。

在假設一些「外來」信息可能隨之而來的情況下,每個緩衝區都必須自行維護。

對於ttys:
追加模式在這裏沒有意義。像以前一樣,但注意行結尾變得更加重要。這非常不適用於閱讀。作爲控制序列的代碼如果即使序列允許在塊之間進行分割的模式也可以讓你啓動。

對於其他設備:
在這裏可能會變得棘手。取決於設備。

1

我打算假定您指的是通用字符設備(例如,一個tty),因爲你不是特定的。據我所知,每個fd類型的操作(例如read()/ write())直接映射到驅動程序中。因此,驅動程序將作爲一個整體接收每個write()的數據塊,並在完成之前不會看到下一個數據塊(例如,將數據排隊傳輸)。但是,如果驅動程序一次不消耗整個數據塊(即write()返回小於指定的字節數,那麼不能保證該線程能夠再次寫入另一個線程之前其餘做了不同的write()。

而且,喬納森·萊弗勒指出,如果你使用標準I/O與過程級的緩衝,全盤皆輸。

底線,如果你是使用直接fd寫入,每次寫入將直接映射到一個驅動程序函數調用。從那裏,它是由驅動程序來決定寫入是否是原子的。

編輯: wlformyd提出了在多個處理器上的多個線程之間鎖定的問題。據我所知,在FD上沒有鎖定,事實上,由於可以使用多個FD來訪問相同的設備,所以這將是無效的。

我認爲這取決於驅動程序本身進行鎖定以防止爭用內部隊列和/或硬件。在這個意義上,在多處理器系統上,內核不會阻止多個同時訪問驅動程序的寫入例程。但是,正確寫入的驅動程序應該執行鎖定以防止在兩個寫入調用之間混合輸出。

+0

因此,當在sys_write中調用驅動程序的寫入函數時,它將鎖定文件描述符,因此這部分操作符是原子的。正確? – wlformyd

相關問題