使用FD_CLOEXEC實現close-on-exec,關閉子程式無用檔案描述符

中下游國外我發表於2016-10-24

http://blog.csdn.net/chrisniu1984/article/details/7050663


我們經常會碰到需要fork子程式的情況,而且子程式很可能會繼續exec新的程式。這就不得不提到子程式中無用檔案描述符的問題!


fork函式的使用本不是這裡討論的話題,但必須提一下的是:子程式以寫時複製(COW,Copy-On-Write)方式獲得父程式的資料空間、堆和棧副本,這其中也包括檔案描述符。剛剛fork成功時,父子程式中相同的檔案描述符指向系統檔案表中的同一項(這也意味著他們共享同一檔案偏移量)。


接著,一般我們會呼叫exec執行另一個程式,此時會用全新的程式替換子程式的正文,資料,堆和棧等。此時儲存檔案描述符的變數當然也不存在了,我們就無法關閉無用的檔案描述符了。所以通常我們會fork子程式後在子程式中直接執行close關掉無用的檔案描述符,然後再執行exec。


但是在複雜系統中,有時我們fork子程式時已經不知道開啟了多少個檔案描述符(包括socket控制程式碼等),這此時進行逐一清理確實有很大難度。我們期望的是能在fork子程式前開啟某個檔案控制程式碼時就指定好:“這個控制程式碼我在fork子程式後執行exec時就關閉”。其實時有這樣的方法的:即所謂的 close-on-exec。


 close-on-exec的實現只需要呼叫系統的fcntl就能實現,很簡單幾句程式碼就能實現:

  1. int fd=open("foo.txt",O_RDONLY);  
  2. int flags = fcntl(fd, F_GETFD);  
  3. flags |= FD_CLOEXEC;  
  4. fcntl(fd, F_SETFD, flags);  

這樣,當fork子程式後,仍然可以使用fd。但執行exec後系統就會欄位關閉子程式中的fd了。


-------------------------------------------------------- 分割線 ------------------------------------------------------------------------------------

最近好好看了一下open函式,其中flags引數可以傳入O_CLOEXEC標記 [注意:linux 2.6.23才開始支援此標記]

這樣就可以一步實現上面的提到的close-on-exec的效果。

相關文章