我正在尝试使用管道将一些数据发送到子进程。分叉后,我调用 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
子进程应该编码为从特定的文件描述符中读取(它是一个 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 中情况总是如此。