我们有一个家庭作业问题,我们必须编写一个带有两个参数的程序,将它们作为shell命令执行,将第一个程序的stdout输入到第二个程序的stdin中。
这是我的solution这个家庭作业问题。同样的文件转载如下。
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#define SHELL "/bin/sh"
extern int main(int, char*[]);
static int readingend(int, int, const char*);
static int writingend(int, int, const char*);
static int usr1handler();
extern int
main(int argc, char *argv[])
{
int pipefd[2], status;
pid_t rpid, wpid;
if (argc != 3) {
fprintf(stderr, "Invalid argument count\n");
return (EXIT_FAILURE);
}
if (pipe(pipefd)) {
perror("Cannot make a pipe");
return (EXIT_FAILURE);
}
signal(SIGUSR1, (void(*)(int))usr1handler);
if ((rpid = fork()) < 0) {
perror("Cannot fork");
return (EXIT_FAILURE);
}
if (rpid == 0)
return (readingend(pipefd[0], pipefd[1], argv[2]));
if ((wpid = fork()) < 0) {
perror("Cannot fork");
kill(rpid, SIGKILL);
return (EXIT_FAILURE);
}
if (wpid == 0)
return (writingend(pipefd[0], pipefd[1], argv[1]));
close(pipefd[0]);
close(pipefd[1]);
waitpid(rpid, &status, 0);
return (status);
}
static int
readingend(int rfd, int wfd, const char *cmd)
{
close(wfd);
dup2(rfd, STDIN_FILENO);
/* execl() only returns on error */
execl(SHELL, SHELL, "-c", cmd, NULL);
fprintf(stderr, "Cannot execute %s: ", cmd);
perror(NULL);
/* clean up */
kill(getppid(), SIGUSR1);
return (EXIT_FAILURE);
}
static int
writingend(int rfd, int wfd, const char *cmd)
{
close(rfd);
dup2(wfd, STDOUT_FILENO);
execl(SHELL, SHELL, "-c", cmd, NULL);
fprintf(stderr, "Cannot execute %s: ", cmd);
perror(NULL);
/* clean up */
kill(getppid(), SIGUSR1);
return (EXIT_FAILURE);
}
static int
usr1handler()
{
/* child already printed diagnostic */
exit(EXIT_FAILURE);
}
问题在于,在某些调用中,第一个进程在从stdin读取时收到EIO
。这似乎只发生在一些shell上:它发生在ksh93
和bash
但不发生在bosh
。这样的错误看起来像这样:
$ LANG=C ./mypipe cat true $ cat: -: Input/output error
有人可以告诉我为什么会出现这种错误吗?我该怎么办才能让错误再次发生?显然必须有一种方法,因为在普通shell中执行cat | true
会产生所需的结果,而不会产生任何虚假的EIO
。
答案 0 :(得分:0)
发生此问题是因为true
立即终止,导致mypipe
终止,导致cat
孤立。如果发生这种情况,read()
可能会失败:
EIO
该进程是尝试从其控制终端读取的后台进程的成员,该进程忽略或阻止
SIGTTIN
信号,或者进程组是孤立的。出于实现定义的原因,也可能会生成此错误。
可以通过等待这两个进程来阻止此问题:
extern int
main(int argc, char *argv[])
{
int status, estatus;
/* ... */
/* wait for both processes to terminate */
if (wait(&status) == rpid) {
estatus = status;
wait(&status);
} else {
wait(&status);
estatus = status;
}
return (estatus);
}