在c++中,想要派生一个不会挂起其父进程的进程——其父进程是一个守护进程,必须保持运行。如果我在forked进程上等待(),forked execl不会取消资助-但是-它也会挂起应用程序-不等待修复应用程序挂起-但是命令变为取消资助。
if((pid = fork()) < 0)
perror("Error with Fork()");
else if(pid > 0) {
//wait here will hang the execl in the parent
//dont wait will defunt the execl command
//---- wait(&pid);
return "";
} else {
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);
if(execl("/bin/bash", "/bin/bash", "-c", "whoami", (char*) 0) < 0) perror("execl()");
exit(0);
}
在execl的命令不会失效的情况下,我如何在没有等待(&pid)的情况下分叉execl?
更新通过在分叉之前添加以下内容修复
signal(SIGCHLD, SIG_IGN);
仍在利用我有限的技能,在公认答案的基础上找到一个更兼容的解决方案。谢谢
默认情况下,wait
和朋友会等待进程退出,然后收获它。如果没有子进程退出,您可以用WNOHANG
调用waitpid
以立即返回。
失效的/"僵尸"进程将一直存在,直到你在它上wait
。因此,如果你在后台运行它,你必须安排最终通过以下几种方式获得它:
- 常规试用
waitpid
和WNOHANG
:int pid = waitpid(-1, &status, WNOHANG)
- 为
SIGCHLD
安装一个信号处理程序,以便在其退出时得到通知
此外,在POSIX.1-2001下,可以使用sigaction
在SIGCHLD
上设置SA_NOCLDWAIT
。或者将其操作设置为SIG_IGN
。较旧的系统(包括Linux 2.4.x,但不包括2.6.x或3.x)不支持此功能。
检查您的系统手册页,或者在"单一Unix规范"中选择等待。Single Unix Spec还提供了一些有用的代码示例。SA_NOCLDWAIT
记录在sigaction中。
我认为信号处理程序将是所示的最佳方式。我想指出另一种处理方法:分叉两次,让孩子退出,而孙子会调用execl
。然后,init进程将清理已失效的进程。
正如注释中所说,双叉将进程从失效状态保存下来。
创建守护程序时执行双分叉的原因是什么?
EX1:当客户端不退出时,不等待
#include <spawn.h>
extern char** environ; //posix_spawn using environ that declare in glibc-2.xx/posix/environ.c
void main()
{
pid_t spawnid;
char param[64] = {0};
char* args[] = {"/usr/drive_server", param, NULL};
posix_spawn(&spawnid, "/usr/drive_server", NULL, NULL, args,
environ);
getchar();
}
EX2:当客户端退出时,等待子进程分离
#include <spawn.h>
extern char** environ;
void main()
{
pid_t spawnid;
char param[64] = {0};
pid_t sessionid;
char* args[] = {"/usr/drive_server", param, NULL};
posix_spawn(&spawnid, "/usr/drive_server", NULL, NULL, args, environ);
sessionid = 0;
while( sessionid != spawnid )
{
sessionid = getsid(spawnid);
printf("sessionid id %dn", sessionid);
usleep(200000);
}
}
//subprocess file
void main()
{
setsid(); //detach
getchar();
}
EX3:当系统有setsid命令时,不等待
#include <spawn.h>
extern char** environ;
void main()
{
pid_t id_spawn;
char* args[] = {"/usr/bin/setsid", "/volume1/drive_server", serviceName8, NULL};
posix_spawn(&id_spawn, "/usr/bin/setsid", NULL, NULL, args, environ);
printf("drive_server* spawn id %dn", id_spawn);
}
有两种源代码可以参考
- util-linux-2.xx.x/sys utils/setsid.c
- busybox-1.xx.x/util-linux/setsid.c