父子进程共享文件描述符的问题解决方法 父子进程间文件描述符传递问题

       困扰了许久的一个问题:父子进程共享文件描述符或者说父子进程传递文件描述符问题   今天终于解决了!!!因此,记录一下。

        一、问题描述:

        在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)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值