Tôi đã viết một mã trong C/C++ mà dĩa một tiến trình con, nhân đôi stdin/stdout thành một đầu ống và gọi execvp.Vô hiệu hóa bộ đệm đệm của một quá trình chia rẽ
Tất cả mọi thứ đang làm việc tốt (ví dụ: sản lượng từ stdin/err ra/được chụp bởi quá trình cha mẹ)
Vấn đề là các stdout đứa trẻ được đệm.
vì vậy nếu mã con trông như thế này:
printf("Enter any key and hit ENTER:\n");
fgets(line);
printf("read: %s\n", line);
exit(0);
Trong quá trình cha mẹ tôi không thấy dòng chữ 'Nhập một phím bất kỳ:' - đó sẽ là "đỏ mặt" chỉ sau khi chương trình gọi exit (trong đó ô tô sẽ xóa đệm stdout) hoặc cuộc gọi rõ ràng để 'tuôn ra (stdout)' được thêm
tôi đã làm một số nghiên cứu và cố gắng thêm một cuộc gọi để vô hiệu hóa đệm stdout bằng cách thêm một cuộc gọi đến:
setvbuf (stdout, NULL, _IONBF, 0); ngay trước khi gọi execvp (...) trong quá trình mẹ
để mã có liên quan hiện nay trông như thế này:
int rc = fork();
if (rc == 0) {
// Child process
if(workingDirectory.IsEmpty() == false) {
wxSetWorkingDirectory(workingDirectory);
}
int stdin_file = fileno(stdin );
int stdout_file = fileno(stdout);
int stderr_file = fileno(stderr);
// Replace stdin/out with our pipe ends
dup2 (stdin_pipe_read, stdin_file);
close(stdin_pipe_write);
dup2 (stdout_pipe_write, stdout_file);
dup2 (stdout_pipe_write, stderr_file);
close(stdout_pipe_read);
setvbuf(stdout, NULL, _IONBF, 0);
// execute the process
execvp(argv[0], argv);
exit(0);
}
Với không may mắn.
Bất kỳ ý tưởng nào?
EDIT:
đây là một mẫu mã cha mẹ, điều duy nhất cần thay đổi là đường dẫn đến đứa trẻ thực thi:
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/select.h>
#include <errno.h>
#include <sys/wait.h>
#include <string>
#include <string.h>
#include <cstdio>
static int read_handle(-1);
static pid_t pid;
bool read_from_child(std::string& buff) {
fd_set rs;
timeval timeout;
memset(&rs, 0, sizeof(rs));
FD_SET(read_handle, &rs);
timeout.tv_sec = 1; // 1 second
timeout.tv_usec = 0;
int rc = select(read_handle+1, &rs, NULL, NULL, &timeout);
if (rc == 0) {
// timeout
return true;
} else if (rc > 0) {
// there is something to read
char buffer[1024*64]; // our read buffer
memset(buffer, 0, sizeof(buffer));
if(read(read_handle, buffer, sizeof(buffer)) > 0) {
buff.clear();
buff.append(buffer);
return true;
}
return false;
} else { /* == 0 */
if (rc == EINTR || rc == EAGAIN) {
return true;
}
// Process terminated
int status(0);
waitpid(pid, &status, 0);
return false;
}
}
void execute() {
char *argv[] = {"/home/eran/devl/TestMain/Debug/TestMain", NULL};
int argc = 1;
int filedes[2];
int filedes2[2];
// create a pipe
int d;
d = pipe(filedes);
d = pipe(filedes2);
int stdin_pipe_write = filedes[1];
int stdin_pipe_read = filedes[0];
int stdout_pipe_write = filedes2[1];
int stdout_pipe_read = filedes2[0];
int rc = fork();
if (rc == 0) {
// Child process
int stdin_file = fileno(stdin );
int stdout_file = fileno(stdout);
int stderr_file = fileno(stderr);
// Replace stdin/out with our pipe ends
dup2 (stdin_pipe_read, stdin_file);
close(stdin_pipe_write);
dup2 (stdout_pipe_write, stdout_file);
dup2 (stdout_pipe_write, stderr_file);
close(stdout_pipe_read);
setvbuf(stdout, NULL, _IONBF, 0);
// execute the process
execvp(argv[0], argv);
} else if (rc < 0) {
perror("fork");
return;
} else {
// Parent
std::string buf;
read_handle = stdout_pipe_read;
while(read_from_child(buf)) {
if(buf.empty() == false) {
printf("Received: %s\n", buf.c_str());
}
buf.clear();
}
}
}
int main(int argc, char **argv) {
execute();
return 0;
}
Tôi nghĩ rằng bạn cần phải đóng (stdout_pipe_write) và stdin_piperead sau khi các cuộc gọi tương ứng để dup2 – Flexo