關於檔案描述符的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
相關文章
- APUE 3-11 對於指定的描述符列印檔案標誌
- 使用FD_CLOEXEC實現close-on-exec,關閉子程式無用檔案描述符
- oracle 關於-日誌檔案Oracle
- 基於檔案描述符的恢復
- 關於C++的標頭檔案C++
- 關於HBase的日誌檔案和HFile
- 關於solairs10的檔案描述符問題及設定AI
- Linux--檔案描述符、檔案指標、索引節點Linux指標索引
- 關於傳送Http標頭檔案HTTP
- C語言關於標頭檔案的使用C語言
- 檔案描述符和檔案系統
- 日誌檔案和歸檔日誌檔案的關係以及如何切換日誌
- 關於SQL Server 2000的日誌檔案壓縮SQLServer
- ASM的優點總結--關於日誌檔案調整ASM
- Linux檔案描述符Linux
- 重做日誌檔案的相關操作
- 檔案描述符、開啟檔案表以及inode
- Linux下檔案描述符Linux
- 關於oracle的控制檔案Oracle
- 12C關於CDB、PDB 日誌檔案redo log的總結
- 檔案包含之包含了Linux檔案描述符Linux
- 檔案描述符恢復rm掉的dbf
- 使用檔案描述符恢復誤刪除的資料檔案
- 關於歸檔日誌的切換測試
- windows 檔案描述符 _open_osfhandleWindows
- 關於控制檔案的總結
- Linus關於核心標頭檔案與核心原始碼關係的論述(轉)原始碼
- 關於PDF檔案解密解密
- 關於 ylepub 檔案格式
- oracle 關於--控制檔案Oracle
- Linux 檔案描述符和重定向Linux
- dup函式:複製檔案描述符函式
- 如何將日誌檔案和二進位制檔案快速匯入HDFS?
- mysqlbinlog 處理二進位制日誌檔案的工具MySql
- 配置SSH的對等性傳送ORACLE錯位的歸檔日誌檔案Oracle
- 關於ubuntu修改hosts檔案的方法Ubuntu
- 關於Play框架的靜態檔案框架
- mysql關於ibdata檔案的理解MySql