Это довольно тяжелое решение, но сработает следующее:
- Создайте канал, вызвав
pipe()
- Создайте дочерний процесс
- Вparent: перенаправить
stdout
на сторону записи канала и закрыть сторону чтения (и старую stdout
) - В дочернем: продолжить чтение со стороны чтения канала и копироватьданные в унаследованный
stdout
(который является исходным stdout
) - считая его по мере того, как он проходит мимо - В родителе продолжайте записывать в
stdout
(который теперь является каналом) как обычно - Использование какой-либо формы IPC для передачи результата подсчета от дочернего элемента к родительскому.
По сути, идея состоит в том, чтобы порождать дочерний процесс и передавать весь вывод через него,и пусть дочерний процесс подсчитывает все данные по мере прохождения.
Точная форма IPC для использования может варьироваться - например, разделяемая память (с атомарным чтением / записью на каждой стороне) будет работать хорошо для быстрогопередача данных, но другие методы (такие как сокетыбольше каналов и т. д.), и они предоставляют больше возможностей для синхронизации.
Самая сложная часть - это синхронизация, то есть обеспечение того, чтобы в то время, когда ребенок сообщает родителю, сколько данных было написано, он ужеобработал все данные, которые сказал родитель (а в канале, например, ничего не осталось).Насколько это важно, будет зависеть от того, к какой именно цели вы стремитесь - если приблизительное указание - это все, что требуется, тогда вы сможете избежать использования общей памяти для IPC и не выполнять какой-либо явной синхронизации;если итог требуется только в конце, вы можете закрыть stdout
от родителя и попросить ребенка указать в общей памяти, когда он получил уведомление eof
.
Если вам требуется чащесчитывания, которые должны быть точными, тогда потребуется нечто большее, чем copmlex, но это может быть достигнуто путем разработки какого-либо протокола с использованием сокетов, каналов или даже condvars / semaphores / etc в общей памяти.