叉子过程 - 面试问题 [英] Fork child process - Interview question

查看:98
本文介绍了叉子过程 - 面试问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述





几个月前我接受了采访,他们问我以下问题:



查找并修复`test.c'中的错误,简要说明你是如何找到它以及问题所在。描述你期望的输出和实际输出。你需要一个POSIX系统才能编译和运行此代码(在Windows上,fork()表现不同)。如果您无法访问POSIX系统,只需描述程序的预期输出。



我建立并运行程序,但我找不到任何问题。他们对我的回答不满意。这个问题困扰了我一段时间,因为我仍然认为该程序运行正常



这是代码



  / *   * @file test.c 
*
*守护程序代码的一个小例子。它会在子流程中分离
*,而父流会立即退出。
*
* @todo关闭孩子的文件描述符。
* /


#include < stdlib.h >
#include < stdio.h >
#include < unistd.h >
#include < sys / types.h >


/ * *要传递给守护程序的参数。 * /
struct params {
pid_t pid;
unsigned sleeptime;
};

/ * *子进程的功能。
*
*这是守护进程的主要功能。在此函数中填写
*守护程序功能。
*
*必须传递给守护进程
*的任何参数都在params结构中收集。
* /

void childfunc( struct params * params)
{
sleep(params-> sleeptime);
printf( Child已停止。\ n);
}

int main( int argc, char * argv [])
{
struct params params;

printf( 父启动:);
params.sleeptime = 3 ;
if ((params.pid = fork())< 0 ){
printf( fork failed:%m!\ n);
return 1 ;
} 其他 如果(params.pid> 0 ){
printf( 使用PID%d分叉的子项将睡眠% u seconds.\\\
,params.pid,params.sleeptime);
} else {
childfunc(¶ms);
}

return 0 ;
}





提前获得的任何帮助将非常适合



谢谢

解决方案

我没有编译并运行程序,但我认为问题由输出指示。什么是输出?从代码ist应该是:

父启动:子分叉... 
父启动:孩子已经停止。



第二行的'Parent started'指示错误。这是由孩子打印的。要解决此问题,请删除第一个printf()并将已启动的字符串添加到fork消息中。在调用 childfunc()之前,可以选择添加printf(Child has the started)。


我经常编程posix / linux系统,但我绝对不是一个大师。关于这个面试问题我还有一些提示。程序本身没有任何可能导致崩溃或世界末日的严重错误,如果我们谈论守护进程,它只有一个美学问题,也许还有一个技术问题。我没有编译和测试你的程序,但我不希望分叉守护进程在控制台上打印Child已经停止。信息。守护进程永远不会记录到控制台,更重要的是它应该与系统中的每个终端完全分离。

美学问题:当你启动程序时,父进程可能会打印它的东西(父进程启动:hild分叉PID ......)到控制台然后立即存在。由于我们控制台中的shell程序等待父进程立即终止,控件返回到控制台,并且shell的提示被打印到屏幕上,如duckfoot:/ home / duckfoot


< BLOCKQUOTE>)。由于子/守护进程进程尚未停止并且尚未从控制台分离,并且文件描述符(stdin / out / err)打开到控制台,因此它将其内容与其他程序并行打印到控制台(你的shell,或者是你在孩子等待3秒钟时启动的另一个控制台程序)。守护进程永远不应该记录到任何控制台,它应该记录/打印到其他东西(如/ dev / null,套接字,系统日志服务器,日志文件......),它应该完全脱离控制台。我对守护进程初始化和控制台分离的了解如下:你必须分叉两次。你分叉一次来创建你的第一个子进程。子进程应该关闭所有文件句柄,特别是那些打开到控制台/终端的文件句柄(我已经看到了从零到getdtablesize()关闭所有句柄的代码),它应该调用setsid()。在此之后,子进程将分叉以创建守护进程,然后终止。守护进程与控制台正确分离,并且没有任何引用任何终端的继承句柄。第一个子进程完成了它的工作,因此可以退出。在原始(第一和父)过程中,您正在等待第一个孩子阻止它变成僵尸。在守护进程中,您可以从stdio调用初始化/打开自己的stdin(0),stdout(1)和stderr(2)句柄开始,例如通过指向/ dev / null或文件或套接字等。

Hi,

Few month ago I had an interview and they asked me the following question:

"Find and fix the bug in `test.c', briefly explain how you found it and what the problem is. Describe the output you expect and the actual output. You'll need a POSIX system to be able to compile and run this code (on Windows, fork() behaves differently). If you don't have access to a POSIX system, just describe the expected output of the program."

I built and ran the program, but I could not find any problem on it. They were not satisfied with my answer. This question is bugging me for a while, since I still think the program is working properly

Here is the code

/** @file test.c
 *
 * A small example of daemon code.  It forks off
 * a child process, while the parent exits immediately.
 *
 * @todo Close file descriptors in the child.
 */

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>


/** Parameters to be passed to the daemon. */
struct params {
   pid_t pid;
   unsigned sleeptime;
};

/** Functionality of the child process.
 *
 * This is the main function of the daemon.  Fill in the
 * daemon functionality in this function.
 *
 * Any parameters that have to be passed to the daemon
 * are collected in the params struct.
 */
void childfunc (struct params *params)
{
    sleep(params->sleeptime);
    printf("Child has stopped.\n");
}

int main (int argc, char* argv[])
{
    struct params params;

    printf("Parent started: ");
    params.sleeptime = 3;
    if ( (params.pid = fork()) < 0) {
        printf("fork failed: %m!\n");
        return 1;
    } else if (params.pid > 0) {
        printf("child forked with PID %d and will sleep for %u seconds.\n", params.pid, params.sleeptime);
    } else {
        childfunc(¶ms);
    }

    return 0;
}



Any help in advance will be very much appriciated

Thanks

解决方案

I did not compile and run the program but I think the problem is indicated by the output. What is the output? From the code ist should be:

Parent started: child forked...
Parent started: Child has stopped.


The 'Parent started' indication of the second line is wrong. This is printed by the child. To fix this, remove the first printf() and prepend the started string to the fork messages. Optionally add a printf("Child has the started") before calling childfunc().


I'm regularly programming posix/linux systems but I'm definitely not a guru. Still I have a few tips regarding this interview question. The program itself doesn't have any serious bugs that would cause a crash or the end of the world, it has only one aesthetic and maybe one technical problem if we are talking about a daemon. I haven't compiled and tested your program but what I wouldn't expect a forked daemon process to print on the console the "Child has stopped." message. A daemon process never logs to the console and more importantly it should be completely detached from every terminals in your system.
The esthetic problem: When you start the program the parent process probably prints it stuff ("Parent started: hild forked with PID.....") to the console and then exists immediately. Since our shell program in the console waits for the parent process that terminates immediately the control returns to the console and the prompt is being printed to the screen by your shell like "duckfoot:/home/duckfoot


"). Since the child/"daemon" process hasn't yet stopped and hasn't been detached from the console and it has file descriptors (stdin/out/err) open to the console it prints its stuff to the console in parallel with other programs (your shell, or maybe another console program you start while the child is waiting for the 3 seconds to pass). A daemon process should never log to any console, it should log/print to something else (like /dev/null, a socket, a syslog server, a logfile, ...) and it should be detached from the console completely. What I know about daemon initialization and console detach is the following: You have to fork twice. You fork once to create your first child process. The child process should close all file handles especially those that are opened to the console/terminal (I have seen code that closes all handles from zero to getdtablesize()) and it should call setsid(). After this the child process forks to create the daemon process and then it terminates. The daemon process is correctly detached from the console and it doesn't have any inherited handles that reference any terminals. The first child process did it job so it can exit. In the original (first and parent) process you are waiting for the first child to prevent it from becoming a zombie. In the daemon process you can start by initializing/opening your own stdin(0), stdout(1) and stderr(2) handles for your stdio calls for example by pointing to /dev/null or to a file or socket or whatever.


这篇关于叉子过程 - 面试问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆