C++ 读取标准文件
我已经创建了以下模拟问题的测试用例。我已经编译了源代码并能够模拟问题 1) 当系统命令发出时,我们得到了一些控制台(即您提交的作业),它使用dup2重定向到文件并创建file.stdout 当我试图读取此文件时,因为我需要作业提交信息,但并没有从控制台中获取数据。我能够得到我写的数据。(确认文件操作) 我们不能从子进程创建的文件中读取控制台输出 *更改rundir和cmdC++ 读取标准文件,c++,linux,file-io,operating-system,C++,Linux,File Io,Operating System,我已经创建了以下模拟问题的测试用例。我已经编译了源代码并能够模拟问题 1) 当系统命令发出时,我们得到了一些控制台(即您提交的作业),它使用dup2重定向到文件并创建file.stdout 当我试图读取此文件时,因为我需要作业提交信息,但并没有从控制台中获取数据。我能够得到我写的数据。(确认文件操作) 我们不能从子进程创建的文件中读取控制台输出 *更改rundir和cmd #include <string> #include <vector> #include <u
#include <string>
#include <vector>
#include <utility>
#include <sstream>
#include <fstream>
#include <iostream>
#include <iterator>
#include <algorithm>
#include <functional>
#include <map>
#include <sys/stat.h>
#include <fcntl.h>
using namespace std;
int child();
int main()
{
string rundir = "/temp";
pid_t id =child();
string _xafile;
string _afile;
string _afilecmd;
string line;
stringstream ss(stringstream::in | stringstream::out);
ss<<int(id);
_xafile = rundir;
_xafile = _xafile + "/" + ss.str()+".stdout";
cout<<" _xafile is "<<_xafile<<endl;
string cmd ="cat "+ _xafile + ">" + rundir + "/" + "process.txt";
_afile = rundir;
_afile = _afile + "/" + "process.txt";
_afilecmd = "rm -rf "+ _afile;
system(cmd.c_str());
ifstream xafile(_afile.c_str());
while(xafile)
{
string word;
xafile >> word;
cout<<word<<" ";
/* try to read console output but did not read data */
}
system(_afilecmd.c_str());
return 0;
}
int child()
{
string rundir = "/tmp";
string cmd = " tool <input file> -o <outputfile>";
const char* std_out_file;
pid_t pid = fork();
if (pid < 0) {
return -1;
}
if (pid == 0) {
pid_t mypid = getpid();
stringstream sm;
sm << rundir << "/";
if (strlen(std_out_file) == 0)
sm << mypid << ".stdout";
else
sm << std_out_file;
int fd = open(sm.str().c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0644);
dup2(fd, 1);
dup2(fd, 2);
int fd2 = open("/dev/zero", O_RDONLY);
dup2(fd2, 0);
cout<<cmd <<endl<<endl;
// execl("/bin/sh", "/bin/sh", "-c", cmd, NULL);
system(cmd.c_str());
/*When system call it generate console output like : your job submitted */
/* redirect to file */
exit(-1);
}
if (pid > 0)
return pid;
cout<<" child is done"<<endl;
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
int child();
int main()
{
字符串rundir=“/temp”;
pid_t id=child();
字符串xau文件;
字符串文件;
字符串_afilecmd;
弦线;
stringstream ss(stringstream::in | stringstream::out);
ss您的想法还不完全清楚-您的代码似乎有一个孩子,他做了一堆奇特的io工作,试图将您的应用程序stdout重定向到一个文件,然后用system()运行一个命令。您代码中的命令有自己的重定向,特别是通过“-o”,因此它可能没有写入stdout
回到父进程,您尝试打开以读取子进程将打开以写入的同一文件。您没有同步,因此它们可能以任何顺序发生。您似乎试图使用“cat”读取文件并尝试读取cat的标准输出
我认为您实际上正在尝试做的是C/C++与Perl的等价物
$foo = `ls -l /tmp`;
或者类似的操作—执行命令并捕获输出
更好的方法是使用管道
#include <iostream>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
enum { WritePipe = 1, ReadPipe = 0 };
int main(int argc, const char** argv)
{
int pipes[2]; // each process is going to have its own file descriptor.
if(pipe(pipes) != 0) {
perror("pipe failed");
return -1;
}
pid_t pid = fork();
if(pid == 0) {
// child
close(pipes[ReadPipe]); // close the parent pipe in our context.
// redirect stdout and stderr to the pipe.
dup2(pipes[WritePipe], STDOUT_FILENO);
dup2(pipes[WritePipe], STDERR_FILENO);
// close(STDERR_FILENO); // <- or just do this to close stderr.
int result = system("ls -ltr /etc");
close(pipes[WritePipe]);
return result;
}
if(pid < 0) {
perror("fork failed");
return -1;
}
// Parent process has launched the child.
close(pipes[WritePipe]);
char buffer[4097];
int bytesRead;
while((bytesRead = read(pipes[ReadPipe], buffer, sizeof(buffer) - 1)) > 0) {
buffer[bytesRead] = 0;
std::cout << buffer;
}
std::cout << std::endl;
close(pipes[ReadPipe]);
return 0;
}
#包括
#包括
#包括
#包括
枚举{writepe=1,ReadPipe=0};
int main(int argc,常量字符**argv)
{
int pipes[2];//每个进程都有自己的文件描述符。
如果(管道)!=0){
perror(“管道故障”);
返回-1;
}
pid_t pid=fork();
如果(pid==0){
//孩子
close(pipes[ReadPipe]);//关闭上下文中的父管道。
//将stdout和stderr重定向到管道。
dup2(管道[WritePie],标准文件号);
dup2(管道[WritePie],标准文件号);
//关闭(STDERR_FILENO);//0){
缓冲区[字节读取]=0;
std::cout您的想法还不完全清楚-您的代码似乎有一个孩子,他做了一堆奇特的io工作,试图将您的应用程序stdout重定向到一个文件,然后使用system()运行一个命令。您代码中的命令有自己的重定向,特别是通过“-o”,因此它可能没有写入stdout
回到父进程,您尝试打开以读取子进程将打开以写入的同一文件。您没有同步,因此它们可能以任何顺序发生。您似乎试图使用“cat”读取文件并尝试读取cat的标准输出
我认为您实际上正在尝试做的是C/C++与Perl的等价物
$foo = `ls -l /tmp`;
或者类似的操作—执行命令并捕获输出
更好的方法是使用管道
#include <iostream>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
enum { WritePipe = 1, ReadPipe = 0 };
int main(int argc, const char** argv)
{
int pipes[2]; // each process is going to have its own file descriptor.
if(pipe(pipes) != 0) {
perror("pipe failed");
return -1;
}
pid_t pid = fork();
if(pid == 0) {
// child
close(pipes[ReadPipe]); // close the parent pipe in our context.
// redirect stdout and stderr to the pipe.
dup2(pipes[WritePipe], STDOUT_FILENO);
dup2(pipes[WritePipe], STDERR_FILENO);
// close(STDERR_FILENO); // <- or just do this to close stderr.
int result = system("ls -ltr /etc");
close(pipes[WritePipe]);
return result;
}
if(pid < 0) {
perror("fork failed");
return -1;
}
// Parent process has launched the child.
close(pipes[WritePipe]);
char buffer[4097];
int bytesRead;
while((bytesRead = read(pipes[ReadPipe], buffer, sizeof(buffer) - 1)) > 0) {
buffer[bytesRead] = 0;
std::cout << buffer;
}
std::cout << std::endl;
close(pipes[ReadPipe]);
return 0;
}
#包括
#包括
#包括
#包括
枚举{writepe=1,ReadPipe=0};
int main(int argc,常量字符**argv)
{
int pipes[2];//每个进程都有自己的文件描述符。
如果(管道)!=0){
perror(“管道故障”);
返回-1;
}
pid_t pid=fork();
如果(pid==0){
//孩子
close(pipes[ReadPipe]);//关闭上下文中的父管道。
//将stdout和stderr重定向到管道。
dup2(管道[WritePie],标准文件号);
dup2(管道[WritePie],标准文件号);
//关闭(STDERR_FILENO);//0){
缓冲区[字节读取]=0;
STD::CUT考虑在你的问题中确定代码的缩进。BTW,如果你使用“使用空格而不是标签”,你就可以避免混乱了。编辑器的选项…在写入标准输入之前,您似乎应该使用dup2
。我没有理解您。它已经生成了我需要读取的processid.stdout文件。您通常会将程序/dev/null
作为标准输入,而不是/dev/zero
。如果您提供/dev/zero
因为它有无限多的零字节供进程读取。您应该始终检查open
类操作是否成功;在失败后盲目前进可能会导致问题。使用dup()
或dup2()后
要将文件描述符复制到标准输入、标准输出或标准错误,您几乎应该总是关闭原始文件描述符。在execl()
之前使用chdir()
是不寻常的;这是否按照您的意愿工作?(您是否已打印出wd
?在执行chdir()
之前,进程在哪个目录中?)如果execl()
失败,您是否考虑过报告错误?这可能有助于您确定出了什么问题。(但在从execl()返回后退出是件好事。),因为返回总是意味着它失败了。你打印出了<代码> CMD < /代码>的值吗?考虑在你的问题中修改代码的缩进。BTW,如果你使用“使用空格而不是标签”,你就可以避免混乱了。编辑器的选项…在写入标准输入之前,您似乎应该使用dup2
。我没有理解您。它已经生成了我需要读取的processid.stdout文件。您通常会将程序/dev/null
作为标准输入,而不是/dev/zero
。如果您提供/dev/zero
因为它有无限多的零字节供进程读取。