linux管道原子性写入,write(2)/ read(2)linux中进程之间的原子性
我有一個案例,有兩個進程作用于同一個文件 – 一個作為作者,一個作為讀者.該文件是一行文本文件,編寫器在循環(huán)中重寫該行.讀者讀取該行.偽代碼如下所示:
作家過程
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字節(jié)的大小,寫入將是原子的.但是從我的實驗來看,看起來原子性只有16個字節(jié).
man page沒有說正常文件的原子性,它只提到512字節(jié)的管道原子性.
我用tmpfs和ext4嘗試了這個,結(jié)果是一樣的.使用O_SYNC,ext4寫入變?yōu)樵硬⑶椅依斫馑?因為寫入在它到達(dá)磁盤之前不會返回,但是O_SYNC對tmpfs(/ dev / shm)沒有幫助.
解決方法:
POSIX不對read和write的原子操作提供任何最低保證,除了在管道上寫入(其中寫入高達(dá)PIPE_BUF(≥512)字節(jié)保證是原子的,但讀取沒有原子性保證).讀取和寫入操作以字節(jié)值描述;除了管道之外,與圍繞單字節(jié)寫操作的循環(huán)相比,寫操作不提供額外的保證.
我不知道Linux會給出任何額外的保證,無論是16還是512.在實踐中,我希望它依賴于內(nèi)核版本,文件系統(tǒng),以及可能還有其他因素,如底層塊設(shè)備, CPU數(shù)量,CPU架構(gòu)等
O_SYNC,O_RSYNC和O_DSYNC保證(synchronized I/O data integrity completion,在POSIX的可選SIO功能中讀取和寫入)不是您所需要的.它們保證在讀取或?qū)懭胂到y(tǒng)調(diào)用之前將寫入提交到持久存儲,但不對在讀取操作正在進行時啟動的寫入做出任何聲明.
在您的方案中,讀取和寫入文件看起來不像正確的工具集.
>如果您只需要傳輸少量數(shù)據(jù),請使用管道.不要過于擔(dān)心復(fù)制:在大多數(shù)處理或上下文切換的規(guī)模上復(fù)制內(nèi)存中的數(shù)據(jù)非常快.另外Linux非常適合優(yōu)化副本.
>如果需要傳輸大量數(shù)據(jù),則應(yīng)該使用某種形式的內(nèi)存映射:如果不需要磁盤支持,則為共享內(nèi)存段;如果是,則為mmap.這并不能神奇地解決原子性問題,但可能會提高正確同步機制的性能.要執(zhí)行同步,有兩種基本方法:
>生產(chǎn)者將數(shù)據(jù)寫入共享內(nèi)存,然后向消費者發(fā)送通知,準(zhǔn)確指出可用的數(shù)據(jù).消費者僅根據(jù)請求處理數(shù)據(jù).通知可以使用相同的信道(例如mmap msync)或不同的信道(例如管道).
>生產(chǎn)者將數(shù)據(jù)寫入共享內(nèi)存,然后刷新寫入(例如msync).然后,生產(chǎn)者將一個眾所周知的值寫入一個機器字(sig_atomic_t通常會起作用,即使其原子性僅在信號上正式保證 – 或者,實際上是uintptr_t).消費者讀取一個機器字,并且只有當(dāng)該字具有可接受的值時才處理相應(yīng)的數(shù)據(jù).
標(biāo)簽:filesystems,linux,tmpfs
來源: https://codeday.me/bug/20190623/1270109.html
總結(jié)
以上是生活随笔為你收集整理的linux管道原子性写入,write(2)/ read(2)linux中进程之间的原子性的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: arm架构的linux芯片方案,ARM推
- 下一篇: 小米kali linux蓝牙,小米筆記本