3

当 Wine 服务器启动时,它通过 open_master_socket() 创建一个 Unix 套接字,之后启动的所有 Wine 进程都使用这个套接字连接到 Wine 服务器,这里是 server/request.c,open_master_socket() 的代码:

 771     if (!foreground)
 772     {
 773         if (pipe( sync_pipe ) == -1) fatal_perror( "pipe" );
 774         pid = fork();
 775         switch( pid )
 776         {
 777         case 0:  /* child */
 778             setsid();
 779             close( sync_pipe[0] );
 780 
 781             acquire_lock();
 782 
 783             /* close stdin and stdout */
 784             dup2( fd, 0 );
 785             dup2( fd, 1 );
 786 
 787             /* signal parent */
 788             dummy = 0;
 789             write( sync_pipe[1], &dummy, 1 );
 790             close( sync_pipe[1] );
 791             break;
 792 
 793         case -1:
 794             fatal_perror( "fork" );
 795             break;
 796 
 797         default:  /* parent */
 798             close( sync_pipe[1] );
 799 
 800             /* wait for child to signal us and then exit */
 801             if (read( sync_pipe[0], &dummy, 1 ) == 1) _exit(0);
 802 
 803             /* child terminated, propagate exit status */
 804             wait4( pid, &status, 0, NULL );
 805             if (WIFEXITED(status)) _exit( WEXITSTATUS(status) );
 806             _exit(1);
 807         }
 808     }
 809     else  /* remain in the foreground */
 810     {
 811         acquire_lock();
 812     }

acquire_lock() 用于设置主套接字,问题是在后台运行时,为什么 fork() 让子进程完成工作,而父进程只是等待和 exit()?为什么不在前台运行?

4

2 回答 2

2

fork()并让子进程完成工作”“在后台运行”。

管道是一个习惯用法,让父级在子级进行可能失败的设置(在这种情况下,获取锁)时留在身边,并在发生故障时正确传播失败;否则,您将无法轻易发现子进程失败,而必须在事后检查其是否存在或扫描日志文件以查看是否出现问题。

于 2012-04-22T06:47:01.550 回答
1

是的,恶魔!
感谢ninjalj,这是实现后台运行守护进程的通用方法,并让分叉的孩子(守护进程)做守护进程。使用 _exit() 而不是 exit() 的父级是为了避免意外删除临时文件。
有关守护程序的更多信息,请参阅 如何制作进程守护程序http://software.clapper.org/daemonize/

geekosaur 很好地解释了为什么我们需要在 _exit() 之前等待孩子。

于 2012-04-25T13:46:15.217 回答