国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 服務(wù)器 > Linux服務(wù)器 > 正文

Linux:write調(diào)用的原子性

2024-09-05 23:01:20
字體:
供稿:網(wǎng)友

UNIX環(huán)境高級編程中關(guān)于原子操作的介紹,其中有一種情形是在文件尾端添加數(shù)據(jù)。文中說,如果多個進(jìn)程都需要將數(shù)據(jù)添加到某一文件,那么為了保證定位和寫數(shù)據(jù)這兩步是一個原子操作,需要在打開文件時設(shè)置O_APPEND標(biāo)志,看到這里我們就會想,雖然保證了定位和寫數(shù)據(jù)是一個原子操作,但是是否能夠保證多個進(jìn)程或線程寫入的數(shù)據(jù)不會交錯呢,比如A進(jìn)程調(diào)用write(filedes1, "AAA", 3),B進(jìn)程調(diào)用write(filedes2, "BBBB", 4)(其中filedes1和filedes2指向同一個文件),但是最后文件中的數(shù)據(jù)是否有可能是AABBBAB,如果這個文件是一個管道或socket呢。linux man手冊頁中關(guān)于write調(diào)用的說明很不詳細(xì),并未說明寫操作是否是原子的,所以我們有必要查找Single UNIX Specification(SUS)對write調(diào)用的說明,在SUS中對此調(diào)用的說明還是比較詳細(xì)的。在繼續(xù)討論之前我們需要清楚內(nèi)核在寫文件之前會對該文件加鎖,不管是否成功完成寫操作,在返回之前都會解鎖。下面我們就以三種常見的文件根據(jù)SUS標(biāo)準(zhǔn)來討論上面提出的這個問題:

1.普通文件
SUS中也沒有說明在寫普通文件時是否會保證是原子操作,但是它說明了write調(diào)用可能并不能完全把我們需要寫入的數(shù)據(jù)寫到文件中去,那么什么情況下可能少寫數(shù)據(jù)呢?SUS說明了兩種情況:磁盤已滿或則要寫入的文件的大小超過了當(dāng)前進(jìn)程的文件大小限制。其實至少還有一種情況,那就是內(nèi)核中的高速緩存不夠用的時候,比如linux內(nèi)核在發(fā)現(xiàn)高速緩存不夠用的時候就只寫入實際能夠容下的數(shù)據(jù)然后返回。正是由于存在上述最后一種情況,所以說按照APUE那種方法在linux下面寫文件并不能保證我們的數(shù)據(jù)不會交錯(不過我們可以根據(jù)write的返回值得知是否有發(fā)生交錯的可能)。其它的unix內(nèi)核可能會在實現(xiàn)上不同于linux內(nèi)核,他們可能在寫之前就判斷一下緩沖區(qū)是否足夠容納所有數(shù)據(jù),如果是這種情況,寫操作應(yīng)該就是原子的;也可能寫了一部分?jǐn)?shù)據(jù)后才發(fā)現(xiàn)緩沖區(qū)不夠用并讓當(dāng)前進(jìn)程進(jìn)入睡眠狀態(tài),此時內(nèi)核如果解鎖,那么在當(dāng)前進(jìn)程睡眠期間其它進(jìn)程可能寫了數(shù)據(jù),如果不解鎖,那么就是原子操作,其他進(jìn)程不可能在這個時候?qū)懭霐?shù)據(jù)。由上面的分析可知,正是由于SUS標(biāo)準(zhǔn)不太完整的標(biāo)準(zhǔn),我們不能確定一定可以按APUE的方法來同時向同一個普通文件寫數(shù)據(jù)。如果我們非要在同一個文件中記錄多個進(jìn)程產(chǎn)生的數(shù)據(jù),我們最好采用unix日志系統(tǒng)采用的方法,用一個專用進(jìn)程處理文件IO,其它進(jìn)程把需要寫的數(shù)據(jù)發(fā)送給這個專用進(jìn)程,這樣應(yīng)該比多個進(jìn)程同時寫一個文件可靠和高效。


2.管道
SUS對管道的寫操作說得更多也更明確,我們只需遵照其標(biāo)準(zhǔn)就可以了。對于write(pipefd, buf, nbyte),其要點如下:
如果nbyte <= PIPE_BUF,不管O_NONBLOCK是否設(shè)置,其寫操作都是原子的,就是說多個進(jìn)程都在此條件下同時寫同一個管道不會引起數(shù)據(jù)交錯。
如果nbyte > PIPE_BUF,是不能保證寫操作是原子的,寫入的數(shù)據(jù)可能與其他進(jìn)程寫入的數(shù)據(jù)交錯。

3.socket
SUS中對于寫socket并沒有說很多,我們無法從標(biāo)準(zhǔn)中得知write是否保證寫操作的原子性。我看了一下linux 2.6.14內(nèi)核關(guān)于tcp數(shù)據(jù)的寫操作,發(fā)現(xiàn)它不是原子的,也從網(wǎng)上查到了這部分代碼的作者(們)對這個問題的看法,他(們)認(rèn)為對一個可能永久阻塞的操作保證原子性是錯誤的。我們也只能姑且這么認(rèn)為了。

補充:

對于用UNIX日志系統(tǒng)服務(wù)器的方法,連接端必須每個線程connect一次logsvr,這樣才能保證發(fā)過來的日志數(shù)據(jù)不互相錯亂,保證原子性;此時logsvr只要用reactor方法來處理每個線程的連接就好,把這些fd放到隊列里輪流處理,寫文件,也保證了寫文件的原子性。

實際上日志服務(wù)器一般都是用UDP來完成的。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 乌拉特前旗| 文成县| 交口县| 大宁县| 康保县| 原阳县| 丰宁| 长葛市| 大足县| 宕昌县| 来宾市| 囊谦县| 莲花县| 尤溪县| 浙江省| 平顺县| 阜阳市| 保亭| 辰溪县| 平江县| 永泰县| 平泉县| 寿宁县| 桓台县| 绥德县| 花莲市| 铁力市| 汤原县| 博乐市| 且末县| 吐鲁番市| 灵丘县| 鹿泉市| 延川县| 平原县| 克拉玛依市| 迁安市| 安龙县| 靖边县| 长岛县| 惠安县|