C/Linux-重定向stdin和stout时遇到问题
我有以下计划:C/Linux-重定向stdin和stout时遇到问题,c,linux,io-redirection,C,Linux,Io Redirection,我有以下计划: int main(int argc, char **argv) { char *program; char stringa[1000] = ""; int num = 0; char snum[10]; int pipefd[2]; pipe(pipefd); program = argv[1]; sprintf(stringa, "./%s", program); pid_t pid
int main(int argc, char **argv)
{
char *program;
char stringa[1000] = "";
int num = 0;
char snum[10];
int pipefd[2];
pipe(pipefd);
program = argv[1];
sprintf(stringa, "./%s", program);
pid_t pid = fork();
if (pid < 0 ) {
perror("fork failed.");
exit(1);
}
else if (pid == 0) {
char* args[] = {stringa, NULL};
execv(args[0], args);
}
else {
char procmon_str[] = "./procmon";
num = pid;
sprintf(snum, "%d",num);
pid_t pid2 = fork();
if (pid2 == 0) { //launch procmon
char* args2[] = {procmon_str, snum, NULL};
close(pipefd[0]); //close reading end in the child
dup2(pipefd[1], 1); //send stdout to the pipe
dup2(pipefd[1], 2); //send stderr to the pipe
close(pipefd[1]); //this descriptor is no longer needed
execv(args2[0], args2);
}
else {
close(pipefd[1]);
dup2(pipefd[0], STDIN_FILENO);
close(pipefd[0]);
char* args3[] = {"./filter", NULL};
execv(args3[0], args3);
}
}
return 0;
}
然后,发生以下情况:
启动myProgram
并确定其进程
PID
- 然后,它使用相同的
启动PID
程序procmon
- 它将启动另一个进程来运行程序
过滤器
procmon
的输出应发送到filter
的输入,这意味着-filter
将从其标准输入读取procmon
写入其标准输出的内容
由于某种原因,我没有得到想要的结果
procmon
的任务是获取给定进程的PID,访问相应的/proc/PID/stat
文件并打印进程状态。
filter
需要接受该值,并且只打印状态从一个变为另一个的行。目前,我没有从filter
获得任何信息
过程
进入一个循环(10次迭代),该循环休眠3秒,然后启动另一个循环,使变量递增400000次
我做得对吗?不能很好地描述您所面临的问题
总的来说,代码还不错。我已经做了一些重要的更改,还有一些无关紧要的更改(移动变量声明、初始化变量而不是赋值、格式化)。重大变化包括:
- 检查是否使用参数调用程序
- 在创建第一个子级之前不创建管道
- 报告错误并在
execv()失败时退出
- 未将
进程的标准错误重定向到管道procmon
过程
将管道两端打开,因此过滤器
将不会在管道上获得EOF,而过程
将继续。由于process
不太可能使用管道(它不知道为它们打开了哪些文件描述符),因此保持管道打开实际上没有意义,也可能有一些危害
没有将标准错误重定向到管道允许我看到在我使用的测试脚本中没有shebang的错误消息
我使用了一组来自stderr.h
和stderr.c
的函数,这些函数可以在GitHub上找到。它们简化了错误报告,所以我的大多数程序都使用它们
这将产生以下代码,这些代码与您的代码非常相似:
#include "stderr.h"
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv)
{
err_setarg0(argv[0]);
if (argc != 2)
err_usage("program");
pid_t pid = fork();
if (pid < 0)
err_syserr("failed to fork");
else if (pid == 0)
{
char stringa[1000] = "";
char *program = argv[1];
sprintf(stringa, "./%s", program);
char *args[] = {stringa, NULL};
execv(args[0], args);
err_syserr("failed to execute '%s': ", args[0]);
}
else
{
int pipefd[2];
pipe(pipefd);
pid_t pid2 = fork();
if (pid2 < 0)
err_syserr("failed to fork");
else if (pid2 == 0) // launch procmon
{
int num = pid;
char snum[10];
sprintf(snum, "%d", num);
char procmon_str[] = "./procmon";
char *args2[] = {procmon_str, snum, NULL};
close(pipefd[0]); // close reading end in the child
dup2(pipefd[1], 1); // send stdout to the pipe
//dup2(pipefd[1], 2); // send stderr to the pipe
close(pipefd[1]); // this descriptor is no longer needed
execv(args2[0], args2);
err_syserr("failed to execute '%s': ", args2[0]);
}
else
{
close(pipefd[1]);
dup2(pipefd[0], STDIN_FILENO);
close(pipefd[0]);
char *args3[] = {"./filter", NULL};
execv(args3[0], args3);
err_syserr("failed to execute '%s': ", args3[0]);
}
}
/*NOTREACHED*/
return 0;
}
procmon
#!/bin/sh
exec timeout -t 2m -- dribbler -m "$0: PID $1" -r 0.3 -t
过滤器
#!/bin/sh
echo "$0 at work"
exec grep -e '^[0-9]*9[0-9]*:' -- -
dribbler
程序是一种写信息速度较慢的自制程序,timeout
程序(也是自制程序,版本可追溯到1989年,而不是同名GNU程序)在指定时间后停止其进程。dribbler
的-r
和-s
选项实现高斯时间分布(-s
平均睡眠时间,默认为1秒,-r
随机性的标准偏差)。过滤器
脚本宣布它正忙,然后在输出的第一个字段中查找9
通过该基础设施,我得到了如下输出:
$ pp37 process
./filter at work
0: ./process: PID 48812
1: ./process: PID 48812
2: ./process: PID 48812
…
9: ./process: PID 48812
10: ./process: PID 48812
…
20: ./process: PID 48812
21: ./process: PID 48812
9: ./procmon: PID 48812
22: ./process: PID 48812
23: ./process: PID 48812
…
92: ./process: PID 48812
93: ./process: PID 48812
49: ./procmon: PID 48812
94: ./process: PID 48812
95: ./process: PID 48812
96: ./process: PID 48812
97: ./process: PID 48812
98: ./process: PID 48812
99: ./process: PID 48812
100: ./process: PID 48812
101: ./process: PID 48812
102: ./process: PID 48812
…
116: ./process: PID 48812
117: ./process: PID 48812
59: ./procmon: PID 48812
118: ./process: PID 48812
119: ./process: PID 48812
…
140: ./process: PID 48812
69: ./procmon: PID 48812
141: ./process: PID 48812
…
161: ./process: PID 48812
162: ./process: PID 48812
79: ./procmon: PID 48812
163: ./process: PID 48812
…
179: ./process: PID 48812
180: ./process: PID 48812
89: ./procmon: PID 48812
181: ./process: PID 48812
182: ./process: PID 48812
90: ./procmon: PID 48812
183: ./process: PID 48812
91: ./procmon: PID 48812
184: ./process: PID 48812
185: ./process: PID 48812
186: ./process: PID 48812
92: ./procmon: PID 48812
187: ./process: PID 48812
188: ./process: PID 48812
93: ./procmon: PID 48812
189: ./process: PID 48812
94: ./procmon: PID 48812
190: ./process: PID 48812
191: ./process: PID 48812
95: ./procmon: PID 48812
192: ./process: PID 48812
193: ./process: PID 48812
96: ./procmon: PID 48812
194: ./process: PID 48812
195: ./process: PID 48812
196: ./process: PID 48812
97: ./procmon: PID 48812
197: ./process: PID 48812
98: ./procmon: PID 48812
198: ./process: PID 48812
199: ./process: PID 48812
200: ./process: PID 48812
201: ./process: PID 48812
99: ./procmon: PID 48812
202: ./process: PID 48812
…
220: ./process: PID 48812
109: ./procmon: PID 48812
221: ./process: PID 48812
…
234: ./process: PID 48812
235: ./process: PID 48812
$
process
的输出不会被过滤,因此会显示其中的每一行,但是procmon
的输出会被过滤,并且只显示带有9
的行。这似乎是正确的。对于您的问题,“我没有得到想要的结果”是一个非常糟糕的描述。你应该展示你所得到的。你应该解释为什么它不是你认为你应该得到的。您应该更清楚地说明过程
、过程
和过滤器
的作用。因为它们都是从当前目录运行的,所以它们是仅在您的计算机上可用的自定义程序。您说得对,对不起。我编辑了我的问题。filter
是否已知有效?procmon
是否已知有效?我不能使用/proc/PID/stat
,因为macOS Sierra没有/proc
文件系统,而且我的机器上没有可用的Linux虚拟机。什么是用-C、Perl、shell等编写的filter
…?从表面上看,问题可能出在filter
或procmon
中,就像您展示的程序一样。过程
做了什么,到那个地步了?它是否足够频繁地改变状态?procmon
是否确保它刷新其输出行,以便数据正确地进入管道?procmon
肯定可以工作,但对filter
不确定。它们都是用C语言编写的。我在问题中添加了对过程的描述。我强烈建议将注意力集中在过滤器上。使用procmon
从命令行驱动它,使用另一个终端运行进程
。我甚至会运行两次procmon
,一次输入过滤器
,一次写入终端(另一个-三个终端可供检查)。问题中的驾驶程序似乎“正常”,因此罪魁祸首可能是其他人之一。我编辑了我的问题,并就我对程序的期望进行了更多解释。考虑到我的编辑和您的测试,我假设如果它仍然不适用于我,则可能是procmon
或filter
存在问题?考虑到filter
的功能,我如何“单独”测试它?我在主要问题下面添加了“如何测试(filter
,尤其是procmon
)”的建议。我使用我选择的测试程序的原因之一是因为我知道它们工作可靠。你应该尽量减少你正在处理的“未知”的数量。
#!/bin/sh
echo "$0 at work"
exec grep -e '^[0-9]*9[0-9]*:' -- -
$ pp37 process
./filter at work
0: ./process: PID 48812
1: ./process: PID 48812
2: ./process: PID 48812
…
9: ./process: PID 48812
10: ./process: PID 48812
…
20: ./process: PID 48812
21: ./process: PID 48812
9: ./procmon: PID 48812
22: ./process: PID 48812
23: ./process: PID 48812
…
92: ./process: PID 48812
93: ./process: PID 48812
49: ./procmon: PID 48812
94: ./process: PID 48812
95: ./process: PID 48812
96: ./process: PID 48812
97: ./process: PID 48812
98: ./process: PID 48812
99: ./process: PID 48812
100: ./process: PID 48812
101: ./process: PID 48812
102: ./process: PID 48812
…
116: ./process: PID 48812
117: ./process: PID 48812
59: ./procmon: PID 48812
118: ./process: PID 48812
119: ./process: PID 48812
…
140: ./process: PID 48812
69: ./procmon: PID 48812
141: ./process: PID 48812
…
161: ./process: PID 48812
162: ./process: PID 48812
79: ./procmon: PID 48812
163: ./process: PID 48812
…
179: ./process: PID 48812
180: ./process: PID 48812
89: ./procmon: PID 48812
181: ./process: PID 48812
182: ./process: PID 48812
90: ./procmon: PID 48812
183: ./process: PID 48812
91: ./procmon: PID 48812
184: ./process: PID 48812
185: ./process: PID 48812
186: ./process: PID 48812
92: ./procmon: PID 48812
187: ./process: PID 48812
188: ./process: PID 48812
93: ./procmon: PID 48812
189: ./process: PID 48812
94: ./procmon: PID 48812
190: ./process: PID 48812
191: ./process: PID 48812
95: ./procmon: PID 48812
192: ./process: PID 48812
193: ./process: PID 48812
96: ./procmon: PID 48812
194: ./process: PID 48812
195: ./process: PID 48812
196: ./process: PID 48812
97: ./procmon: PID 48812
197: ./process: PID 48812
98: ./procmon: PID 48812
198: ./process: PID 48812
199: ./process: PID 48812
200: ./process: PID 48812
201: ./process: PID 48812
99: ./procmon: PID 48812
202: ./process: PID 48812
…
220: ./process: PID 48812
109: ./procmon: PID 48812
221: ./process: PID 48812
…
234: ./process: PID 48812
235: ./process: PID 48812
$