Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/.htaccess/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 从C+;启动Linux服务时避免套接字继承+;应用_C++_Linux_Sockets_Boost_Boost Asio - Fatal编程技术网

C++ 从C+;启动Linux服务时避免套接字继承+;应用

C++ 从C+;启动Linux服务时避免套接字继承+;应用,c++,linux,sockets,boost,boost-asio,C++,Linux,Sockets,Boost,Boost Asio,我有一个Linux服务(守护进程),它有多个线程,并使用boost io_服务监听TCP套接字。当我在该套接字上收到某条消息时,我想启动另一个服务,例如/etc/init.d/corosync start 问题是,在启动服务后,当我退出自己的服务时,另一个服务从我自己的服务继承了套接字,并且它仍然处于一种奇怪的状态,我无法以通常的方式停止它 在退出我的进程“MonitorSipServer”之前,打开的套接字显示如下: netstat -anop |grep 144 tcp 0

我有一个Linux服务(守护进程),它有多个线程,并使用boost io_服务监听TCP套接字。当我在该套接字上收到某条消息时,我想启动另一个服务,例如
/etc/init.d/corosync start

问题是,在启动服务后,当我退出自己的服务时,另一个服务从我自己的服务继承了套接字,并且它仍然处于一种奇怪的状态,我无法以通常的方式停止它

在退出我的进程“MonitorSipServer”之前,打开的套接字显示如下:

netstat -anop |grep 144
tcp        0      0 0.0.0.0:20144           0.0.0.0:*               LISTEN          4480/MonitorSipServ off (0.00/0/0)
tcp        0      0 140.0.24.181:20144      140.0.101.75:47036      ESTABLISHED 4480/MonitorSipServ off (0.00/0/0)
netstat -anop |grep 144
tcp        0      0 0.0.0.0:20144           0.0.0.0:*               LISTEN      4502/corosync    off (0.00/0/0)
tcp        0      0 140.0.24.181:20144      140.0.101.75:47036      ESTABLISHED 4502/corosync    off (0.00/0/0)
退出我的进程“MonitorSipServer”后,打开的套接字显示如下:

netstat -anop |grep 144
tcp        0      0 0.0.0.0:20144           0.0.0.0:*               LISTEN          4480/MonitorSipServ off (0.00/0/0)
tcp        0      0 140.0.24.181:20144      140.0.101.75:47036      ESTABLISHED 4480/MonitorSipServ off (0.00/0/0)
netstat -anop |grep 144
tcp        0      0 0.0.0.0:20144           0.0.0.0:*               LISTEN      4502/corosync    off (0.00/0/0)
tcp        0      0 140.0.24.181:20144      140.0.101.75:47036      ESTABLISHED 4502/corosync    off (0.00/0/0)
我已经用
system
popen
fork
+
execv
execve
null
环境进行了尝试。结果总是一样或更糟。 我最后的希望是Linux
setsid
命令,但它也不起作用

任何帮助都将不胜感激。 当做
Jan

如果您指的是套接字描述符本身被执行的子进程继承,这是不可取的,那么您可以在使用
socket(2)
创建套接字时传递
SOCK\u CLOEXEC
,以确保在执行其他程序时关闭它们。(顺便说一下,这不会关闭连接,因为您的程序仍然有对套接字的引用。)

如果您使用的是某个更高级别的库,那么请检查是否有某种方法使其通过此标志,或者执行
fcntl(sock_fd,F_SETFD,fcntl(sock_fd,F_GETFD)| fd_CLOEXEC)
在描述符创建后设置close-on-exec标志(如果可以的话)。(不过,在多线程环境中,
fcntl(2)
方法是可行的,因为一些线程可以
exec(3)
在创建套接字的点和设置了
FD\u CLOEXEC
的点之间执行程序。)

如果上述操作不起作用,那么您可以在执行服务之前手动
fork(2)
,然后
关闭(2)
套接字描述符。
SOCK\u CLOEXEC
的优点是,只有当
exec*()
实际成功时,才会关闭套接字,这有时会使从错误中恢复更容易。此外,
SOCK\u CLOEXEC
可以避免一些竞争,并且更难忘记关闭描述符

我有一个Linux服务(守护进程),它有多个线程,并使用boost io_服务监听TCP套接字。当我在该套接字上收到某条消息时,我想用/etc/init.d/corosync start启动另一个服务

对于使用systemd的现代Linux,您可能想了解一下。也就是说,主服务守护进程将只向unix套接字发送一个数据报(该数据报可能包含要显式传递给其他服务的文件描述符)。如果尚未启动,systemd将为您启动其他服务

使用systemd的好处是,您的服务不需要以root用户身份运行,就可以启动另一个服务,并且服务进程彼此完全隔离(没有继承任何东西,就像
fork
ing一样)。

Boost.Asio:

  • 它要求程序准备并通知fork的
    io\u服务

    io\u服务\u.notify\u fork(boost::asio::io\u服务::fork\u prepare);
    如果(fork()==0)
    {
    io\ U服务\通知\分支(boost::asio::io\ U服务::分支\子级);
    ...
    }
    其他的
    {
    io\ U服务\通知\分叉(boost::asio::io\ U服务::分叉\父级);
    ...
    }
    
    未能使用此模式将导致未指定的行为。对于某些配置,父级将无法接收事件通知,因为它们被子级使用

  • 该程序负责处理通过Boost.Asio的公共API访问的任何文件描述符。例如,如果父进程有一个打开的接受程序,则子进程需要在生成自己的子进程或替换进程映像之前显式调用。fork支持文档说明:

    请注意,通过Boost.Asio的公共API访问的任何文件描述符(例如
    basic_socket
    posix::stream_descriptor
    )在fork期间都不会更改。项目有责任根据需要对其进行管理

  • Asio的fork支持对于多线程进程是不安全的。对于多线程进程,声明子进程只能在
    fork()
    和其中一个
    exec()
    函数之间调用异步信号安全操作<代码>io_服务::notify_fork()不保证这一点,当前调用非异步信号安全操作

话虽如此,我已经看到应用程序在多线程进程中使用Boost.Asio的
fork()
支持时没有观察到不良行为。但是,如果希望同时满足
fork()
和Boost.Asio的要求,那么一个解决方案是在守护进程仍然是单线程的情况下为其提供fork。当父进程通过进程间通信通知子进程执行时,子进程将保持单线程,并执行
fork()
exec()
。回答中建议并演示了此解决方案。

还请注意,在许多情况下,您无法控制所有文件描述符以及它们是否是使用SOCK\u CLOEXEC创建的,在这种情况下,您可以在fork()之后运行一个循环,关闭()所有描述符,直到sysconf(\u SC\u OPEN\u MAX)(如果您想不使用stdin/out/err或将其重定向到/dev/null,则可能从fd 3开始)目前,并非所有文件描述符都可以通过
fd_CLOEXEC
set自动创建。在多线程应用程序中,另一个线程可能会在创建文件描述符之后,但在设置
fd_CLOEXEC
之前分叉进程。H