目标是实施终端命令 prog1>文件&& prog2 | prog3 给出参数
prog1
,file
,prog2
和prog3
。
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char **argv)
{
int fd,status,pipefd[2];
pipe(pipefd);
/* S_IRWXU - full acces to file */
fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
if (!fork()){
dup2(fd, 1); /* redirection to file */
close(fd); /* it's useless now */
execlp(argv[1], argv[1], NULL);
}
else {
wait(&status);
if (!status){
if (fork()){
dup2(pipefd[1],1);
close(pipefd[1]);
close(pipefd[0]);
execlp(argv[3], argv[3],NULL);
}
wait(NULL);
dup2(pipefd[0],0);
close(pipefd[0]);
close(pipefd[1]);
execlp(argv[4], argv[4],NULL);
}
}
return 0;
}
我无法使此代码显示上一个程序从上一个程序获得的数据。
例如(假设程序的名称为prog
):
./prog ps f date echo
不显示当前日期。我不明白为什么。你能解释一下吗?
答案 0 :(得分:2)
如果你跑:
date | echo
在shell的命令行提示符下,您将获得换行符并且没有日期。将echo
更改为cat
,您会看到日期:
$ date | echo
$ date | cat
Mon Dec 11 16:35:54 PST 2017
$
您可以修复代码,以便更好地处理错误:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char **argv)
{
if (argc != 5)
{
fprintf(stderr, "Usage: %s prog1 file prog2 prog3\n", argv[0]);
return 1;
}
int pid = fork();
if (pid < 0)
{
fprintf(stderr, "%s: failed to fork\n", argv[0]);
return 1;
}
else if (pid == 0)
{
/* S_IRWXU - full access to file */
int fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
if (fd < 0)
{
fprintf(stderr, "%s: failed to open file %s for writing\n", argv[0], argv[2]);
return 1;
}
dup2(fd, 1); /* redirection to file */
close(fd); /* it's not needed now */
execlp(argv[1], argv[1], NULL);
fprintf(stderr, "%s: failed to execute %s\n", argv[0], argv[1]);
return 1;
}
else
{
int status;
wait(&status);
if (status == 0)
{
int pipefd[2];
pipe(pipefd); // Error check?
pid = fork();
if (pid < 0)
{
fprintf(stderr, "%s: failed to fork\n", argv[0]);
return 1;
}
else if (pid == 0)
{
dup2(pipefd[1], 1);
close(pipefd[1]);
close(pipefd[0]);
execlp(argv[3], argv[3], NULL);
fprintf(stderr, "%s: failed to execute %s\n", argv[0], argv[3]);
return 1;
}
else
{
dup2(pipefd[0], 0);
close(pipefd[0]);
close(pipefd[1]);
execlp(argv[4], argv[4], NULL);
fprintf(stderr, "%s: failed to execute %s\n", argv[0], argv[4]);
return 1;
}
}
}
return 0;
}
很多C编程都是关于错误处理的。拥有一个使错误报告更简单的函数库有很大帮助。例如,我有一个包含头文件stderr.h
的库和stderr.c
中的实现 - 来自GitHub的源代码。它简化(并改进了)错误报告:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "stderr.h"
int main(int argc, char **argv)
{
err_setarg0(argv[0]);
if (argc != 5)
err_usage("prog1 file prog2 prog3");
int pid = fork();
if (pid < 0)
err_syserr("failed to fork: ");
else if (pid == 0)
{
/* S_IRWXU - full access to file */
int fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
if (fd < 0)
err_syserr("failed to open file %s for writing: ", argv[2]);
dup2(fd, 1); /* redirection to file */
close(fd); /* it's not needed now */
execlp(argv[1], argv[1], NULL);
err_syserr("failed to execute %s: ", argv[1]);
}
else
{
int status;
wait(&status);
if (status == 0)
{
int pipefd[2];
pipe(pipefd); // Error check?
pid = fork();
if (pid < 0)
err_syserr("failed to fork");
else if (pid == 0)
{
dup2(pipefd[1], 1);
close(pipefd[1]);
close(pipefd[0]);
execlp(argv[3], argv[3], NULL);
err_syserr("failed to execute %s: ", argv[3]);
}
else
{
dup2(pipefd[0], 0);
close(pipefd[0]);
close(pipefd[1]);
execlp(argv[4], argv[4], NULL);
err_syserr("failed to execute %s: ", argv[4]);
}
}
}
return 0;
}
例如,err_syserr()
函数报告系统错误号和消息以及命令名称(prog41
)和呼叫中指定的消息。 (是的,有一些方法可以再压缩两个程序 - 可以删除外部else
块上的if
,使下面的代码减少一级(并且代码三行更短) ,例如。)
此程序为prog41
,测试输出可能为:
$ ./prog41 rigmarole /dev/not-there fudge pumpkin
prog41: failed to open file /dev/not-there for writing: error (1) Operation not permitted
$ ./prog41 rigmarole not-there fudge pumpkin
prog41: failed to execute rigmarole: error (2) No such file or directory
$ ./prog41 ps not-there fudge pumpkin
prog41: failed to execute pumpkin: error (2) No such file or directory
prog41: failed to execute fudge: error (2) No such file or directory
$ ./prog41 ps not-there date pumpkin
prog41: failed to execute pumpkin: error (2) No such file or directory
$ ./prog41 ps not-there date cat
Mon Dec 11 16:49:11 PST 2017
$ ./prog41 proxy mangler
Usage: prog41 prog1 file prog2 prog3
$
成功运行程序后,文件not-there
当然在那里。
答案 1 :(得分:-1)
你有三个执行官,但有2个叉子。我个人会做三个叉子(每个exec一个),并有2个管道在流程中进行通信。