从C中的系统命令开始的进程继承父fd的

Eli*_*ven 11 c linux netstat system pppd

我有一个SIP服务器的示例应用程序,它同时监听tcp和udp端口5060.在代码中的某个时刻,我做了一个系统("pppd file/etc/ppp/myoptions&");

在此之后,如果我执行netstat -apn,它会显示端口5060也为pppd打开!有没有办法避免这种情况?这是Linux中系统功能的标准行为吗?

谢谢,艾莉森

Chr*_*odd 14

是的,默认情况下,每当您分叉一个进程(system确实如此)时,子进程将继承所有父进程的文件描述符.如果孩子不需要那些描述符,它应该关闭它们.使用system(或执行fork + exec的任何其他方法)的方法是在所有文件描述符上设置FD_CLOEXEC标志,该标志不应由您的子进程使用.这将导致它们在任何孩子执行其他程序时自动关闭.

一般情况下,任何时候你的程序打开任何一段长时间存在的文件描述符(例如你的例子中的一个监听套接字),哪些不应该与孩子共享,你应该这样做

fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
Run Code Online (Sandbox Code Playgroud)

在文件描述符上.


截至2016年?在修改POSIX.1时,您可以使用SOCK_CLOEXEC标记或者插入套接字类型来在创建套接字时自动获得此行为:

listenfd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, 0);
bind(listenfd, ...
listen(listemfd, ...
Run Code Online (Sandbox Code Playgroud)

哪个guarentees它将被正确关闭,即使其他一些同时运行的线程执行systemfork+ exec调用.幸运的是,这个标志在Linux和BSD unix上已经支持了一段时间(但不幸的是OSX).

  • 使用POSIX 2008或GNU,您还可以在打开文件时使用`O_CLOEXEC`标志.这避免了必须进行单独调用,并使操作*原子*,如果另一个线程(或信号处理程序)可以在`open`调用和`fcntl`调用之间进行fork-and-exec,则这很重要. (2认同)