Есть такая проблемка: пишется прога, которая забирает данные по конвееру из сислога. Для этого надо определять есть ли данные в 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 готов для чтения — даже когда в потоке нет данных. В чем ошибка?
Здравствуйте kong, Вы писали:
K>Есть такая проблемка: пишется прога, которая забирает данные по конвееру из сислога. Для этого надо определять есть ли данные в stdin. Если просто опрашивать stdin, то прога сильно грузит процессор. Нужен совет как сделать так, чтобы прога находилась в спящем режиме, а при поступлении данных в stdin — просыпалась.
А помоему тебе надо просто читать из stdin и когда в нем не будет данных
твою прогу забликируют до их поступления
т.е. когда ты делаешь cin >> s; прога ведь ждет пока ты что-то наберешь
Любая проблема дизайна может быть решена введением дополнительного абстрактного слоя, за исключением проблемы слишком большого количества дополнительных абстрактных слоев
Здравствуйте 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 стоит на начале строки). Вот этот метод и грузит проц — проверял.
Здравствуйте 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 из своего процесса не делаешь?
Здравствуйте santucco, Вы писали:
S>Здравствуйте kong, Вы писали:
K>>Есть такая проблемка: пишется прога, которая забирает данные по конвееру из сислога. Для этого надо определять есть ли данные в stdin. Если просто опрашивать stdin, то прога сильно грузит процессор. Нужен совет как сделать так, чтобы прога находилась в спящем режиме, а при поступлении данных в stdin — просыпалась.
S>А ты, случаем, daemon из своего процесса не делаешь?
Здравствуйте kong, Вы писали:
K>Здравствуйте santucco, Вы писали:
S>>Здравствуйте kong, Вы писали:
K>>>Есть такая проблемка: пишется прога, которая забирает данные по конвееру из сислога. Для этого надо определять есть ли данные в stdin. Если просто опрашивать stdin, то прога сильно грузит процессор. Нужен совет как сделать так, чтобы прога находилась в спящем режиме, а при поступлении данных в stdin — просыпалась.
K> S>>А ты, случаем, daemon из своего процесса не делаешь?
K> да что-то в этом роде
Я имею ввиду, код не работает, уже будучи daemon'ом?
Здравствуйте santucco, Вы писали:
S>Здравствуйте kong, Вы писали:
K>>Здравствуйте santucco, Вы писали:
S>>>Здравствуйте kong, Вы писали:
K>>>>Есть такая проблемка: пишется прога, которая забирает данные по конвееру из сислога. Для этого надо определять есть ли данные в stdin. Если просто опрашивать stdin, то прога сильно грузит процессор. Нужен совет как сделать так, чтобы прога находилась в спящем режиме, а при поступлении данных в stdin — просыпалась.
K>> S>>>А ты, случаем, daemon из своего процесса не делаешь?
K>> да что-то в этом роде S>Я имею ввиду, код не работает, уже будучи daemon'ом?
Я его как демона не запускал.
Вобщем ситуация такая: есть демон, который выводит информацию через сислог. В сислоге по конвееру (*.info | my prog)данные идут моей проге на stdin. Вот в такой последовательности код и не работает (select() считает что в stdin всегда есть данные для чтения)
Здравствуйте kong, Вы писали:
K> Да дело в том что я пишу на чистой сюхе, а вроде cin >> s это уже С++. Данные у меня идут сроками, причем строки не фиксированной длины (от 25 символов и до ...). Для этого я сначала определяю длину строки в stdin (функция K>pStr_stdin = fgetln(stdin, &SyslogStr_len)), а потом просто копирую ее в свой локальный буфер (указатель pStr_stdin стоит на начале строки). Вот этот метод и грузит проц — проверял.
Читай оттуда просто кусох буфера, cin ничем не отличается от того же getch или scanf,
а и банальный read тебе здесь должен помочь.
Любая проблема дизайна может быть решена введением дополнительного абстрактного слоя, за исключением проблемы слишком большого количества дополнительных абстрактных слоев
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'на готов для чтения, а потоке данных нет
Здравствуйте 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 и иной механизм выцарапывания строк
S>Сам по себе код рабочий — у меня под Linux'ом работает и во FreeBSD должен работать. Проблема явно с syslog'ом. S>Попробуй блокирующий read и иной механизм выцарапывания строк
Я пробывал забирать строки фиксированной длины через fgets(), получается такая же ситуация. Т.е. select() даже при пустом stdin говорит, что дескриптор готов к чтению. Также я пробывал, просто на вход проги подавать данные через команду cat (cat file | program), такая же ситуация. Если гне трудно кинь кусок своего кода.
Здравствуйте kong, Вы писали:
K>Здравствуйте santucco, Вы писали:
K> S>>Сам по себе код рабочий — у меня под Linux'ом работает и во FreeBSD должен работать. Проблема явно с syslog'ом. S>>Попробуй блокирующий read и иной механизм выцарапывания строк K> Я пробывал забирать строки фиксированной длины через fgets(), получается такая же ситуация. Т.е. select() даже при пустом stdin говорит, что дескриптор готов к чтению. Также я пробывал, просто на вход проги подавать данные через команду cat (cat file | program), такая же ситуация. Если гне трудно кинь кусок своего кода.
Это твой код, я только чтение и распечатку вставил (сделано на скорую руку, поэтому сделано неправильно )
Specially for you на чистом С.
Вариант cat file | program у меня работает...
Здравствуйте santucco, Вы писали:
S>Здравствуйте kong, Вы писали:
K>>Здравствуйте santucco, Вы писали:
S>Это твой код, я только чтение и распечатку вставил (сделано на скорую руку, поэтому сделано неправильно ) S>Specially for you на чистом С. S>Вариант cat file | program у меня работает...
В смысле ты читаешь по циклу все строки file, а после конца файла select() перестает выдавть готовность дескриптора stdin к чтению? Я тоже попробывал это кусок кода, но у меня после конца файла select() по прежнему считает что есть данные.
Здравствуйте 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 );
}
}
Здравствуйте 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> }
Да так можно, но шефу не нравиться — говорит так не правильно (да и буфер может переполняться — частота посылки данных моей проге может быть очень большой).
Здравствуйте 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 ?)
K>>Да так можно, но шефу не нравиться — говорит так не правильно (да и буфер может переполняться — частота посылки данных моей проге может быть очень большой). S>На самом деле я не вижу другого способа — данные в stdin будут постоянно (тот же конец файла). S>Буфер переполнятся не будет по той простой причине, что ты больше размера буфера из дескриптора не читаешь (sizeof ( Buffer ) ), хотя буфер лучше свсе-таки делать динамическим и побольше (это был только пример).
Я имел ввиду буфер в потоке. А вот на счет другого способа, он мне его искать поручил (вариан с синхронизацией процессов через семафор ему тоже не понравился).
Здравствуйте kong, Вы писали:
K>Здравствуйте santucco, Вы писали:
K> K>>>Да так можно, но шефу не нравиться — говорит так не правильно (да и буфер может переполняться — частота посылки данных моей проге может быть очень большой). S>>На самом деле я не вижу другого способа — данные в stdin будут постоянно (тот же конец файла). S>>Буфер переполнятся не будет по той простой причине, что ты больше размера буфера из дескриптора не читаешь (sizeof ( Buffer ) ), хотя буфер лучше свсе-таки делать динамическим и побольше (это был только пример).
K>Я имел ввиду буфер в потоке. А вот на счет другого способа, он мне его искать поручил (вариан с синхронизацией процессов через семафор ему тоже не понравился).
А что надо сделать-то?
Здравствуйте santucco, Вы писали:
K>>Я имел ввиду буфер в потоке. А вот на счет другого способа, он мне его искать поручил (вариан с синхронизацией процессов через семафор ему тоже не понравился). S>А что надо сделать-то?
да вот такая схема: есть демон, который через сислог по конвееру передает данные моей программе на stdin. Мне их надо оттуда забирать и писать в базу. Если постоянно по циклу проверять stdin на наличие данных, то сильно грузиться процессор. Вот и надо сделать, чтобы прога просыпалась только когда есть данныее в stdin. Я предложил вариант сделать синронизацию с демоном через семафор, но шефу не понравилось и он меня навел на идею с select(). Я с ним сам вчера целый день промучился, вот сегодня решил в форум месагу кинуть.