posts - 403, comments - 310, trackbacks - 0, articles - 7
            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          APUE - File I/O (4) - Atomic Operations

          Posted on 2007-08-21 14:45 ZelluX 閱讀(528) 評論(0)  編輯  收藏 所屬分類: LinuxC/C++
          Appending to a File
           考慮某個單一進(jìn)程試圖在文件追加寫入的操作。由于早期的UNIX系統(tǒng)不支持O_APPEND選項,因此得先用lseek將offset置于文件尾部。
          if (lseek(fd, 0L, 2) < 0)
              err_sys("lseek error");
          if (write(fd, buf, 100) != 100)
              err_sys("write error");
          注意這里的lseek函數(shù)的第三個參數(shù)2等于SEEK_END常量,但是早期UNIX并沒有這個常量名(System V中才引進(jìn))

          這樣的處理在多進(jìn)程試圖在同一文件尾部追加寫入時就有可能出現(xiàn)問題。
          假設(shè)兩個獨立線程A B要在某個文件尾部追加寫入,使用了上述方法,并沒有使用O_APPEND開關(guān)。
          首 先A指向了該文件尾部(假設(shè)是offset=1500的地方),接著內(nèi)核切換到B進(jìn)程,B也指向了該尾部,然后寫入了100字節(jié),此時內(nèi)核把v-node 中當(dāng)前文件的大小改為了1600。內(nèi)核再次切換進(jìn)程,A繼續(xù)運行,調(diào)用write方法,結(jié)果就在offset=1500的地方寫入了,覆蓋了B進(jìn)程寫入的 內(nèi)容。

          這個問題其實和Java中的多線程差不多,指向文件尾部和寫入應(yīng)該作為一個原子操作執(zhí)行,就像Java中使用synchronized塊保護(hù)原子操作。使用O_APPEND選項就是一種解決方法。
          另一種解決方法時使用XSI extension中的pread和pwrite函數(shù)。
          #include <unistd.h>

          ssize_t pread(int filedes, void *buf, size_t nbytes, off_t offset);
          // Returns: number of bytes read, 0 if end of file, -1 on error

          ssize_t pwrite(int filedes, const void *buf, size_t nbytes, off_t offset);
          // Returns: number of bytes read, 0 if end of file, -1 on error

          調(diào)用pread與調(diào)用lseek后再調(diào)用read等價,以下情況除外:
          1. pread的兩個步驟無法被中斷。
          2. 文件指針尚未被更新時。

          pwrite與lseek+write的差別也相似。

          Creating a File
          當(dāng)使用O_CREAT和O_EXCL開關(guān)調(diào)用open函數(shù)時,如果文件已經(jīng)存在,則open函數(shù)返回失敗值。如果不使用這兩個開關(guān),可以這樣寫:
          if ((fd = open(pathname, O_WRONLY)) < 0) {
              
          if (errno == ENOENT) {
                  
          if ((fd = creat(pathname, mode)) < 0)
                      err_sys(
          "creat error");
              } 
          else {
                  err_sys(
          "open error");
              }
          }

          當(dāng)open函數(shù)執(zhí)行后creat函數(shù)執(zhí)行前另一個進(jìn)程創(chuàng)建了同名文件的話,該數(shù)據(jù)就會被擦除。
          主站蜘蛛池模板: 山东省| 乃东县| 隆尧县| 来安县| 屏东市| 长武县| 修文县| 涪陵区| 普安县| 天长市| 高雄县| 广州市| 綦江县| 建瓯市| 楚雄市| 白银市| 海晏县| 内乡县| 涡阳县| 河西区| 远安县| 志丹县| 大悟县| 辽源市| 南平市| 陵川县| 探索| 藁城市| 偃师市| 大连市| 鹤峰县| 本溪市| 泽普县| 道真| 鄂尔多斯市| 万载县| 黄龙县| 临夏市| 河池市| 新和县| 绥滨县|