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

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

          Posted on 2007-08-21 14:45 ZelluX 閱讀(523) 評論(0)  編輯  收藏 所屬分類: LinuxC/C++
          Appending to a File
           考慮某個單一進程試圖在文件追加寫入的操作。由于早期的UNIX系統不支持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函數的第三個參數2等于SEEK_END常量,但是早期UNIX并沒有這個常量名(System V中才引進)

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

          這個問題其實和Java中的多線程差不多,指向文件尾部和寫入應該作為一個原子操作執行,就像Java中使用synchronized塊保護原子操作。使用O_APPEND選項就是一種解決方法。
          另一種解決方法時使用XSI extension中的pread和pwrite函數。
          #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

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

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

          Creating a File
          當使用O_CREAT和O_EXCL開關調用open函數時,如果文件已經存在,則open函數返回失敗值。如果不使用這兩個開關,可以這樣寫:
          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");
              }
          }

          當open函數執行后creat函數執行前另一個進程創建了同名文件的話,該數據就會被擦除。
          主站蜘蛛池模板: 株洲县| 凌源市| 海林市| 台安县| 南郑县| 锡林郭勒盟| 当雄县| 普格县| 丰顺县| 松溪县| 磐安县| 梅河口市| 平乡县| 正宁县| 雅安市| 双城市| 裕民县| 襄樊市| 长治县| 呈贡县| 呼伦贝尔市| 武定县| 盘山县| 永川市| 本溪| 兴化市| 邵阳市| 亚东县| 平泉县| 衡水市| 辉南县| 扶余县| 庐江县| 樟树市| 黄石市| 丹阳市| 闵行区| 旅游| 元江| 松潘县| 双流县|