我可以在没有分支的情况下执行shell或系统调用吗?

时间:2015-11-20 12:17:49

标签: c linux multithreading tcp fork

我有一个TCP服务器应用程序,偶尔需要通过关闭它们然后稍后打开它们来重新配置绑定端口。

应用程序还需要执行与之通信的外部二进制文件。目前使用popen()调用完成此操作。外部二进制运行时间可以跨越需要​​重新配置网络端口的时间段。

问题是,当主应用程序关闭一个端口时,它会由“分叉”接收。 popen为了运行二进制文件而创建的进程。

这是有道理的(它在What happens when a tcp server binds and forks before doing an accept ? Which process would handle the client requests?讨论过),但不可取,因为主应用程序无法重新打开端口。

是否可以使用popen(3)中可用的FD_CLOEXEC O_CLOEXEC?应用程序需要popen(3)提供的管道作为stdin到执行的二进制文件,当CLOEXEC关闭其他文件时,文件句柄保持打开状态。

是否有更好的方法来运行二进制文件,这会导致分叉进程无法保持关闭端口?

How to fork process without inheriting handles?

还有另一个可能相关的问题

2 个答案:

答案 0 :(得分:5)

不,你不能启动另一个程序,并且在没有fork(2)后跟一些execve(2)代码(popenposix_spawn和{{1 }} 是做)。您最好避免system popen并自己明确编码system + pipe + fork(因为你知道吗应该保留哪些文件描述符以及close(2)哪些文件描述符通常在execve之后和子进程中fork之前...),请参阅{{3 }}

除<{1}}以外的每个流程和程序以及一些热插拔内容都以execve + /sbin/init开头;您的shell是对于大多数命令不断使用fork + execve,除了fork之类的内置命令

this来电可由fork(2)实施。

阅读一些好的书,例如 Advanced Linux Programming 在线免费提供的书籍clone(2)。另见here。使用(至少用于调试和理解事物)syscalls(2)和调试器(execve)。研究strace(1) libc(free softwareGNU libc)中cdgdb的源代码,以及shell的源代码。

您可以通过棘手的序列musl-libc(以及相关的popen)调用几乎模仿execve(2),但不完全(尤其是近距离执行等...)。您可能还需要调用过时的mmap(2)(或编写等效的汇编代码)。

您可以考虑与system&amp;上的类似shell的类似服务器的程序进行通信。 munmap(例如,请参阅我的setcontext(3)和灵感)。也许你会发现execicar.c很有用。

更好的选择可能是在您的应用中嵌入一些解​​释器(如daemon(3)lua)和/或guile部分dlopen(3)。缺点是错误(在解释的脚本或插件中)会影响整个服务器。

答案 1 :(得分:0)

你绝对可以使用close-on-exec标志来避免新启动的进程继承打开的文件或套接字(并且没有其他方式我知道)。如果您使用open(2)打开文件,则可以通过将O_CLOEXEC添加到文件创建标志来设置此时的标志。如果文件已经打开,您可以使用fcntl()进行设置(如果您使用fopen(3)打开文件,则可以通过fileno(3)获取此文件所需的文件描述符。对于套接字,您还可以通过设置socket(2)在使用SOCK_CLOEXEC打开时设置标记。没有设置此标记的文件将由您的程序生成的进程继承,无论是直接通过fork + exec还是该组合的任何其他“伪装”,例如system(3)popen(3)。< / p>