Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/159.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++;ServerSocket()、FD_CLOEXEC、fork();execl()_C++ - Fatal编程技术网

C++ c++;ServerSocket()、FD_CLOEXEC、fork();execl()

C++ c++;ServerSocket()、FD_CLOEXEC、fork();execl(),c++,C++,我在尝试在我的应用程序中设置命令的背景时遇到问题,因此我需要使用双叉并清除一些设置,因此这是我的结果: if((pid = fork()) < 0) perror("Error with Fork()"); else if(pid > 0) { return ""; } if (setsid()==-1) { Log("failed to become a session leader"); } if (chdir("/") == -1) { Log

我在尝试在我的应用程序中设置命令的背景时遇到问题,因此我需要使用双叉并清除一些设置,因此这是我的结果:

if((pid = fork()) < 0)
    perror("Error with Fork()");
else if(pid > 0) {
    return "";
}
if (setsid()==-1) {
    Log("failed to become a session leader");
}

if (chdir("/") == -1) {
    Log("failed to change working directory");
}

umask(0);
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
if (open("/dev/null",O_RDONLY) == -1) {
    Log("failed to reopen stdin");
}
if (open("/dev/null",O_WRONLY) == -1) {
    Log("failed to reopen stdout");
}
if (open("/dev/null",O_RDWR) == -1) {
    Log("failed to reopen stderr");
}

signal(SIGHUP, SIG_IGN);
Log("No return, forking..");
if((pid = fork()) < 0)
    perror("Error with Fork()");
else if(pid > 0) {
    return "";
} else {        
    if(execl("/bin/bash", "/bin/bash", "-c", cmddo, (char*) 0) < 0) perror("execl()");
    exit(0);
}
在我的最后一个问题中,我被告知要在套接字上使用FD_CLOEXEC,但我不知道如何做到这一点——而谷歌(加上堆栈)在这方面并没有给我多少帮助

如何在我的ServerSocket()上FD_CLOEXEC,以便在我fork/excl子进程时它不会挂起我的套接字

谢谢:D

回答: 如下所述,为了清除fd,我的代码实际上有这样一个功能,它对我很有用:

struct rlimit       rl;
int                 i;

if (rl.rlim_max == RLIM_INFINITY)
  rl.rlim_max = 1024;

for (i = 0; (unsigned) i < rl.rlim_max; i++)
  close(i);
struct rlimit rl;
int i;
if(rl.rlim_max==rlim_无穷大)
rl.rlim_max=1024;
对于(i=0;(无符号)i
FD\u CLOEXEC
是一个可以在文件描述符上设置的标志——其作用是当持有句柄的进程调用
exec()
时,描述符关闭

使用

设置旗帜;要使其工作,您需要访问实际的文件描述符

另外,
setsid()
足以使您与父进程组解除关联,虽然double
fork()
也可以工作,但它不会为您赢得嵌入式进程组的布朗尼点数

最后,无法保证在关闭前三个文件描述符后,下一个打开的FD将是这三个文件描述符;最好使用

fd newstdin = open(...);
if(dup2(newstdin, STDIN_FILENO) != 0) { /* handle error */ }
close(newstdin);

我想我确实理解了第二点和第三点,但是我的第一点,也是主要的一点,我仍然很困惑——ServerSocket()是否构成fd?我的应用程序中唯一的fd是当它被设置为守护程序时,我已经fd_CLOEXEC了。fd0=打开(“/dev/null”,O_RDWR);fcntl(fd0、F_SETFD、FD_CLOEXEC);谢谢ServerSocket内部有一个fd,是的。这是一个实现细节,原则上不应涉及您的应用程序,但通常有一种方法可以打破抽象(或者,尝试了解是否可以教ServerSocket设置close on exec标志,这是正确的做法)。请注意,您不应该关闭
exec()
上的标准文件描述符--这些文件描述符将由子级继承,否则首先设置它们是没有意义的。原则相当简单:当这三个文件描述符打开时,您的程序是
execve()
'd,其他程序也有同样的期望,所以这三个程序不应该接近exec。如果其他程序需要,您可以传递其他文件描述符(例如,gnupg有一个
--status fd
参数,告诉它将机器可读状态写入某个fd),除此之外,关闭fds通常是一个好主意。说到这一点,这可以实现得简单得多:只需检查所有可能的fd号码,然后在调用
exec*()
之前调用
close()
。这也将捕获您的服务器套接字。
fcntl(fd, F_SETFD, (long)FD_CLOEXEC);
fd newstdin = open(...);
if(dup2(newstdin, STDIN_FILENO) != 0) { /* handle error */ }
close(newstdin);