父子進程共享文件描述符的問題解決方法 父子進程間文件描述符傳遞問題

       困擾了許久的一個問題:父子進程共享文件描述符或者說父子進程傳遞文件描述符問題   今天終於解決了!!!因此,記錄一下。

        一、問題描述:

        在linux系統,我有一個A程序,使用socket函數打開並綁定了本地端口假設是5555,然後A程序執行一個sh腳本文件,這個腳本文件會將B程序運行起來。結果,查詢端口占用情況時,A,B兩個程序都在監聽5555端口。即A程序啓動B程序時,端口發生了傳遞。我的問題是,怎樣才能防止端口傳遞?

       在Windows系統,我有一個A程序,使用socket函數打開並綁定了本地端口假設是5555,然後A程序用CreateProcess啓動一個B程序。然後用任務管理器將A程序強殺,再次啓動A程序,發現A程序無法正常啓動了,提示端口已經被佔用,無法打開。將B程序退出運行後,再啓動A程序,此時A程序可以正常啓動。我的問題是,怎樣才能防止端口傳遞?

      二、 解決辦法:

       1)創建socket時,如果是linux系統,設置FD_CLOEXEC標誌位,核心代碼如下:

    int m_sock = socket(AF_INET, SOCK_STREAM, 0);

    if (m_sock == -1)

    {

        printf("create socket failed:%s\n",strerror(errno));

    }

    ::fcntl(m_sock, F_SETFD, FD_CLOEXEC);

       2)創建socket時,如果是Windows系統,使用SetHandleInformation設置HANDLE_FLAG_INHERIT標誌位,核心代碼如下:

      SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0);

     3)我寫了一個Windows和linux設置屬性的函數,如下:

//Windows和linux

void mg_set_close_on_exec(sock_t sock) {

#if defined(_WIN32) && !defined(WINCE)

  (void) SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0);

#elif defined(__unix__)

  fcntl(sock, F_SETFD, FD_CLOEXEC);

#else

  (void) sock;

#endif

}

 

三、問題擴展

 注:libevent庫沒有處理句柄傳遞和文件描述符傳遞的問題。

 

SetHandleInformation函數介紹來自百度百科:

函數

SetHandleInformation函數:

[函數功能]

控制哪些子進程能繼承內核對象句柄,可調用SetHandleInformation函數改變內核對象句柄的繼承標誌。

[函數原型聲明]

BOOL WINAPI SetHandleInformation(

_In_ HANDLE hObject,

_In_ DWORD dwMask,

_In_ DWORD dwFlags

);

參數說明

第一個參數hObject標識了一個有效句柄。

第二個參數dwMask告訴函數我們想更改哪個或者哪些標誌:

1\ HANDLE_FLAG_INHERIT 用CreateProcess(bInheritHandle設爲TRUE)創建出來的子進程可以繼承對象句柄

2\HANDLE_FLAG_PROTECT_FROM_CLOSE 無法調用CloseHandle關閉對象句柄

第三個參數dwFlags指出希望把標誌設成什麼。

實例

例如,要打開一個內核對象句柄的繼承標誌,可以像下面這樣寫:

SetHandleInformation( hObj, HANDLE_FLAG_INHERIT ,HANDLE_FLAG_INHERIT );

要關閉這個標誌,可以像下面這樣寫:

SetHandleInformation( hObj , HANDLE_FLAG_INHERIT , 0)

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