linux管道原子性写入,write(2)/ read(2)linux中进程之间的原子性
我有一個案例,有兩個進程作用于同一個文件 – 一個作為作者,一個作為讀者.該文件是一行文本文件,編寫器在循環中重寫該行.讀者讀取該行.偽代碼如下所示:
作家過程
char buf[][18] = {
"xxxxxxxxxxxxxxxx",
"yyyyyyyyyyyyyyyy"
};
i = 0;
while (1) {
pwrite(fd, buf[i], 18, 0);
i = (i + 1) % 2;
}
讀者流程
while(1) {
pread(fd, readbuf, 18, 0);
//check if readbuf is either buf[0] or buf[1]
}
運行兩個進程一段時間后,我可以看到readbuf是xxxxxxxxxxxxxxxxyy或yyyyyyyyyyyyyyyyxx.
我的理解是,對于大小為512字節的大小,寫入將是原子的.但是從我的實驗來看,看起來原子性只有16個字節.
man page沒有說正常文件的原子性,它只提到512字節的管道原子性.
我用tmpfs和ext4嘗試了這個,結果是一樣的.使用O_SYNC,ext4寫入變為原子并且我理解它,因為寫入在它到達磁盤之前不會返回,但是O_SYNC對tmpfs(/ dev / shm)沒有幫助.
解決方法:
POSIX不對read和write的原子操作提供任何最低保證,除了在管道上寫入(其中寫入高達PIPE_BUF(≥512)字節保證是原子的,但讀取沒有原子性保證).讀取和寫入操作以字節值描述;除了管道之外,與圍繞單字節寫操作的循環相比,寫操作不提供額外的保證.
我不知道Linux會給出任何額外的保證,無論是16還是512.在實踐中,我希望它依賴于內核版本,文件系統,以及可能還有其他因素,如底層塊設備, CPU數量,CPU架構等
O_SYNC,O_RSYNC和O_DSYNC保證(synchronized I/O data integrity completion,在POSIX的可選SIO功能中讀取和寫入)不是您所需要的.它們保證在讀取或寫入系統調用之前將寫入提交到持久存儲,但不對在讀取操作正在進行時啟動的寫入做出任何聲明.
在您的方案中,讀取和寫入文件看起來不像正確的工具集.
>如果您只需要傳輸少量數據,請使用管道.不要過于擔心復制:在大多數處理或上下文切換的規模上復制內存中的數據非???另外Linux非常適合優化副本.
>如果需要傳輸大量數據,則應該使用某種形式的內存映射:如果不需要磁盤支持,則為共享內存段;如果是,則為mmap.這并不能神奇地解決原子性問題,但可能會提高正確同步機制的性能.要執行同步,有兩種基本方法:
>生產者將數據寫入共享內存,然后向消費者發送通知,準確指出可用的數據.消費者僅根據請求處理數據.通知可以使用相同的信道(例如mmap msync)或不同的信道(例如管道).
>生產者將數據寫入共享內存,然后刷新寫入(例如msync).然后,生產者將一個眾所周知的值寫入一個機器字(sig_atomic_t通常會起作用,即使其原子性僅在信號上正式保證 – 或者,實際上是uintptr_t).消費者讀取一個機器字,并且只有當該字具有可接受的值時才處理相應的數據.
標簽:filesystems,linux,tmpfs
來源: https://codeday.me/bug/20190623/1270109.html
總結
以上是生活随笔為你收集整理的linux管道原子性写入,write(2)/ read(2)linux中进程之间的原子性的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: arm架构的linux芯片方案,ARM推
- 下一篇: 吉大18秋学期C语言作业二答案,吉大18