LINUX.ORG.RU

c,stdout,начинающий

 , ,


0

1

Здравствуй, ЛОР!

Ткните носом. Осваиваю Си. Застрял в одном месте.

В программе стандартныe вывода (stdout и stderr) одной консольной программы через каналы (pipe) завел в основную программу. Файловые дескрипторы каналов преобразовал в поток даных (FILE*), чтобы обрабатывать их стандартной библиотекой си. События о том, что в каналах появились новые данные обрабатываю в epoll().

Вот кусок кода.

	while (1) {	
		nr_events = epoll_wait (epfd, events, 64, -1);
		
		if (nr_events<0) {
			perror ("epoll_wait:");
			free (events);
			exit(EXIT_FAILURE);
		}
		
		
		if (nr_events >0) {			
			for (n = 0; n < nr_events; ++n) {
			
				int i =0;
				if (events [n].data.fd == 3) {	
					while ((sym = fgetc (stream_info)) != '\n') {			
						buff[i++] = sym;
					}								
					buff[i]   = '\0';
					printf ("STDOUT - %s \n", buff);										
				}
			
				int k = 0;
				if (events [n].data.fd == 5) {							
					while ((sym = fgetc (stream_err)) != '\n') {							
						buff_err[k++] = sym;							
					}							
					buff_err[k]   = '\0';
					printf ("STDERR - %s \n", buff_err);					
				}					
			}			
		}
	}

В принципе код рабочий, но, если только принимается одна строка. Если в выводе за одно событие больше 2-х строк, вижу только первую. Остаток прочитается при следующем событии. По коду ясно почему так. Не понятно как правильно определить, что в потоке больше нет данных? И как правильно парсить стандартные потоки?


Сначала пытался определить по EOF, код не отработал. Потом попробовал '\n', по строкам считывает. Вот и возник у меня вопрос. Если правильно определять конец данных по EOF, то где ошибка в коде?

salik
() автор топика

Просто не смешивай файловые дескрипторы с файловыми потоками. Если ты работаешь с FILE *stdint то ты не можешь гарантировать что символы всё ещё в STDIN_FILENO, а не в каких-то буферах потока. Используешь epoll? Вот и дальше работай с дескрипторами, а не с потоками.

Вот тебе цитата из гнутой доки

You must also use file descriptors if your program needs to do input or output in special modes, such as nonblocking (or polled) input

kim-roader ★★
()
Ответ на: комментарий от kim-roader

Наглядная демонстрация:

$ cat test.c 
#include <stdio.h>
#include <unistd.h>

int main()
{
  int a = fgetc(stdin);

  char b;  int count = read (STDIN_FILENO, &b, 1);

  int c = fgetc(stdin);

  printf ("%c %c\n%d %d\n", a, c, b, count);
}
$ gcc test.c ; echo -e '123\nqwe' | ./a.out 

В таком случае у тебя при первом fgetc весь ввод попадёт в буферы и read считает 0 символов, а если ты строчку с командой read переместишь выше строчки с fgetc, то каждый из вызовов будет возвращать по одному символу.

kim-roader ★★
()
Ответ на: комментарий от kim-roader

Спасибо, понял. Перепишу используя только файловые дескрипторы.

salik
() автор топика
Ответ на: комментарий от kim-roader

Все работает. Еще раз спасибо.

salik
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.