1

問題をシミュレートするために、次のテスト ケースを作成しました。ソース コードをコンパイルし、問題をシミュレートすることができました。

1) システム コマンドを実行すると、dup2 を使用してファイルにリダイレクトされ、ファイル .stdout を作成するコンソールが出力されます (つまり、ジョブがサブミットされます)。

ジョブ送信情報が必要なため、このファイルを読み取ろうとしたときに、コンソールにあるデータを取得できませんでした。書き込んだデータを取得できました(ファイル動作確認)。

子プロセスによって作成されたファイルからコンソール出力を読み取れませんか。

* rundir と cmd を変更

#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;
}
4

1 に答える 1

1

あなたの考えがここにあることは完全には明らかではありません-あなたのコードは、アプリケーションのstdoutをファイルにリダイレクトしようとする多くの派手なio処理を実行する子をフォークしているように見え、次にsystem()でコマンドを実行します。コード内のコマンドには、特に「-o」を介した独自のリダイレクトがあるため、おそらく stdout に書き込まれていません。

親プロセスに戻り、子プロセスが書き込み用に開くのと同じファイルを読み取り用に開こうとします。同期がないため、それらは任意の順序で発生する可能性があります。「cat」を使用してファイルを読み取ろうとしているように見えますが、猫の stdout を読み取ろうとしていますか?

あなたが実際にやろうとしていると思うのは、PerlのC/C++に相当するものです

$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;
}
于 2013-06-24T06:12:18.960 に答える