Определение наличия данных в stdin
От: kong Украина  
Дата: 12.09.02 05:45
Оценка:
Есть такая проблемка: пишется прога, которая забирает данные по конвееру из сислога. Для этого надо определять есть ли данные в stdin. Если просто опрашивать stdin, то прога сильно грузит процессор. Нужен совет как сделать так, чтобы прога находилась в спящем режиме, а при поступлении данных в stdin — просыпалась.

Попоробывал вот такое решение проблемы:
  int iRes_stdin, iStdin;
  struct timeval timeout;
  fd_set readfd;

  //definition of presence of the data in stdin
  iStdin=fileno(stdin);  
  FD_ZERO(&readfd);
  FD_SET(iStdin, &readfd);
  timeout.tv_sec = 60;
  timeout.tv_usec = 60000;

  iRes_stdin = select(iStdin + 1, &readfd, NULL, NULL, &timeout);
  if (iRes_stdin > 0 )
  { 
      //забираю данные
  }

По идее функция select() определяет наличие готовых к чтению дескрипоторов и тогда возвращает положительное значение. Если таймаут истек то возвращается ноль. Вроде все подходит, но почему-то select()всегда возвращает, что дескриптор stdin готов для чтения — даже когда в потоке нет данных. В чем ошибка?
Re: Определение наличия данных в stdin
От: Anatolix Россия https://www.linkedin.com/in/anatolix/
Дата: 12.09.02 05:57
Оценка:
Здравствуйте kong, Вы писали:

K>Есть такая проблемка: пишется прога, которая забирает данные по конвееру из сислога. Для этого надо определять есть ли данные в stdin. Если просто опрашивать stdin, то прога сильно грузит процессор. Нужен совет как сделать так, чтобы прога находилась в спящем режиме, а при поступлении данных в stdin — просыпалась.



А помоему тебе надо просто читать из stdin и когда в нем не будет данных
твою прогу забликируют до их поступления

т.е. когда ты делаешь cin >> s; прога ведь ждет пока ты что-то наберешь
Любая проблема дизайна может быть решена введением дополнительного абстрактного слоя, за исключением проблемы слишком большого количества дополнительных абстрактных слоев
Re[2]: Определение наличия данных в stdin
От: kong Украина  
Дата: 12.09.02 06:14
Оценка:
Здравствуйте Anatolix, Вы писали:

A>Здравствуйте kong, Вы писали:


K>>Есть такая проблемка: пишется прога, которая забирает данные по конвееру из сислога. Для этого надо определять есть ли данные в stdin. Если просто опрашивать stdin, то прога сильно грузит процессор. Нужен совет как сделать так, чтобы прога находилась в спящем режиме, а при поступлении данных в stdin — просыпалась.


A>А помоему тебе надо просто читать из stdin и когда в нем не будет данных

A>твою прогу забликируют до их поступления
A>т.е. когда ты делаешь cin >> s; прога ведь ждет пока ты что-то наберешь

Да дело в том что я пишу на чистой сюхе, а вроде cin >> s это уже С++. Данные у меня идут сроками, причем строки не фиксированной длины (от 25 символов и до ...). Для этого я сначала определяю длину строки в stdin (функция
pStr_stdin = fgetln(stdin, &SyslogStr_len)), а потом просто копирую ее в свой локальный буфер (указатель pStr_stdin стоит на начале строки). Вот этот метод и грузит проц — проверял.
Re: Определение наличия данных в stdin
От: santucco  
Дата: 12.09.02 06:36
Оценка:
Здравствуйте kong, Вы писали:

K>Есть такая проблемка: пишется прога, которая забирает данные по конвееру из сислога. Для этого надо определять есть ли данные в stdin. Если просто опрашивать stdin, то прога сильно грузит процессор. Нужен совет как сделать так, чтобы прога находилась в спящем режиме, а при поступлении данных в stdin — просыпалась.


K>Попоробывал вот такое решение проблемы:

K>
K>  int iRes_stdin, iStdin;
K>  struct timeval timeout;
K>  fd_set readfd;

K>  //definition of presence of the data in stdin
K>  iStdin=fileno(stdin);  
K>  FD_ZERO(&readfd);
K>  FD_SET(iStdin, &readfd);
K>  timeout.tv_sec = 60;
K>  timeout.tv_usec = 60000;

K>  iRes_stdin = select(iStdin + 1, &readfd, NULL, NULL, &timeout);
K>  if (iRes_stdin > 0 )
K>  { 
K>      //забираю данные
K>  }
K>

K>По идее функция select() определяет наличие готовых к чтению дескрипоторов и тогда возвращает положительное значение. Если таймаут истек то возвращается ноль. Вроде все подходит, но почему-то select()всегда возвращает, что дескриптор stdin готов для чтения — даже когда в потоке нет данных. В чем ошибка?
А ты, случаем, daemon из своего процесса не делаешь?
Не стреляйте в пианиста, он играет как умеет...
Re[2]: Определение наличия данных в stdin
От: kong Украина  
Дата: 12.09.02 06:40
Оценка:
Здравствуйте santucco, Вы писали:

S>Здравствуйте kong, Вы писали:


K>>Есть такая проблемка: пишется прога, которая забирает данные по конвееру из сислога. Для этого надо определять есть ли данные в stdin. Если просто опрашивать stdin, то прога сильно грузит процессор. Нужен совет как сделать так, чтобы прога находилась в спящем режиме, а при поступлении данных в stdin — просыпалась.



S>А ты, случаем, daemon из своего процесса не делаешь?


да что-то в этом роде
Re[3]: Определение наличия данных в stdin
От: santucco  
Дата: 12.09.02 06:49
Оценка:
Здравствуйте kong, Вы писали:

K>Здравствуйте santucco, Вы писали:


S>>Здравствуйте kong, Вы писали:


K>>>Есть такая проблемка: пишется прога, которая забирает данные по конвееру из сислога. Для этого надо определять есть ли данные в stdin. Если просто опрашивать stdin, то прога сильно грузит процессор. Нужен совет как сделать так, чтобы прога находилась в спящем режиме, а при поступлении данных в stdin — просыпалась.


K>

S>>А ты, случаем, daemon из своего процесса не делаешь?

K> да что-то в этом роде

Я имею ввиду, код не работает, уже будучи daemon'ом?
Не стреляйте в пианиста, он играет как умеет...
Re[4]: Определение наличия данных в stdin
От: kong Украина  
Дата: 12.09.02 07:00
Оценка:
Здравствуйте santucco, Вы писали:

S>Здравствуйте kong, Вы писали:


K>>Здравствуйте santucco, Вы писали:


S>>>Здравствуйте kong, Вы писали:


K>>>>Есть такая проблемка: пишется прога, которая забирает данные по конвееру из сислога. Для этого надо определять есть ли данные в stdin. Если просто опрашивать stdin, то прога сильно грузит процессор. Нужен совет как сделать так, чтобы прога находилась в спящем режиме, а при поступлении данных в stdin — просыпалась.


K>>

S>>>А ты, случаем, daemon из своего процесса не делаешь?

K>> да что-то в этом роде

S>Я имею ввиду, код не работает, уже будучи daemon'ом?

Я его как демона не запускал.
Вобщем ситуация такая: есть демон, который выводит информацию через сислог. В сислоге по конвееру (*.info | my prog)данные идут моей проге на stdin. Вот в такой последовательности код и не работает (select() считает что в stdin всегда есть данные для чтения)
Re[3]: Определение наличия данных в stdin
От: Anatolix Россия https://www.linkedin.com/in/anatolix/
Дата: 12.09.02 07:12
Оценка:
Здравствуйте kong, Вы писали:

K> Да дело в том что я пишу на чистой сюхе, а вроде cin >> s это уже С++. Данные у меня идут сроками, причем строки не фиксированной длины (от 25 символов и до ...). Для этого я сначала определяю длину строки в stdin (функция

K>pStr_stdin = fgetln(stdin, &SyslogStr_len)), а потом просто копирую ее в свой локальный буфер (указатель pStr_stdin стоит на начале строки). Вот этот метод и грузит проц — проверял.

Читай оттуда просто кусох буфера, cin ничем не отличается от того же getch или scanf,
а и банальный read тебе здесь должен помочь.
Любая проблема дизайна может быть решена введением дополнительного абстрактного слоя, за исключением проблемы слишком большого количества дополнительных абстрактных слоев
Re: Определение наличия данных в stdin
От: Kubyshev Andrey  
Дата: 12.09.02 07:21
Оценка:
Здравствуйте kong

Zabirai dannye cherez funkciyu getline, predvaritelno include <string.h>

eto func sama sdelaet malloc nuzhnoi tebe dlinny, potom ego nado budet free().
Vyglyadit eto tak:

char * s = getline (NULL,0,stdin);
...
free(s);

No esli hochesh imenno s selectom , ne zabud' fcntl(iStdin,F_SETFL,O_NDELAY);
Re[2]: Определение наличия данных в stdin
От: kong Украина  
Дата: 12.09.02 07:59
Оценка:
Здравствуйте Kubyshev Andrey, Вы писали:


KA>Zabirai dannye cherez funkciyu getline, predvaritelno include <string.h>

KA>eto func sama sdelaet malloc nuzhnoi tebe dlinny, potom ego nado budet free().
KA>Vyglyadit eto tak:
KA>char * s = getline (NULL,0,stdin);
KA>...
KA>free(s);
Я пишу под FreeBSD 4.5, там такой функции нет (по крайней мере я не нашел)

KA>No esli hochesh imenno s selectom , ne zabud' fcntl(iStdin,F_SETFL,O_NDELAY);

Я так понял это установка не блокирующего ввода. Выставил функцию перед select(), не помогло селект всеравно выдает что хендл stdin'на готов для чтения, а потоке данных нет
Re[5]: Определение наличия данных в stdin
От: santucco  
Дата: 12.09.02 09:15
Оценка:
Здравствуйте kong, Вы писали:

K>Здравствуйте santucco, Вы писали:


S>>Здравствуйте kong, Вы писали:


K>>>Здравствуйте santucco, Вы писали:


S>>>>Здравствуйте kong, Вы писали:


K>>>>>Есть такая проблемка: пишется прога, которая забирает данные по конвееру из сислога. Для этого надо определять есть ли данные в stdin. Если просто опрашивать stdin, то прога сильно грузит процессор. Нужен совет как сделать так, чтобы прога находилась в спящем режиме, а при поступлении данных в stdin — просыпалась.


K>>>

S>>>>А ты, случаем, daemon из своего процесса не делаешь?

K>>> да что-то в этом роде

S>>Я имею ввиду, код не работает, уже будучи daemon'ом?

K>Я его как демона не запускал.

K>Вобщем ситуация такая: есть демон, который выводит информацию через сислог. В сислоге по конвееру (*.info | my prog)данные идут моей проге на stdin. Вот в такой последовательности код и не работает (select() считает что в stdin всегда есть данные для чтения)
Сам по себе код рабочий — у меня под Linux'ом работает и во FreeBSD должен работать. Проблема явно с syslog'ом.
Попробуй блокирующий read и иной механизм выцарапывания строк
Не стреляйте в пианиста, он играет как умеет...
Re[6]: Определение наличия данных в stdin
От: kong Украина  
Дата: 12.09.02 09:26
Оценка:
Здравствуйте santucco, Вы писали:


S>Сам по себе код рабочий — у меня под Linux'ом работает и во FreeBSD должен работать. Проблема явно с syslog'ом.

S>Попробуй блокирующий read и иной механизм выцарапывания строк
Я пробывал забирать строки фиксированной длины через fgets(), получается такая же ситуация. Т.е. select() даже при пустом stdin говорит, что дескриптор готов к чтению. Также я пробывал, просто на вход проги подавать данные через команду cat (cat file | program), такая же ситуация. Если гне трудно кинь кусок своего кода.
Re[7]: Определение наличия данных в stdin
От: santucco  
Дата: 12.09.02 09:57
Оценка:
Здравствуйте kong, Вы писали:

K>Здравствуйте santucco, Вы писали:


K>

S>>Сам по себе код рабочий — у меня под Linux'ом работает и во FreeBSD должен работать. Проблема явно с syslog'ом.
S>>Попробуй блокирующий read и иной механизм выцарапывания строк
K> Я пробывал забирать строки фиксированной длины через fgets(), получается такая же ситуация. Т.е. select() даже при пустом stdin говорит, что дескриптор готов к чтению. Также я пробывал, просто на вход проги подавать данные через команду cat (cat file | program), такая же ситуация. Если гне трудно кинь кусок своего кода.
Это твой код, я только чтение и распечатку вставил (сделано на скорую руку, поэтому сделано неправильно )
Specially for you на чистом С.
Вариант cat file | program у меня работает...
  int iRes_stdin, iStdin;
  struct timeval timeout;
  char Buffer [100];
  fd_set readfd;
  //definition of presence of the data in stdin
  iStdin=fileno(stdin);  
//  cout << iStdin << endl;
  FD_ZERO(&readfd);
  FD_SET(iStdin, &readfd);
  timeout.tv_sec = 5;
  timeout.tv_usec = 0;
  memset ( Buffer, 0, sizeof ( Buffer ) );
   
  iRes_stdin = select(iStdin + 1, &readfd, NULL, NULL, &timeout);
  if (iRes_stdin > 0 )
  {
    if ( FD_ISSET ( iStdin, &readfd) ) {
      gets ( Buffer );
      puts ( Buffer );
    }   
  }
  else {
    return -1;
  }
Не стреляйте в пианиста, он играет как умеет...
Re[8]: Определение наличия данных в stdin
От: kong Украина  
Дата: 12.09.02 10:20
Оценка:
Здравствуйте santucco, Вы писали:

S>Здравствуйте kong, Вы писали:


K>>Здравствуйте santucco, Вы писали:


S>Это твой код, я только чтение и распечатку вставил (сделано на скорую руку, поэтому сделано неправильно )

S>Specially for you на чистом С.
S>Вариант cat file | program у меня работает...
В смысле ты читаешь по циклу все строки file, а после конца файла select() перестает выдавть готовность дескриптора stdin к чтению? Я тоже попробывал это кусок кода, но у меня после конца файла select() по прежнему считает что есть данные.
Re[9]: Определение наличия данных в stdin
От: santucco  
Дата: 12.09.02 10:50
Оценка:
Здравствуйте kong, Вы писали:

K>Здравствуйте santucco, Вы писали:


S>>Здравствуйте kong, Вы писали:


K>>>Здравствуйте santucco, Вы писали:


S>>Это твой код, я только чтение и распечатку вставил (сделано на скорую руку, поэтому сделано неправильно )

S>>Specially for you на чистом С.
S>>Вариант cat file | program у меня работает...
K> В смысле ты читаешь по циклу все строки file, а после конца файла select() перестает выдавть готовность дескриптора stdin к чтению? Я тоже попробывал это кусок кода, но у меня после конца файла select() по прежнему считает что есть данные.

Слушай, действительно, у меня тоже select показывает, что данные есть. Они там действительно есть — это признак конца файла . В данном случае select не подходит.

Остается следующее

#include <string.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>

int main ()
{
  int iStdin, iStdout;
  char Buffer [100];
  int res = 0;
  iStdin=fileno(stdin); 
  iStdout=fileno(stdout); 
  memset ( Buffer, 0, sizeof ( Buffer ) );
  while ( 1 ) {
    res = read ( iStdin, Buffer, sizeof ( Buffer ) );
    if ( !res )
      sleep ( 3 );
    write ( iStdout, Buffer, res  );
  }
}
Не стреляйте в пианиста, он играет как умеет...
Re[10]: Определение наличия данных в stdin
От: kong Украина  
Дата: 12.09.02 10:59
Оценка:
Здравствуйте santucco, Вы писали:

S>Слушай, действительно, у меня тоже select показывает, что данные есть. Они там действительно есть — это признак конца файла . В данном случае select не подходит.


S>Остается следующее


S> while ( 1 ) {

S> res = read ( iStdin, Buffer, sizeof ( Buffer ) );
S> if ( !res )
S> sleep ( 3 );
S> write ( iStdout, Buffer, res );
S> }

Да так можно, но шефу не нравиться — говорит так не правильно (да и буфер может переполняться — частота посылки данных моей проге может быть очень большой).
Re[11]: Определение наличия данных в stdin
От: santucco  
Дата: 12.09.02 11:30
Оценка:
Здравствуйте kong, Вы писали:

K>Здравствуйте santucco, Вы писали:


S>>Слушай, действительно, у меня тоже select показывает, что данные есть. Они там действительно есть — это признак конца файла . В данном случае select не подходит.


S>>Остается следующее


S>> while ( 1 ) {

S>> res = read ( iStdin, Buffer, sizeof ( Buffer ) );
S>> if ( !res )
S>> sleep ( 3 );
S>> write ( iStdout, Buffer, res );
S>> }

K>Да так можно, но шефу не нравиться — говорит так не правильно (да и буфер может переполняться — частота посылки данных моей проге может быть очень большой).

На самом деле я не вижу другого способа — данные в stdin будут постоянно (тот же конец файла).
Буфер переполнятся не будет по той простой причине, что ты больше размера буфера из дескриптора не читаешь (sizeof ( Buffer ) ), хотя буфер лучше свсе-таки делать динамическим и побольше (это был только пример).

А насчет шефа — пусть предложит лучший способ в свете всего вышеописанного )) (без обид, OK ?)
Не стреляйте в пианиста, он играет как умеет...
Re[12]: Определение наличия данных в stdin
От: kong Украина  
Дата: 12.09.02 11:41
Оценка:
Здравствуйте santucco, Вы писали:


K>>Да так можно, но шефу не нравиться — говорит так не правильно (да и буфер может переполняться — частота посылки данных моей проге может быть очень большой).

S>На самом деле я не вижу другого способа — данные в stdin будут постоянно (тот же конец файла).
S>Буфер переполнятся не будет по той простой причине, что ты больше размера буфера из дескриптора не читаешь (sizeof ( Buffer ) ), хотя буфер лучше свсе-таки делать динамическим и побольше (это был только пример).

Я имел ввиду буфер в потоке. А вот на счет другого способа, он мне его искать поручил (вариан с синхронизацией процессов через семафор ему тоже не понравился).
Re[13]: Определение наличия данных в stdin
От: santucco  
Дата: 12.09.02 12:10
Оценка:
Здравствуйте kong, Вы писали:

K>Здравствуйте santucco, Вы писали:


K>

K>>>Да так можно, но шефу не нравиться — говорит так не правильно (да и буфер может переполняться — частота посылки данных моей проге может быть очень большой).
S>>На самом деле я не вижу другого способа — данные в stdin будут постоянно (тот же конец файла).
S>>Буфер переполнятся не будет по той простой причине, что ты больше размера буфера из дескриптора не читаешь (sizeof ( Buffer ) ), хотя буфер лучше свсе-таки делать динамическим и побольше (это был только пример).

K>Я имел ввиду буфер в потоке. А вот на счет другого способа, он мне его искать поручил (вариан с синхронизацией процессов через семафор ему тоже не понравился).

А что надо сделать-то?
Не стреляйте в пианиста, он играет как умеет...
Re[14]: Определение наличия данных в stdin
От: kong Украина  
Дата: 12.09.02 12:21
Оценка:
Здравствуйте santucco, Вы писали:

K>>Я имел ввиду буфер в потоке. А вот на счет другого способа, он мне его искать поручил (вариан с синхронизацией процессов через семафор ему тоже не понравился).

S>А что надо сделать-то?

да вот такая схема: есть демон, который через сислог по конвееру передает данные моей программе на stdin. Мне их надо оттуда забирать и писать в базу. Если постоянно по циклу проверять stdin на наличие данных, то сильно грузиться процессор. Вот и надо сделать, чтобы прога просыпалась только когда есть данныее в stdin. Я предложил вариант сделать синронизацию с демоном через семафор, но шефу не понравилось и он меня навел на идею с select(). Я с ним сам вчера целый день промучился, вот сегодня решил в форум месагу кинуть.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.