Можно ли в Linux узнать, в какой момент сообщение было записано в файловый поток? Одна программа пишет в два разных потока, другая программа читает из этих двух потоков и должна вывести сообщения в порядке записи (а не в том, каком там накешировалось).
Вот первая программа:
$ clang-format main2.c
#include <stdio.h>
int main() {
setbuf(stdout, NULL); // Отключение буферизации stdout
setbuf(stderr, NULL); // Отключение буферизации stderr
printf("Это stdout\n");
fflush(stdout);
fprintf(stderr, "Это stderr\n");
fflush(stderr);
fprintf(stderr, "Это stderr2\n");
fflush(stderr);
printf("Это stdout 2\n");
fflush(stdout);
fprintf(stderr, "Это stderr3\n");
fflush(stderr);
printf("Это stdout 3\n");
fflush(stdout);
printf("Это stdout 4\n");
fflush(stdout);
return 0;
}
Вот вторая программа:
$ clang-format main1.c
#include <errno.h>
#include <poll.h> // Для структуры pollfd и константы POLLIN
#include <pty.h>
#include <stdbool.h>
#include <stdio.h>
#include <sys/select.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h> // Для функции nanosleep
int nanosleep(const struct timespec *req, struct timespec *rem);
int max(int a, int b) { return (a > b) ? a : b; }
int main() {
int master_fd_stdin, slave_fd_stdin;
int master_fd_stdout, slave_fd_stdout;
int master_fd_stderr, slave_fd_stderr;
openpty(&master_fd_stdin, &slave_fd_stdin, NULL, NULL, NULL);
openpty(&master_fd_stdout, &slave_fd_stdout, NULL, NULL, NULL);
openpty(&master_fd_stderr, &slave_fd_stderr, NULL, NULL, NULL);
pid_t pid = fork();
if (pid == 0) {
// В дочернем процессе
close(master_fd_stdin);
close(master_fd_stdout);
close(master_fd_stderr);
dup2(slave_fd_stdin, 0);
dup2(slave_fd_stdout, 1);
dup2(slave_fd_stderr, 2);
close(slave_fd_stdin);
close(slave_fd_stdout);
close(slave_fd_stderr);
execl("./main2", "main2", NULL);
} else {
// В родительском процессе
close(slave_fd_stdin);
close(slave_fd_stdout);
close(slave_fd_stderr);
char buffer[1024];
ssize_t bytes_read;
bool is_stdout_expected = true;
bool is_stderr_expected = true;
fd_set read_fds;
int max_fd = max(master_fd_stdout, master_fd_stderr);
struct pollfd fds[2];
fds[0].fd = master_fd_stdout;
fds[0].events = POLLIN;
fds[1].fd = master_fd_stderr;
fds[1].events = POLLIN;
while (is_stderr_expected || is_stdout_expected) {
FD_ZERO(&read_fds);
if (is_stdout_expected) {
FD_SET(master_fd_stdout, &read_fds);
}
if (is_stderr_expected) {
FD_SET(master_fd_stderr, &read_fds);
}
select(max_fd + 1, &read_fds, NULL, NULL, NULL);
if (FD_ISSET(master_fd_stdout, &read_fds)) {
bytes_read = read(master_fd_stdout, buffer, 1024);
if (bytes_read > 0) {
buffer[bytes_read] = '\0'; // Добавляем нулевой символ в конец строки
printf("\033[0;37m%s\033[0m", buffer);
} else {
is_stdout_expected = false;
}
}
if (FD_ISSET(master_fd_stderr, &read_fds)) {
bytes_read = read(master_fd_stderr, buffer, 1024);
if (bytes_read > 0) {
buffer[bytes_read] = '\0'; // Добавляем нулевой символ в конец строки
printf("\033[0;31m%s\033[0m", buffer);
} else {
is_stderr_expected = false;
}
}
}
}
return 0;
}
При выводе строки выводятся в неправильном порядке. Как сделать, чтобы выводились в правильном?
Пока у меня мысль такая:
- нужно сделать библиотеку, которая содержит функции printf, fprintf и что там ещё бывает. Делать она ничего не должна, должна загрузить системную и все вызовы туда пересылать, кроме особоинтересных.
- загрузить эту библиотеку в дочерний процесс вместо системной
- каждый факт вывода оборачивать в «пакет», к которому добавлять момент времени (и номер процесса/нити?).