进程、fork、管道程序……我哪里出错了?
Processes, fork, pipes program...Where am I going wrong?
我在 Unix 中工作,我正在尝试编写一个 .c 文件来执行以下操作:
对于每个命令行参数,主进程将启动一个子进程(类型 A)。
A 进程将尝试在新的子进程(类型 B)中使用 exec 函数之一执行接收到的参数。
如果失败,类型 A 的进程将使用管道通道将 exec 调用生成的错误代码(errno 值)发送到其父进程。
成功后,进程 A 将等待类型 B 的进程,一旦完成,它将使用相同的管道通道将零代码传输给其父进程。
无论执行成功与否,主进程都会打印每个参数。仅对于失败的执行,错误接收代码也会被打印出来。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
int main(int argc, char const *argv[]) {
int c2p[2], g2c[2];
int i;
char n[100];
int *stat;
for (i = 0; i < argc; i++ ) {
pipe(c2p);
pipe(g2c);
if (fork() == 0) {
//child code
if (fork() == 0) {
//grandchild code
if (execlp("argv[i]", "argv[i]", NULL) == -1) {
write(g2c[1], errno, sizeof(int));
} else {
write(g2c[1], 0, sizeof(int));
}
}
wait(0);
read(g2c[0], n, 10);
write(c2p[1], n, 10);
exit(0);
}
read(c2p[0], &stat, sizeof(int));
if (*stat !=0) {
printf("Not succsesful: %s %d\n", argv[i], *stat);
} else {
printf("Succes! %s\n", argv[i]);
}
}
return 0;
}
两个问题:
- 你不能那样写一个整数,write 需要一个 pointer,所以
int n; ...; write(fd, &n, sizeof n);
- execlp replaces 调用它的进程,这意味着如果它有效,你将永远不会向管道写入零,因为孙子已被 execlp() 程序替换正在
如下更改您的代码,这对您有用:
int main(int argc, char const *argv[])
{
int c2p[2];
int i;
int stat;
for (i = 1; i < argc; i++ ) {
pipe(c2p);
if (fork() == 0) {
//child code
if (fork() == 0) {
//grandchild code
if (execlp(argv[i], argv[i], NULL) == -1)
exit(errno);
}
wait(&stat);
write(c2p[1], &stat, sizeof(stat));
exit(0);
}
read(c2p[0], &stat, sizeof(int));
if (stat != 0)
printf("Not succsesful: %s %d\n", argv[i], stat);
else
printf("Succes! %s\n", argv[i]);
}
}
如您在我的代码中所见:
- stat 必须是整数而不是指针
- 你将 argv[i] 作为参数而不是 "argv[i]" 传递给 execlp
- 您退出状态代码以通过 grandchild 的状态(您也可以
此技术在 child)
- 从 1 开始执行循环,因为 argv[0] 是您的程序名称。
- 在使用 exec 系列函数后永远记住你的源代码
进程替换为您调用的程序,因此您无法在成功后执行 运行。
我在 Unix 中工作,我正在尝试编写一个 .c 文件来执行以下操作:
对于每个命令行参数,主进程将启动一个子进程(类型 A)。
A 进程将尝试在新的子进程(类型 B)中使用 exec 函数之一执行接收到的参数。
如果失败,类型 A 的进程将使用管道通道将 exec 调用生成的错误代码(errno 值)发送到其父进程。
成功后,进程 A 将等待类型 B 的进程,一旦完成,它将使用相同的管道通道将零代码传输给其父进程。
无论执行成功与否,主进程都会打印每个参数。仅对于失败的执行,错误接收代码也会被打印出来。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
int main(int argc, char const *argv[]) {
int c2p[2], g2c[2];
int i;
char n[100];
int *stat;
for (i = 0; i < argc; i++ ) {
pipe(c2p);
pipe(g2c);
if (fork() == 0) {
//child code
if (fork() == 0) {
//grandchild code
if (execlp("argv[i]", "argv[i]", NULL) == -1) {
write(g2c[1], errno, sizeof(int));
} else {
write(g2c[1], 0, sizeof(int));
}
}
wait(0);
read(g2c[0], n, 10);
write(c2p[1], n, 10);
exit(0);
}
read(c2p[0], &stat, sizeof(int));
if (*stat !=0) {
printf("Not succsesful: %s %d\n", argv[i], *stat);
} else {
printf("Succes! %s\n", argv[i]);
}
}
return 0;
}
两个问题:
- 你不能那样写一个整数,write 需要一个 pointer,所以
int n; ...; write(fd, &n, sizeof n);
- execlp replaces 调用它的进程,这意味着如果它有效,你将永远不会向管道写入零,因为孙子已被 execlp() 程序替换正在
如下更改您的代码,这对您有用:
int main(int argc, char const *argv[])
{
int c2p[2];
int i;
int stat;
for (i = 1; i < argc; i++ ) {
pipe(c2p);
if (fork() == 0) {
//child code
if (fork() == 0) {
//grandchild code
if (execlp(argv[i], argv[i], NULL) == -1)
exit(errno);
}
wait(&stat);
write(c2p[1], &stat, sizeof(stat));
exit(0);
}
read(c2p[0], &stat, sizeof(int));
if (stat != 0)
printf("Not succsesful: %s %d\n", argv[i], stat);
else
printf("Succes! %s\n", argv[i]);
}
}
如您在我的代码中所见:
- stat 必须是整数而不是指针
- 你将 argv[i] 作为参数而不是 "argv[i]" 传递给 execlp
- 您退出状态代码以通过 grandchild 的状态(您也可以 此技术在 child)
- 从 1 开始执行循环,因为 argv[0] 是您的程序名称。
- 在使用 exec 系列函数后永远记住你的源代码 进程替换为您调用的程序,因此您无法在成功后执行 运行。