【发布时间】:2020-10-24 05:01:01
【问题描述】:
#1:给定命令,我不知道标准输出产生的输出大小。
#2:我不想像这样使用 char 数组
char buffer[1024];
因为这会导致内存不足或浪费。
#3:如果我使用像这样的字符指针
char *buffer;
我将不得不为它分配内存
buffer = (char *)malloc(1024 * sizeof(char));
#4:如果我在 while 循环中使用 getc(),比如
char *buf, c;
int i=0, j=1;
int pipefd[2];
int stdout_bk;
code[message_read] = '\0';
stdout_bk = dup(fileno(stdout));
pipe(pipefd);
dup2(pipefd[1], STDOUT_FILENO);
system(code);
close(pipefd[1]);
dup2(stdout_bk, STDOUT_FILENO);
buf = (char*)malloc(sizeof(char));
while(c!=End_Of_File) // What should I replace End_Of_File with?
{
c = getc(pipefd[0]);
buf = (char*)realloc(buf, j * sizeof(char));
buf[i] = c;
i++;
j++;
}
我不知道标准输出数据的 End_Of_file 是什么。
PS:程序运行一个命令,例如 system("setarch x86_64 -R dd if=/proc/self/maps | grep bin/dd") 或 system("ls -al") 我需要得到标准输出。为此,我使用了 dup2 并且需要将输出通过管道传输到缓冲区。
注意:输出可以是可变长度的。
【问题讨论】:
-
我认为关于这个话题已经有很多问题了,所以只是评论:将
c声明为int(不是char),将while(c!=End_Of_File)替换为while ((c=getc(stdin)) != EOF)(用任何东西替换stdin),并在下一行去掉对get()的调用。 -
为每个字符调用 realloc 并不常见,即使我认为它在内部进行了优化以分配更大的块。
-
为什么不使用 POSIX 标准函数
popen()来获取包含您给它的命令的输出的文件流。您的管道有很多管道问题;使用popen()将避免其中的大部分。 -
您的系统有多少主内存,您认为 1 KiB 缓冲区会造成问题?在大多数非嵌入式系统上,您可以分配 64 KiB 而不会造成任何问题。您可能希望避免堆栈上的兆字节缓冲区;默认情况下,堆栈在 Windows 上限制为 1 MiB(在类 Unix 系统上通常为 8 MiB)。
-
#4 中的代码仅适用于非常小的输出,因为在执行的命令终止之前它不会开始读取。这意味着它依靠管道充当整个输出的缓冲区。管道确实有缓冲作用,但它们这样做的能力是有限的;一旦你填满了管道缓冲区,写入它就会阻塞,这意味着你的程序将有效地死锁。如果您使用的是 Linux,请阅读man 7 pipe 了解更多详细信息(特别注意“管道容量”)。或者阅读 IPC 上的任何好文章。
标签: c string dynamic malloc stdout