С помощью выбора и чтения из трубы - PullRequest
2 голосов
/ 17 октября 2011

У меня есть программа, над которой я работаю, и я использую select для выбора из каналов для чтения.

Проблема в том, что я использую if(FD_ISSET(pfd[i][0], &read_set)), и она не проходит проверку, потому чтоFD_ISSET возвращает 0, но если я попытаюсь прочитать, используя read(pfd[i][0],&c,sizeof(c)), он будет работать нормально, и содержимое из pipe pfd [0] будет отличаться от pfd [1], как я хочу.

Я хочу знать, чтоад продолжается, потому что FD_ISSET возвращает 0, но я могу фактически прочитать содержимое из него

РЕДАКТИРОВАТЬ

Глобальная переменная CORES будет контролировать, сколько процессов я создаю Следующий кодсоздаст каналы и использует FD_SET для установки битов

for(i=0; i<CORES; i++)
{
    if(pipe(pfd[i])==-1)
        perror("Ocorreu um erro a criar um pipe");

    FD_SET(pfd[i][0], &read_set);
}

read_set определяется сразу после запуска main ().Я использую for () сразу после вышеприведенного кода для создания x процессов, используя fork () (x = CORES)

, затем эта часть выполняется в родительском процессе:

    while (x<CORES){
    int selec = select(pfd[CORES-1][0]+1, &read_set, NULL, NULL, NULL);

    if(selec>0)
    {
        if(FD_ISSET(pfd[x][0], &read_set))
        {
            close(pfd[x][1]);

            if(read(pfd[x][0],&c,sizeof(c))==-1)
                perror("Ocorreu um erro a ler do pipe");

            printf("c= %f \n",c);
            c_final+=c;
            x++;
        }
        else
            printf("\nFile descriptor pfd[%d][0] is not set\n",x);

    }
    else if(selec == -1)
        perror("Ocorreu um erro no select");
}

проблема с этимявляется то, что FD_ISSET(pfd[x][0], &read_set) не пройдет, потому что он не установлен для pfd [0], но это может быть для pfd [1] или наоборот (потому что я не знаю, будет ли сбой для 0 или 1)

EDIT2:

select () возвращает int для числа дескрипторов файлов в read_set.У меня CORES установлен на 2, поэтому он создает 2 процесса и 2 канала и устанавливает 2 бита в read_set.Мой метод select () возвращает int 1. Должен ли он также возвращать значения int 2 или 0 (то есть 0 и 1 = 2)?

Ответы [ 2 ]

5 голосов
/ 17 октября 2011

Первый аргумент select должен быть 1+max_fd.Хотя вероятно, что pfd[CORES-1][0] является наибольшим, это не гарантируется.Вы можете вычислить наибольший дескриптор файла при заполнении read_set и использовать его для своего select вызова.

Кроме того, вам необходимо повторно заполнить read_set перед вызовом selectкаждый раз.Так что цикл for вне цикла while должен войти. На самом деле, лучше переместить выделение снаружи и заключить блок, начиная с цикла for, устанавливая read_set и заканчивая после цикла while в другом цикле - такчто при каждом возврате выбора вы обрабатываете все сигнализированные дескрипторы, не входя в повторное выделение.


РЕДАКТИРОВАТЬ: Чтобы уточнить, что я имел в виду в отношении циклов: вы должны проверять все дескрипторы каждый раз, когда возвращается select.Но вы не можете позвонить, чтобы выбрать только один раз, так как нет никаких гарантий, что все ответы будут готовы сразу.Итак, вы делаете что-то вроде:

for (i=0; i != CORES; ++i)
{
  // Call pipe() and populate pfd[i]
}

while (!finished) // Need a proper condition to terminate this loop
{
    // Setup read_set
    FD_ZERO(&read_set);
    for (i=0; i != CORES; ++i)
    {
        FD_SET(pfd[i][0], &read_set);
        // find max_fd here
    }
    // select here
    if (select(max_fd+1, blahblah) > 0)
    {
        for (i=0; i != CORES; ++i) // This used to be while(x < CORES). But a for loop would do
        {
            // Check the fd, and process
        }
    }
    else
    {
         // error in select
    }
}
1 голос
/ 17 октября 2011

Я бы предложил в этом сценарии со всеми этими различными файловыми дескрипторами, с которых вы пытаетесь читать, и проверять наличие неблокирующих записей (т. Е. Кажется, что вы пытаетесь проверить, есть ли конец канал активен), что вы используете poll() вместо select(), если только по какой-то причине вы не должны использовать select(). С помощью poll вы можете просто настроить все свои файловые дескрипторы в массиве struct pollfd и указать им события, которые вы хотите проверить. Затем результаты poll() после его возвращения сообщат вам, сколько из ваших файловых дескрипторов имеют события. Я думаю, что с этим подходом вам будет намного легче справляться с тем, что у вас здесь есть. Например, вы можете сделать что-то вроде следующего:

struct pollfds descriptors[CORES * 2] = {0};

for(int i=0; i<CORES; i++)
{
    if(pipe(pfd[i])==-1)
        perror("Ocorreu um erro a criar um pipe");

    //wait for either a read on pipe[0] or a non-blocking write on pipe[1]
    descriptors[i*2].fd = pfd[i][0];
    descriptors[i*2].events = POLLIN;
    descriptors[(i*2)+1].fd = pdf[i][1];
    descriptors[(i*2)+2].events = POLLOUT;
}

while (x < CORES)
{
    int num_events = poll(descriptors, CORES * 2, -1); //infinite timeout period

    //...check your descriptors array for events
}
...