открытый системный вызов на fifo не блокируется? - PullRequest
1 голос
/ 12 сентября 2011

Я создаю довольно большой проект как домашнее задание, где мне нужно создать серверную программу, которая слушает 2 фута, где клиенты будут писать.

Все работает, но есть кое-что, что меня злит: всякий раз, когда я делаю операцию, которая состоит из некоторой записи / чтения между клиентом и сервером, когда я закрываю fifos на клиенте, это выглядит как сервер "думает", что есть еще кто-то, кто держит эти пятерки открытыми

Из-за этого сервер пытается прочитать 64 байта после каждой операции, очевидно, что происходит сбой (чтение 0 байтов). Это происходит только один раз за операцию, она не пытается прочитать 64 байта

Это не создает никаких проблем для клиентов, но это действительно странно, и я ненавижу подобные ошибки

Я думаю, что это проблема, связанная с открытием / закрытием и с тем фактом, что клиенты используют блокировку.

Обратите внимание, что флаги, используемые в операции открытия, указаны в этом тексте псевдокода

Поведение сервера:

Open Fifo(1) for READING (O_RDONLY)
Open Fifo(2) for WRITING (O_WRONLY)
Do some operations
Close Fifo(1)
Close Fifo(2)

Поведение клиента:

Set a lock on Fifo(1) (waiting if there is already one)
Set a lock on Fifo(2) (same as before)
Open Fifo(1) for WRITING (O_WRONLY)
Open Fifo(2) for READING (O_RDONLY)
Do some operations
Close Fifo(1)
Close Fifo(2)
Get lock from Fifo(1)
Get lock from Fifo(2)

Я не могу публиковать код напрямую, кроме функций, используемых для работы в сети, потому что проект довольно большой, и я не использую системные вызовы напрямую. Вот вы:

int Network_Open(const char* path,int oflag)
{
    return open(path,oflag);
}

ssize_t Network_IO(int fifo,NetworkOpCodes opcode,void* data,size_t dataSize)
{
    ssize_t retsize = 0;
    errno = 0;

    if (dataSize == 0) return 0;

    while ((retsize = (opcode == NetworkOpCode_Write? write(fifo,data,dataSize) : read(fifo,data,dataSize))) < 0)
    {
        if (errno != EINTR) break;
    }

    return retsize;
}

Boolean Network_Send(int fifo,const void* data,size_t dataSize)
{
    return ((ssize_t)dataSize) == Network_IO(fifo,NetworkOpCode_Write,(void*)data,dataSize);
}

Boolean Network_Receive(int fifo,void* data,size_t dataSize)
{
    return ((ssize_t)dataSize) == Network_IO(fifo,NetworkOpCode_Read,data,dataSize);
}

Boolean Network_Close(int fifo)
{
    if (fifo >= 0)
        return close(fifo) == 0;
}

Любая помощь будет оценена, спасибо.

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

Выход клиента: http://pastie.org/2523854 Выход сервера (strace): http://pastie.org/2523858

Ответы [ 2 ]

3 голосов
/ 13 сентября 2011

Нулевые байты, возвращаемые (блокирующими) read (), указывают конец файла, то есть, что другой конец закрыл FIFO.Прочитайте man-страницу для чтения.

2 голосов
/ 13 сентября 2011

Результат нулевых байтов от read() означает, что другой процесс завершен. Теперь ваш сервер должен закрыть исходный дескриптор файла и снова открыть FIFO для обслуживания следующего клиента. Операции блокировки возобновятся, как только вы начнете работать с новым файловым дескриптором.

Так и должно быть.

AFAIK, после того, как вы получите нулевые байты, дальнейшие попытки чтения по файловому дескриптору также будут возвращать 0 байтов, вечно (или до тех пор, пока вы не закроете файловый дескриптор). Даже если другой процесс открывает FIFO, исходный файловый дескриптор будет продолжать указывать EOF (другой клиентский процесс будет зависать, ожидая, пока процесс сервера откроет FIFO для чтения).

...