關於文件描述符的close-on-exec標誌位

引言

我們在使用一些系統調用對文件描述符進行操作時,常常會碰到是否爲文件描述符賦予CLOEXEC屬性的情況,例如:

// open函數中的flags參數可指定O_CLOEXEC標誌
int open(const char *pathname, int flags);

// fcntl函數可通過FD_GETFD、FD_SETFD操作設置FD_CLOEXEC標誌
int fcntl(int fd, int cmd, ... /* arg */);

在上篇博客,我們新學到的系統調用eventfd同樣也有:
// 參數flags可取EFD_NONBLOCK、EFD_CLOEXEC、EFD_SEMAPHORE
int eventfd(unsigned int initval, int flags);

那麼,close-on-exec標誌位究竟有什麼用呢?

設置close-on-exec標誌位的意義

close-on-exec字面意思即執行時關閉。進程中每個打開的描述符都有一個執行時關閉標誌,若設置此標誌,則在執行exec時關閉該描述符,否則該描述符仍打開。

設置該標誌位的重要意義在於它可以方便我們關閉無用的文件描述符

我們考慮這樣的情況:父進程fork出一個子進程,子進程是父進程的副本,獲得父進程的數據空間、堆和棧的副本,當然也包括父進程打開的文件描述符。

fork之後一般我們會調用exec執行另一個程序,此時會用全新的程序替換子進程的正文、數據、堆和棧等,此時保存文件描述符的變量當然也不存在了,我們就無法關閉無用的文件描述符了。所以通常我們會在fork子進程後,在子進程中直接執行close關掉無用的文件描述符,然後再執行exec。

但是在複雜系統中,有時我們fork出子進程時已經不知道打開了多少文件描述符了(包括socket句柄等),如果進行逐一清理難度很大。我們期望的是能在fork出子進程前、打開某個文件描述符時就指定好——這個文件描述符在我fork出子進程後、執行exec時就關閉。其實是有這樣的方法的:即所謂的 close-on-exec。

測試代碼

#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

int main()
{
    int fd;
    pid_t pid;
// 判斷是否定義_O_CLOEXEC宏
#ifdef _O_CLOEXEC
    if ((fd = open("my.txt", O_RDWR | O_CREAT | O_CLOEXEC, 0600)) < 0) 
#else
    if ((fd = open("my.txt", O_RDWR | O_CREAT, 0600)) < 0) 
#endif
        perror("open");
// 通過開啓-D_O_CLOEXEC -D_FORK編譯選項測試使用O_CLOEXEC模式的描述符在子進程中的狀態
#ifndef _FORK 
    // 執行execl後進程名更改爲sleep
    if (execl("/bin/sleep", "sleep", "10000", (void*)0) < 0)
        perror("execl");
#else
 switch ((pid = fork())) {
        case -1:
            perror("fork");
        case 0:
            if (execl("/bin/sleep", "sleep", "10000", (void*)0) < 0)
                perror("execl");
        default:
            sleep(10000);
            break;
    }
#endif

    return 0;
}

測試結果

1.(1)編譯進O_CLOEXEC選項

這裏寫圖片描述

這裏寫圖片描述

進程資源中沒有了my.txt

(2)不編譯進O_CLOEXEC選項

這裏寫圖片描述

這裏寫圖片描述

進程資源中仍有my.txt

2.編譯進O_CLOEXEC選項、_FORK選項

這裏寫圖片描述

這裏寫圖片描述

子進程資源中沒有了my.txt,父進程中仍存在。


參考資料:
http://blog.csdn.net/chrisniu1984/article/details/7050663
http://blog.csdn.net/ubuntu_hao/article/details/51393632

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章