繁体   English   中英

多次分叉后无法将消息发送到父进程

[英]Unable to send message to parent process after multiple forks

我有一个程序,它分叉了四个进程并调用execlp()为子代运行不同的代码。 我给孩子传递了一个数字作为ID。 到目前为止,子级所做的只是尝试将id传递回父级进程。 管道工作,如果我在父进程中通过输出流放置了一个字符串。 但是,当我尝试将id作为一个int认为是流时,它不起作用。 在子级中的fprintf()和fflush()命令之后,我什至没有到达代码行。

我对创建文件描述符的方式进行了一些更改,并为示例添加了更多代码。 现在,在孩子中,我无法创建FILE *。 但是,如果我在文件描述符1上创建出来,则它确实会打印到屏幕上。 我尝试在文件描述符3上创建出来,程序就坐在那儿,等待从未出现的孩子输入。

这是我的父母:

Mom::Mom():childCount(0)
{
    pipeCount = fileCount = 0;
    int fd[2];
    srand(time(NULL));

    for(int c=0; c<NUMJOBS; ++c) jobs[c] = newJob();
    //createFileDescriptors(fd);
    ret = pipe(fd);
    if(ret < 0) fatal("Error creating pipes");
    //cout << fd[0] << "\t"  << fd[1] << endl;
    pipes[fileCount++] = fdopen(fd[0], "r");
    fcntl( 3, F_SETFD, 0 );
    //close(fd[1]);
    //for(int c=3; c<FILEDESCRIPTORS; c+=2) pipes[pipeCount++] = fdopen(c, "w");
    createChildren();
    for(int c=0; c<4; c++)
    {
        int tmp = -1;
        //cout << "About to read from children, tmp = " << tmp << endl;
        ret = fscanf(pipes[0], "%d", &tmp);
        //char* buffer = (char*) malloc(80*sizeof(char));
        //char buffer[80];
        //read(3, buffer, 80);
        cout << ret << "\t" << tmp << endl;
        //cout << ret << " " << tmp << endl;
        //free(buffer);
    }
    //sleep(5);
}

/*------------------------------------------------------------------------------
  Create all the children by using fork() and execlp()
  ----------------------------------------------------------------------------*/
void Mom::createChildren()
{
    int fd[2];
    fcntl( fd[IN], F_SETFD, 0 );
    for(int c=0; c<NUMCHILDREN; c++)
    {
        ret = pipe(fd);
        if(ret < 0) fatal("Error creating pipes");
        int pid = fork();
        //cout << pid << endl;
        if(pid == 0)
        {
            setupChild(c, fd);
        }
        else
        {
            //close(fd[1]);

        }
    }
}

/*------------------------------------------------------------------------------
  set up the child and call exec to run ChildMain
  ----------------------------------------------------------------------------*/
void Mom::setupChild(int count, int fd[])
{
    //cout << "Creating child with id: " << count << endl;
    char cnt = '0' + count;
    string id_str (&cnt + '\0');
    fcntl( fd[0], F_SETFD, 0 );
    pipes[fileCount++] = fdopen(fd[1], "w");
    //execlp("ChildMain", "ChildMain",  id_str.c_str(), NULL);
    execlp("ChildMain",  id_str.c_str(), NULL);
}

这是子代码:

int main(int argc, char* argv[])
{
    //cout << argv[argc-1] << endl;
    if(argc < 1) fatal("Not enough arguments provided to ChildMain");
    int id = atoi(argv[argc-1]);
    //cout << *argv[1] << " " << id << endl;
    //redirect STDIN and STDOUT
    /*int c_in = dup(0);
    close(0);
    dup((2*id) + 5);
    int c_out = dup(1);
    close(1);
    dup(4);*/
    /////////////////////////////
    //Child kid((int) *argv[1]);
    FILE* out = fdopen(4, "w");
    if(out == NULL)
        cout << "Error opening stream to parent in child: " << id << endl;
    //char childID = '0' + id;
    //char buf[80];
    //strcpy(buf, "Child ");
    //strcat(buf, &childID);
    string buf ("Child");
    //cout << tmp << " " << childID << endl;
    //write(4, buf.c_str(), buf.length()+1);
    //cout << id << endl;
    int ret = fprintf(out, "%d", id);
    fflush(out);
    //fclose(out);
    //cout << id << " " << ret << endl;
    //ch.push_back((char) id);
    //put STDIN and STDOUT back to correct file descriptors
    /*close(1);
    dup(c_out);
    close(0);
    dup(c_in);*/
    ////////////////////////////////////////////////////////
    return 0;
}

我很困惑为什么这适用于ID为0的第一个孩子,而其他人没有。 有人知道我的代码有什么问题吗?

execlp(3)期望以空终止的字符串作为参数。 &cnt不会以null终止。

简单修复:

void Mom::setupChild(int count, int fd[])
{
    char cnt[2];
    cnt[0] = '0' + count;
    cnt[1] = '\0';
    fcntl( fd[(2*count)+3], F_SETFD, 0 );
    execlp("ChildMain", "ChildMain",  &cnt, NULL);
}

不过,这不会扩展到10个进程,因此我可能会使用一个缓冲区,而只是将sprintf()放入其中。

这是一个有关如何在我的评论中实施建议的小例子:

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

int main()
{
    /* Need two sets of pipes: one for child stdin, one for child stdout */
    int pipefds1[2];
    int pipefds2[2];

    pipe(pipefds1);
    pipe(pipefds2);

    int rc = fork();
    if (rc == -1)
        perror("fork");
    else if (rc == 0)
    {
        /* In child */

        /* Close the old stdin and stdout */
        close(STDIN_FILENO);
        close(STDOUT_FILENO);

        /* Create new stdin/stroud from the pipes */
        dup2(pipefds1[0], STDIN_FILENO);
        dup2(pipefds2[1], STDOUT_FILENO);

        /* Close the unneeded pipe handles */
        close(pipefds1[1]);
        close(pipefds2[0]);

        /* Now pass control to the new program */
        execl("/bin/ls", "ls", "-l", "/", NULL);
    }
    else
    {
        /* In parent */

        /* Close the uneeded pipe handles */
        close(pipefds1[0]);
        close(pipefds2[1]);

        /* We want to use stdio functions */
        FILE *fp = fdopen(pipefds2[0], "r");

        /* Read all from the child */
        char buffer[128];
        while (fgets(buffer, sizeof(buffer), fp))
        {
            printf("Input from child: %s\n", buffer);
        }

        fclose(fp);

        /* Wait for child to exit */
        wait(NULL);
    }

    return 0;
}

希望这足以让您继续。

错误处理不存在,但是已经过测试。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM