Существует 3 конвейерных вызова для создания stdin, stdout, stderr для нового процесса.вызывается fork (), вызывается exec ().Это обернуто в функцию popen2, которая работает.
При использовании этой функции popen2 чтение из stdout из новых блоков процесса в read (), даже после того, как select () возвращает, что read готов для чтения.Я ожидаю, что он сможет читать ().Мое единственное предположение, что read () для этого fd пытается заполнить входной буфер.
Одно исключение: если stdin закрыт, stdout закрывается дочерним процессом, и чтение завершается, даже когда buf не может быть заполнен.
Мне нужно, чтобы read () возвратила то, чтоготов быть прочитанным?режим по умолчанию буферизован, а я его не знаю?
pid_t popen2(const char *const argv[], int *in, int *out, int *err)
{
int res;
pid_t pid = 0;
int inpipefd[2];
int outpipefd[2];
int errpipefd[2];
if(0!=pipe(inpipefd)) {
perror("allocating pipe for child stdin");
return -1;
}
if(0!=pipe(outpipefd)) {
close(inpipefd[0]);
close(inpipefd[1]);
perror("allocating pipe for child stdout");
return -1;
}
if(0!=pipe(errpipefd)) {
close(inpipefd[0]);
close(inpipefd[1]);
close(outpipefd[0]);
close(outpipefd[1]);
perror("allocating pipe for child stderr");
return -1;
}
pid = fork();
if (0==pid) {
if (-1==dup2(inpipefd[0], STDIN_FILENO)) {exit(errno);}
if (-1==dup2(outpipefd[1], STDOUT_FILENO)) {exit(errno);}
if (-1==dup2(errpipefd[1], STDERR_FILENO)) {exit(errno);}
close(inpipefd[0]);
close(inpipefd[1]);
close(outpipefd[0]);
close(outpipefd[1]);
close(errpipefd[0]);
close(errpipefd[1]);
execvp(argv[0], (char* const*)argv);
perror("exec failed");
exit(1);
}
close(inpipefd[0]);
close(outpipefd[1]);
close(errpipefd[1]);
*in = inpipefd[1];
*out = outpipefd[0];
*err = errpipefd[0];
return pid;
}
...
if(0>=(pid = popen2(argv, &in, &out, &err))) {
return make_unique<std::string>();
}
res = writeall(in, cont.c_str(), cont.length());
if(res==-1) {
goto err;
}
close(in);
...
unique_ptr<std::string> DecryptProcess::Read() {
auto result = make_unique<std::string>();
const unsigned int BUFLEN = 1024*16;
std::vector<char> buf(BUFLEN);
fd_set rfds;
struct timeval tv;
int n;
int fcnt;
FD_ZERO(&rfds);
FD_SET(out_fd, &rfds);
FD_SET(err_fd, &rfds);
tv.tv_sec = 0;
tv.tv_usec = 100000;
fcnt = select(std::max(out_fd, err_fd)+1, &rfds, NULL, NULL, &tv);
if (fcnt == -1) {
return result;
} else if (!fcnt) {
return result;
}
if (FD_ISSET(err_fd, &rfds)) {
n = read(err_fd, &buf[0], buf.size());
}
if (FD_ISSET(out_fd, &rfds)) {
do
{
n = read(out_fd, &buf[0], buf.size());
if (n == -1) {
return result;
}
if (n>0)
result->append(buf.cbegin(), buf.cbegin()+n);
} while ( n > 0 );
}
return result;
}