#c #stream #timeout #libc
#c #поток #тайм-аут #libc
Вопрос:
Я создаю коммуникационную библиотеку, которая принимает поток файлов и использует его для чтения и записи. Протокол определяет тайм-ауты, поэтому я хочу их использовать.
Я использую fread(3)
и fwrite(3)
. Я слышал о select(2)
, и это то, что я ищу, за исключением того, что он использует файловые дескрипторы, а не файловые потоки libc — я хочу поддерживать пользовательские файловые потоки, созданные с fopencookie(3)
помощью, полезные для тестов и других вещей, тоже. Я попытался настроить SIGALRM
с alarm(2)
помощью, чтобы получить сообщение об EINTR
ошибке fread(3)
(настройка обратного вызова для SIGALRM
использования signal(2)
), но это не остановит fopen
вызов, как ожидалось…
Заранее спасибо за любое решение.
РЕДАКТИРОВАТЬ: похоже, это работает.. но только один раз. При втором вызове это не … Oo
/**
* sigalrm_handler:
* Shut up SIGALRM.
*
* @arg code signal code (always SIGALRM)
*/
static __thread jmp_buf env_alrm;
static void sigalrm_handler(int signo)
{
(void)signo;
/* restore env */
longjmp(env_alrm, 5);
}
/**
* _p7_fread:
* Read file with timeout.
*
* @arg ptr the buffer pointer
* @arg size the size of an item
* @arg nitems the number of items in the buffer
* @arg stream the stream
* @arg timeout the timeout (seconds)
* @return the number of read bytes
*/
size_t _p7_fread(void *ptr, size_t size, size_t nitems, FILE *stream,
int timeout)
{
size_t read_count = 0;
/* set long jump */
int val = setjmp(env_alrm);
if (!val) {
/* setup signal handler */
if (signal(SIGALRM, amp;sigalrm_handler) == SIG_ERR)
return (0);
/* setup alarm */
alarm(timeout);
/* read */
read_count = fread(ptr, size, nitems, stream);
} else
errno = EINTR;
/* unset signal handler and alarm */
signal(SIGALRM, NULL);
alarm(0);
/* return */
return (read_count);
}
Еще раз, спасибо за любую помощь ^^
Ответ №1:
функция: fdopen()
получит указатели на файлы из файловых дескрипторов.
Затем вы можете использовать функцию: select()
с указателями файлов, которые были возвращены из fdopen()
.
Комментарии:
1. Но как насчет внутренних буферов в структуре FILE * ? А как насчет файловых потоков, у которых нет файлового дескриптора (я имею в виду созданные с
fopencookie
помощью)?2. это из: <> «Функция fdopen() связывает поток с существующим файловым дескриптором fd. Режим потока (одно из значений «r», «r «, «w», «w «, «a», «a «) должен быть совместим с режимом файлового дескриптора. Для индикатора положения файла нового потока устанавливается значение, принадлежащее fd, а индикаторы ошибки и конца файла очищаются. Режимы «w» или «w » не вызывают усечения файла. Файловый дескриптор не дублируется и будет закрыт, когда поток, созданный fdopen(), будет закрыт. Результат применения fdopen() к объекту с общей памятью не определен «.
3. Итак, я попробовал
select
иfileno
. Но фактfileno
в том, что возвращает -1 для пользовательского потока, созданного сfopencookie
помощью, поэтому я не могу использоватьselect
его. И если я хочу протестировать тайм-ауты с помощью пользовательских файловых потоков… так что это не сработает для меня. :/4. @Cakeisalie5, чего именно ты пытаешься достичь? Понимаете ли вы, что «cookie» — это объект памяти, а не реальный поток ввода-вывода, поэтому какая-то внешняя сила, изменяющая эту память, не вызовет событие, которое будет распознано, например
select()
?5. Я понял это, я использую пользовательские потоки файлов для тестирования. Но именно поэтому я не могу использовать
select
для своего случая (поскольку я также хочу проверять тайм-ауты в пользовательских файловых потоках)… итак, я ищу более общий способ сделатьfopen
/fwrite
timeout (/causeEINTR
, который я не нашел, как вызвать даже сalarm
).