關於開啟檔案時O_APPEND標誌的作用

來源:互聯網
上載者:User

       首先給出一段程式,這段程式的本來目的是為了驗證用O_APPEND標誌開啟檔案後,調用lseek(fd, 0, SEEK_CUR)應該返迴文件長度,但是運行程式後發現錯了。注意加紅的兩句,本來希望分別輸出0和49,但實際輸出都是零。

#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <unistd.h>int main(void){    int fd;    off_t off;    printf("Not using O_APPEND:\n");    fd = open("./test.c", O_WRONLY);    off = lseek(fd, 0, SEEK_SET);    printf("The offset of SEEK_SET is %d.\n", off);    close(fd);            fd = open("./test.c", O_WRONLY);    off = lseek(fd, 0, SEEK_END);    printf("The offset of SEEK_END is %d.\n", off);    close(fd);        fd = open("./test.c", O_WRONLY);    off = lseek(fd, 0, SEEK_CUR);    printf("The offset of SEEK_CUR is %d.\n", off);    close(fd);        printf("Using O_APPEND:\n");    fd = open("./test.c", O_WRONLY | O_APPEND);    off = lseek(fd, 0, SEEK_SET);    printf("The offset of SEEK_SET is %d.\n", off);    close(fd);        fd = open("./test.c", O_WRONLY | O_APPEND);    off = lseek(fd, 0, SEEK_END);    printf("The offset of SEEK_END is %d.\n", off);    close(fd);        fd = open("./test.c", O_WRONLY | O_APPEND);    off = lseek(fd, 0, SEEK_CUR);    printf("The offset of SEEK_CUR is %d.\n", off);    close(fd);    exit(0);}

輸出為:

Not using O_APPEND:
The offset of SEEK_SET is 0.
The offset of SEEK_END is 49.
The offset of SEEK_CUR is 0.
Using O_APPEND:
The offset of SEEK_SET is 0.
The offset of SEEK_END is 49.
The offset of SEEK_CUR is 0.

原本以為O_APPEND把檔案指標移到了檔案尾,以方便從檔案尾添加資料,但這麼看來不對,檔案指標並沒有移動。問題出在哪裡呢?

從APUE中得到答案:

       每個進程有一個開啟檔案描述符表,而該表的表項中有一個檔案狀態標誌,當前檔案位移量和一個v節點指標,v節點指標指向一個v節點表,而該表中的i節點資訊中有一個當前檔案長度。

       對於lseek來說,它直接修改檔案描述符表項中的當前檔案位移量,並返回當前的檔案位移量,而對於O_APPEND標誌,則只是將其設定到了檔案表項的檔案狀態標誌中,此時當前檔案位移量並未修改,仍然為0,只有當使用者企圖寫入檔案時,才將檔案當前位移量置為檔案長度。這從另一個角度說明,如果檔案以O_APPEND標誌開啟,則lseek對該檔案的寫將不起作用,因為無論lseek怎樣調整當前檔案位移量,在寫入時仍然會被設為檔案長度而將內容添加在檔案尾。例如如下程式:

#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <unistd.h>int main(void){        int fd;        off_t off;        fd = open("./test.c", O_WRONLY | O_APPEND);        off = lseek(fd, 3, SEEK_SET);        write(fd, "a", 1);        printf("The offset of SEEK_SET is %d.\n", off);        close(fd);        exit(0);}

輸出為:

The offset of SEEK_SET is 3.

        可見,lseek修改了當前檔案位移量,但是,查看test.c檔案,a卻添加在了檔案尾,驗證了上面的內容。但是,對於讀來說,O_APPEND就不起作用了,如下面的程式:

#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <unistd.h>int main(void){        int fd;        char buf[3];        off_t off;        fd = open("./test.c", O_RDONLY | O_APPEND);        off = lseek(fd, 3, SEEK_SET);        read(fd, buf, 2);        buf[2] = '\0';        printf("%s\n", buf);        printf("The offset of SEEK_SET is %d.\n", off);        close(fd);        exit(0);}

輸出為:

cl
The offset of SEEK_SET is 3.

程式讀到了檔案位移量為3處的兩個字元。

        可見,OAPPEND標誌的主要作用就是保證在多進程寫入時,保證每個進程寫入的內容都的確添加在了檔案尾,因為不管有幾個進程,在他們寫同一個檔案時,都會首先將當前檔案位移量修改為此時此刻的檔案長度,這就保證了檔案寫入的原子性。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.