如何在C语言中将一个子进程与父进程分离

4

我正在用C语言设计一个基本的UNIX shell。

    signal(SIGCHLD, handler);
        pid = fork();
        switch (pid) {
        case -1: printf("Fork failed; cpid == -1\n");
        break;

        case 0: child_pid = getpid();
                argv[0] = prog;
        argv[1] =NULL;
        //exit(0);
        sid = setsid();
        execv(absPath,argv);        
        //printf("%d: this is the child, pid = %d\n", i, child_pid);
        //sleep(1);
        //exit(0);
        break;

        default: printf("This is the parent: waiting for %d to finish\n", pid);
        waitpid(pid, NULL, WNOHANG);
        printf("Ttttthat's all, folks\n");
        //break;
        }
        //execv(absPath,argv);
        //printf("CHILD PROCESS");
    }

}
void handler(int sig)
{
  pid_t pid;

  pid = wait(NULL);

  printf("Pid %d exit.\n", pid);
  exit(0);
}

但它仍然在相同的shell中执行分叉进程,尽管是在“default”子句之后。

请问你能帮我使它作为后台进程运行吗?谢谢!

P.S:这只是一个片段。


首先,你的情况0:很奇怪,因为你在其中有一个exit(0)。你代码片段中的逻辑感觉很奇怪。 - Ahmed Masud
啊,非常抱歉我粘贴了旧代码。请原谅我。请忽略exit(0);。 - Ishwar
你能用适当的代码修复这个问题吗?提供可编译的代码实际上非常有用。如果代码太大,请使用http://pastebin.com。 - Ahmed Masud
调用fork()两次;在第一个fork退出后,第二个进程将重新分配到init之下。在BSD系统中,您可以使用daemon() libc调用;为什么它不在所有地方都存在是超出我的理解范围的。 - tbert
哦,所以execv()需要在孙子进程中被调用?类似这样吗? - Ishwar
我是否仍需要使用setsid?另外,在第一个子进程中,我应该建立一个处理程序来知道孙子进程何时终止吗?谢谢。 - Ishwar
2个回答

2

针对一些明显的错误进行评论:

  • 在子进程中,您执行了exit(0);,因此立即退出了子进程。请删除此行。
  • 为了清晰起见,建议您像这样调用execv()execv(argv[0], argv);

编辑: 阅读以下内容以解决从子进程进行分叉的问题。


absPath包含要执行的文件的完整绝对路径,而argv [0]仅包含文件名。因此我认为我不能这样做。我可以吗? - Ishwar
请忽略 exit(0),我忘记更新代码了。那是我用于调试的。抱歉。 - Ishwar
我从那个网站上复制了上述两行代码 :S。 - Ishwar
那么,你能解释一下接下来会发生什么吗? - iikkoo
太棒了!你提供的链接正是我一直在找的。非常感谢!解释得非常好。 - Ishwar
显示剩余3条评论

0
作为我的 Fat Controller 应用程序的一部分,我制作了一个库来将进程守护化。下载源代码并查看 daemonise.c 文件 - 它应该有相对详尽的注释,但如果您有任何进一步的问题,我很乐意帮忙。

http://sourceforge.net/projects/fat-controller/files/


https://dev59.com/r2PVa4cB1Zd3GeqP2huZ - Ishwar
我似乎仍然无法弄清楚它! - Ishwar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接