select не сохраняет файловые дескрипторы

Вчера я обнаружил select, очень полезный инструмент, но я не могу заставить его работать. Это часть моего общего кода:

/* Code here */
FD_ZERO(&fifo_set);
printf("%d\n", num_proc);
for(i = 0; i < num_proc; ++i)
    FD_SET(proc[i].fifowfd, &fifo_set);

/* More code here */
while(1)
{
    if(select(FD_SETSIZE, &fifo_set, NULL, NULL, NULL) < 0)
    {
        log_event(5, "Could not block.");
        exit(1);
    }
    printf("FD_SETSIZE: %d\n", FD_SETSIZE);
    for(i = 0; i < FD_SETSIZE; ++i)
        printf("ISSET %d: %d\n", i, FD_ISSET(i,&fifo_set));

    log_event(1, "Actions to be done.");
/* More code */

Массив proc представляет собой массив процессов с заданным PID и FIFO для чтения и записи. Дескрипторы файлов в FIFO проверены и действительны. Проблема в том, что есть 3 процесса (num_proc) со значениями fifowfd 5, 7 и 9. Но когда я печатаю все FD_ISSET, кажется, что только 5 зарегистрированы и имеют данные, но все три имеют данные. FD_SETSIZE имеет значение 1024.

Как указал @mux, эти FIFO называются «FIFO для записи». Дело в том, что у меня есть куча "name.r.fifo" и "name.w.fifo", которые представляют собой "FIFO для чтения/записи" со стороны процесса. Код, который я показываю, — это код контроллера, который читает в «.w.fifo» и записывает в «.r.fifo».

Я что-то упускаю?


person markmb    schedule 11.08.2013    source источник


Ответы (2)


Первый аргумент select() — это файловый дескриптор с наибольшим номером плюс 1:

select(highest_fd+1, &fifo_set, NULL, NULL, NULL);

Примечание: набор fd будет содержать дескрипторы, которые «готовы» после возврата из select, вам следует снова установить fds, если вы хотите сделать еще один select()

person iabdalkader    schedule 11.08.2013
comment
Плохое объяснение: для каждого процесса есть FIFO с именами name.r.fifo и name.w.fifo, используемые для чтения и записи со стороны процесса. Этот код, который я показываю, является контроллером, который читает то, что пишет процесс. - person markmb; 11.08.2013
comment
@markmb о, понятно .. тогда попробуйте передать самый высокий fd, посмотрите, решит ли это проблему - person iabdalkader; 11.08.2013
comment
@markmb см. мое примечание, вам нужно снова добавлять fds перед каждым вызовом select, потому что после его возврата набор модифицируется, чтобы включить fds, которые изменили свое состояние. - person iabdalkader; 11.08.2013
comment
Извините, я не видел вашей заметки. Это была ошибка. Так как были данные сначала в № 5, а потом в 7 и 9, когда зациклился, посмотрел только на 5. Спасибо большое! Я потерял все утро с этим. - person markmb; 11.08.2013

Если все дескрипторы не имеют данных при вызове select, он будет заблокирован до тех пор, пока хотя бы один дескриптор не будет готов для чтения. Вероятно, дескриптор 5 проверяется первым и выбирает выходы до того, как другие каналы получат какие-либо данные для чтения.

Вы также должны проверить фактический результат выбора, поскольку он содержит количество установленных битов.

person aragaer    schedule 11.08.2013
comment
Я забыл добавить цикл while(1) в этот код. Выбор находится в начале цикла while(1), и когда выбор возвращается, это происходит потому, что есть данные в FIFO номер 5, а не из-за других. - person markmb; 11.08.2013
comment
Кроме того, select всегда возвращает 1 и, как сказано, возвращает только тогда, когда есть данные в числе 5, а не в 7 или 9. - person markmb; 11.08.2013