使用管道和 execve 没有接收到字节

问题描述 投票:0回答:1

我正在尝试使用管道将一些数据发送到子进程。分叉后,我调用 execve,它工作正常,但我仍然无法从管道接收任何字节。我不知道我错过了什么。我尝试在不使用 execve 的情况下构建相同的程序,并且它运行没有任何问题。

家长代码:

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sysinfo.h>
#include <sys/wait.h>
#include <errno.h>
#include <time.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>


char *args_0[] = {"./child.out", "", (char *)0};

struct INFO
{
    int a;
    int b;
    int c;
};

pid_t child_pid;

int i, j, status;

int main()
{
    struct INFO *info;
    ssize_t num_bytes;
    char buf[30];
    int my_pipe[2];
    info = malloc(sizeof(struct INFO));
    if (pipe(my_pipe) == -1)
    {
        perror("error on pipe");
    };

    for (i = 0; i < 2; i++)
    {
        write(1, "fork\n", 5);
        switch (fork())
        {
        case -1:
            write(1, "Error1\n", 7);
            exit(EXIT_FAILURE);
        case 0:
            write(1, "forked\n", 7);
            
            
            if (execve(args_0[0], args_0, NULL) == -1)
            {
                write(1, "Error\n", 6);
                exit(EXIT_FAILURE);
            }
            
            exit(EXIT_SUCCESS);
            break;

        default:
            break;
        }
    }

    info->a = 10;
    info->b = 20;
    info->c = 30;
    close(my_pipe[0]);
    for (size_t i = 0; i < 2; i++)
    {
        write(my_pipe[1], info, sizeof(struct INFO));
    }
    close(my_pipe[1]);
    write(1, "writed\n", 7);

    /* Now let's wait for the termination of all kids */
    while ((child_pid = wait(&status)) != -1)
    {
        /*printf("PARENT: PID=%d. Got info of child with PID=%d, status=0x%04X\n", getpid(), child_pid,status);*/
    }

    exit(EXIT_SUCCESS);
}

儿童代码:

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sysinfo.h>
#include <sys/wait.h>
#include <errno.h>
#include <time.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>

struct INFO
{
    int a;
    int b;
    int c;
};

int main()
{
    struct INFO* info;
    ssize_t num_bytes;
    char buf[30];
    int my_pipe[2];

    if (pipe(my_pipe) == -1)
    {
        perror("error on pipe");
    };

    close(my_pipe[1]);
    num_bytes = read(my_pipe[0], info, sizeof(struct INFO));

    if (num_bytes >= 0)
    {
         bzero(buf, 30);
        snprintf(buf, 30, "num byte %ld\n",num_bytes);
        write(1, buf, 30); 

        bzero(buf, 30);
        snprintf(buf, 30, "%d %d %d\n", info->a, info->b, info->c);
        write(1, buf, 30);
    }
    
    close(my_pipe[0]);
    write(1, "pausing\n", 8);
    pause();
}

我应该获得

10 20 30

但是我得到了

0 0 0

c pipe exec
1个回答
0
投票

子进程应该编码为从特定的文件描述符中读取(它是一个 int,可以是任何 int...我不知道是 16 位、32 位还是 64 位)。

例如,500。

int main()
{
    struct INFO* info;
    ssize_t num_bytes;
    char buf[30];
/*  *** you don't need any of this, because the pipe is already open before this process image is loaded ***
    int my_pipe[2];

    if (pipe(my_pipe) == -1)
    {
        perror("error on pipe");
    };

    close(my_pipe[1]);
*/

    /* here, 500 is the file descriptor agreed upon between parent and child */
    num_bytes = read(500, info, sizeof(struct INFO));

    /* [...] */

在执行之前,您必须安排该特定文件描述符准备好并可读(通过复制)。

    /* [...] */
       case 0:
            write(1, "forked\n", 7);
            /* before execing, memory address has the same contents (though independent copy-on-write) */

            /* close the write end of the pipe */
            close(my_pipe[1]);

            /* arrange for it to be 500 */
            dup2(my_pipe[0], 500);

            /* my_pipe[0] and 500 are duplicates, close the unneeded one */
            close(my_pipe[0]);
            
            if (execve(args_0[0], args_0, NULL) == -1)
            {
                write(1, "Error\n", 6);
                exit(EXIT_FAILURE);
            }

            /* doesn't really get here, but by this time the new image is running, with a readable file descriptor 500, connected to the parent my_pipe[1] */
            
            exit(EXIT_SUCCESS);

我很着急,没有时间编写代码并编译以查看它是否有效。我刚刚概述了进程之间的管道应该如何完成。我希望你能从这里走出来。

了解什么是流程及其形象是一件好事。对于您的子进程,它甚至在加载新图像之前就存在。事实上,在 UNIX 中情况总是如此。

© www.soinside.com 2019 - 2024. All rights reserved.