问题描述
我有以下程序:
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 process
然后,发生以下情况:
-
myProgram
启动process
并确定其PID
- 然后使用相同的
PID
启动 - 它将启动另一个运行程序
filter
的进程
procmon
程序myProgram
launchesprocess
and determines itsPID
- It then launches the
procmon
program with that samePID
- It will launch another process that runs the program
filter
procmon
的输出应发送到filter
的输入,这意味着filter
将从其标准输入中读取procmon
写入其标准输出的内容.
The output of procmon
should be sent to the input of filter
, meaning - filter
will read from its standard input what procmon
is writing to its standard output.
由于某种原因,我没有得到想要的结果.
For some reason, i don't get the desired results.
procmon
的工作是获取给定进程的PID,访问相应的/proc/PID/stat
文件并打印进程状态.filter
需要采取这种措施,并且仅打印状态从一种更改为另一种的行.目前,我没有从filter
那里得到任何东西.
procmon
s job is to take a given process's PID, access the corresponding /proc/PID/stat
file and print the process state.filter
needs to take that and only prints the line where the state changes from one to another. At the moment, i don't get anything from filter
.
process
进入一个循环(10次迭代),该循环休眠3秒,然后开始另一个循环,该循环将变量增加40万次.
process
goes into a loop (10 iterations) that sleeps for 3 seconds, and then starts another loop that increments a variable 400,000 times.
我做对了吗?
推荐答案
未获得期望的结果"不是对您所面临问题的很好描述.
"Don't get the desired results" is not a good description of the problem you are facing.
总的来说,代码还不错.我进行了一些重大更改,并进行了一些无关紧要的更改(移动变量声明,初始化变量而不是分配变量,格式化).重大变化包括:
On the whole, the code is not bad. I've made some significant changes and a load of insignificant ones (moving variable declarations, initializing variables instead of assigning them, formatting). The significant changes include:
- 检查是否已使用参数调用程序.
- 在创建第一个孩子之后才创建管道.
- 报告错误,如果
execv()
失败,则退出. - 不将
procmon
进程的标准错误重定向到管道.
- Checking that the program is called with an argument.
- Not creating the pipe until after the first child is created.
- Reporting errors and exiting if the
execv()
fails. - Not redirecting standard error of the
procmon
process to the pipe.
管道的创建可能很重要.如最初所写,process
的两端都打开,因此filter
在继续执行process
时不会在管道上产生EOF.由于process
不太可能使用管道(它没有为它们打开哪些文件描述符的正式知识),所以确实没有意义,而且保持管道打开也可能有一定危害.
The pipe creation might be important. As originally written, the process
had both ends of the pipe open, so filter
would not get EOF on the pipe while process
continued. Since process
is unlikely to use the pipe (it has no formal knowledge of which file descriptors are open for them), there really is no point and could be some harm in keeping the pipe open.
未将标准错误重定向到管道,这使我看到了错误消息,原因是我使用的测试脚本中没有弹出按钮.
Not redirecting standard error to the pipe allowed me to see an error message from not having a shebang in the test scripts I used.
我使用了stderr.h
和stderr.c
中的一组函数,这些函数可在GitHub上的 https://github.com/jleffler/soq/tree/master/src/libsoq .它们简化了错误报告,因此我的大多数程序都使用它们.
I used a set of functions from stderr.h
and stderr.c
, which are available on GitHub at https://github.com/jleffler/soq/tree/master/src/libsoq. They simplify error reporting, so most of my programs use them.
这将导致以下代码,与您所拥有的代码相似:
This leads to the following code, which is recognizably similar to what you have:
#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;
}
然后我面临测试的问题.我创建了三个Shell脚本-process
,procmon
和filter
.看起来process
的作用并不重要,只要花费一些时间即可. procmon
可能旨在监视进程的状态.它不能是标准程序,因为您在当前目录中运行它.类似地,filter
可能意味着修改它从输入中读取的内容.因此,我发明了脚本来完成这些工作:
I was then faced with the problem of testing this. I created three shell scripts — process
, procmon
and filter
. It seems that it is not critical what process
does as long as it takes some time doing it. The procmon
is probably meant to monitor a process's status; it can't be a standard program because you run it in the current directory. Similarly, filter
is presumably meant to modify what it reads from its input. So, I invented scripts to do those jobs:
过程
#!/bin/sh
exec timeout -t 2m -- dribbler -m "$0: PID $$" -r 0.2 -s 0.5 -t
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
程序(也是Home-brew,其版本可以追溯到1989年,而不是同名的GNU程序)在指定的时间. dribbler
的-r
和-s
选项实现高斯时间分布(-s
平均睡眠时间,默认为一秒,-r
随机性的标准偏差). filter
脚本宣布它正忙,然后在输出的第一个字段中查找9s.
The dribbler
program is a home-brew that writes information slowly, and the timeout
program (also home-brew, with versions back to 1989, rather than the GNU program of the same name) stops its process after a designated time. The -r
and -s
options to dribbler
implement a Gaussian time distribution (-s
the mean sleep time, defaulting to one second, -r
the standard deviation of the randomness). The filter
script announces that it is busy and then looks for 9s in the first field of the output.
有了该基础架构,我得到的输出如下:
With that infrastructure, I got output like:
$ 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
的行.这似乎行为正确.
The output of process
is not filtered so every line of that is shown, but the output of procmon
is filtered and only lines with a 9
are shown. This seems to be behaving correctly.
这篇关于C/Linux-重定向stdin和stout时遇到麻烦的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!