Я хочу запустить tcpdump на 5 секунд и получить его стандартный вывод. Проблема в том, что когда я читаю в неблокирующем режиме, все работает как положено. Но поскольку я не хочу застревать в чтении, я использую неблокирующее чтение. Когда я использую неблокирующее чтение, я получаю стандартный вывод tcpdump каждые 4096 байт. Я искал много раз и пробовал много вещей, но все равно безуспешно.
Пожалуйста, скажите мне, что я делаю неправильно. Как я могу читать в неблокирующем режиме из стандартного вывода дочернего процесса, не дожидаясь заполнения его буфера?
#include
#include
#include
#include
#include
#include
#include
#define PIPE_READ 0
#define PIPE_WRITE 1
// Function to set a file descriptor to non-blocking mode
void set_nonblocking(int fd) {
int flags = fcntl(fd, F_GETFL, 0);
if (flags == -1) {
perror("fcntl F_GETFL");
exit(1);
}
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
perror("fcntl F_SETFL");
exit(1);
}
}
int main() {
int stdout_pipe[2], stderr_pipe[2];
pid_t pid;
// Create two pipes: one for stdout, one for stderr
if (pipe(stdout_pipe) == -1) {
perror("pipe stdout");
exit(1);
}
if (pipe(stderr_pipe) == -1) {
perror("pipe stderr");
exit(1);
}
// Fork the process
pid = fork();
if (pid == -1) {
// Error during fork
perror("fork");
exit(1);
}
if (pid == 0) { // Child process
// Close the unused ends of the pipes in the child
close(stdout_pipe[PIPE_READ]);
close(stderr_pipe[PIPE_READ]);
// Set stdout and stderr to be unbuffered
setvbuf(stdout, NULL, _IONBF, 0); // Unbuffered stdout
setvbuf(stderr, NULL, _IONBF, 0); // Unbuffered stderr
// Redirect stdout and stderr to the pipes
dup2(stdout_pipe[PIPE_WRITE], STDOUT_FILENO);
dup2(stderr_pipe[PIPE_WRITE], STDERR_FILENO);
// Close the pipe write ends since they're now redirected
close(stdout_pipe[PIPE_WRITE]);
close(stderr_pipe[PIPE_WRITE]);
// Child runs tcpdump (for example)
execlp("timeout", "timeout", "5s", "tcpdump", "src", "port", "41972", (char *)NULL);
// If execlp fails
perror("execlp");
exit(1);
} else { // Parent process
char buffer[256];
int status;
ssize_t nbytes;
// Close the unused ends of the pipes in the parent
close(stdout_pipe[PIPE_WRITE]);
close(stderr_pipe[PIPE_WRITE]);
// Set both pipe file descriptors to non-blocking
set_nonblocking(stdout_pipe[PIPE_READ]);
set_nonblocking(stderr_pipe[PIPE_READ]);
// Parent process reads from the pipes in non-blocking mode
printf("Parent is reading from child's stdout:\n");
while (1) {
// Try to read from stdout pipe
nbytes = read(stdout_pipe[PIPE_READ], buffer, sizeof(buffer) - 1);
if (nbytes > 0) {
buffer[nbytes] = '\0'; // Null-terminate the string
printf("%s", buffer);
} else if (nbytes == 0) {
// EOF reached (child process closed its end)
break;
} else if (errno != EAGAIN && errno != EWOULDBLOCK) {
// Handle other errors
perror("read stdout");
break;
}
// Try to read from stderr pipe
nbytes = read(stderr_pipe[PIPE_READ], buffer, sizeof(buffer) - 1);
if (nbytes > 0) {
buffer[nbytes] = '\0'; // Null-terminate the string
printf("%s", buffer);
} else if (nbytes == 0) {
// EOF reached (child process closed its end)
break;
} else if (errno != EAGAIN && errno != EWOULDBLOCK) {
// Handle other errors
perror("read stderr");
break;
}
// Sleep for a short time to avoid tight loop (can adjust as needed)
usleep(100000); // sleep for 100ms
}
// Wait for the child process to exit
waitpid(pid, &status, 0);
// Close the pipe read ends in the parent
close(stdout_pipe[PIPE_READ]);
close(stderr_pipe[PIPE_READ]);
}
return 0;
}
Подробнее здесь: https://stackoverflow.com/questions/792 ... uffer-size