- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我有以下程序:
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
启动 procmon
程序filter
procmon
的输出应该被发送到 filter
的输入,这意味着 - filter
将从它的标准输入读取什么 procmon
正在写入其标准输出。
出于某种原因,我没有得到想要的结果。
procmon
的工作是获取给定进程的 PID,访问相应的 /proc/PID/stat
文件并打印进程状态。filter
需要接受它并且只打印状态从一个状态变为另一个状态的那一行。目前,我没有从 filter
得到任何东西。
process
进入休眠 3 秒的循环(10 次迭代),然后开始另一个循环,将变量递增 400,000 次。
我做对了吗?
最佳答案
“没有得到想要的结果”并不能很好地描述您所面临的问题。
总体来说,代码还不错。我做了一些重大更改和一些无关紧要的更改(移动变量声明、初始化变量而不是分配它们、格式化)。重大变化包括:
execv()
失败。procmon
的标准错误处理到管道。管道创建可能很重要。如最初所写,process
管道的两端都打开了,所以filter
process
时不会在管道上获得 EOF继续。自 process
不太可能使用管道(它不知道为它们打开了哪些文件描述符),保持管道打开确实没有意义,而且可能会有一些危害。
不将标准错误重定向到管道让我看到一条错误消息,因为我使用的测试脚本中没有 shebang。
我使用了 stderr.h
中的一组函数和 stderr.c
,可在 GitHub 上找到 https://github.com/jleffler/soq/tree/master/src/libsoq .它们简化了错误报告,因此我的大多数程序都使用它们。
这将导致以下代码,可以看出它与您所拥有的相似:
#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
大概是为了修改它从输入中读取的内容。所以,我发明了脚本来完成这些工作:
过程
#!/bin/sh
exec timeout -t 2m -- dribbler -m "$0: PID $$" -r 0.2 -s 0.5 -t
进程
#!/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 程序)在指定时间后停止其进程。 -r
和 -s
dribbler
的选项实现高斯时间分布(-s
平均 sleep 时间,默认为一秒,-r
随机性的标准偏差)。 filter
脚本宣布它正忙,然后在输出的第一个字段中查找 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
的行显示。这似乎是正确的行为。
关于C/Linux - 在重定向 stdin 和 stout 时遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41972528/
我有以下代码可以完全按预期工作: from subprocess import Popen process = Popen( ["/bin/bash"], stdin=sys.stdi
我有一个关于 php-cli 的新问题。 我正在使用这个: define("STDIN", fopen('php://stdin','r')); $input = ""; while($input =
这个问题在这里已经有了答案: Can fseek(stdin,1,SEEK_SET) or rewind(stdin) be used to flush the input buffer inste
我正在编写一个 python 程序,它将所有输入都大写(替代非工作 tr '[:lowers:]' '[:upper:]')。语言环境是 ru_RU.UTF-8,我使用 PYTHONIOENCODIN
自从我发现 fflush(stdin) 不是处理熟悉的“换行潜伏在输入缓冲区中”问题的可移植方法,我一直在使用当我必须使用scanf时如下: while((c = getchar()) != '\n'
当我使用时在 Perl 模块( *.pm )文件中,它不会从键盘读取输入,但是当我使用 时在同一个地方它工作得很好。 为什么我使用时没有得到输入? 最佳答案 STDIN 是记录的文件句柄。还有 st
stdin 是否是一个指针,正如我在 fgets() 中看到的那样。 我使用“0”作为标准输入的读取或写入错误,并在 fgets 期间出现段错误。 STDIN宏和0是否相同。 stdin 是文件指针吗
我想知道 STDIN 和 $stdin 之间是否有任何真正的区别。我在 irb: STDIN == $stdin 并返回 true。它们只是同一事物的两个名称吗?还是有什么不同? 最佳答案 来自 Ru
有没有一种简单的方法可以将内容通过管道传输到编辑器原子? 例如: echo "Content." | atom 不幸的是atom没有获取到内容。当前版本的 gedit 具有参数 - 以启用读取 STD
这个问题已经有答案了: Using fflush(stdin) (7 个回答) 已关闭 9 年前。 我有一个这样的测试代码 #include #include #include int main
我有一个 bash启动 scp 的脚本通过以下方式: echo "${SCP_PASS:-$PASSWORD}" | ( exec 3<&0; scp -qp ${SCP_PORT:+-P$SCP_P
我正在创建一个 NASM 汇编代码来从标准输入读取文件中存在的二维数字数组我正在运行这样的可执行文件 -> ./abc < input.txt . 之后,我将在终端上显示读取的二维数组,然后我想获取箭
这是一个循环,它重复地从 stdin 获取两个字符并输出它们。 char buf[2]; while (1) { printf("give me two characters: ");
我有一个 golang 程序,可以为 jq 做一个简单的 repl。 .我希望能够在程序启动时从 stdin 读取输入到一个临时文件中,这样我就可以将 repl 与管道输入一起使用。 cat file
有没有非阻塞的 PHP 从 STDIN 读取: 我试过了: stream_set_blocking(STDIN, false); echo fread(STDIN, 1); 还有这个: $stdin
这实际上与我已经回答的另一个问题有关。这个问题在这里:Redirecting stdout of one process object to stdin of another 我的问题是(我认为)获取
我只是一个java初学者,目前正在大学学习,但由于某些原因我不会深入,我无法询问我的导师。 我在 Netbeans 中使用 StdIn 库时遇到问题。在类里面我们使用 DrJava,但由于我无法让它在
Ruby 有两种引用标准输入的方法:STDIN 常量和$stdin 全局变量。 除了我可以将不同的 IO 对象分配给 $stdin 因为它不是常量(例如,在我的 child 中 fork 重定向 IO
我是 Pythonizer 的作者我正在尝试将 CGI.pm 的代码从标准 perl 库转换为 Python。我在 read_from_client 中看到这段代码: read(\*STDIN, $$
我正在使用 laravel 5.6 并遇到问题,当我在控制台中使用命令“php artisan vendor:publish”时,出现以下错误: [ERROR] Use of undefined co
我是一名优秀的程序员,十分优秀!