Как получить пользовательские данные для обработчика сигнала aio в Mac OS X

Я пытаюсь использовать функции aio_* для асинхронного ввода-вывода файлов в Mac OS X, но у меня возникают проблемы с получением той или иной формы пользовательских данных в обработчике сигналов.

Это код, который устанавливает операцию:

class aio_context {
public:
    aio_context(int fildes, boost::uint64_t offset,
        const MyBufferClassPtr &buffer)
    {
        // The aiocb struct must be zeroed
        memset(&m_aiocb, 0, sizeof(struct aiocb));

        // Set what to do
        m_aiocb.aio_fildes = fildes;
        m_aiocb.aio_buf = buffer->data();
        m_aiocb.aio_nbytes = buffer->size();
        m_aiocb.aio_offset = offset;

        // Set notification
        m_aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
        m_aiocb.aio_sigevent.sigev_signo = SIGUSR1;

        // ATTEMPT TO SET A VALUE THAT CAN BE READ IN THE HANDLER
        m_aiocb.aio_sigevent.sigev_value.sival_ptr = this;
    }

    struct aiocb* GetAiocbp()
    {
        return &m_aiocb;
    }

private:
    struct aiocb m_aiocb;
    // Some more context here
};

Затем это вызывается откуда-то еще, как это:

aio_context *ctx = new aio_context(file_descriptor, offset, data);
// set some more context here
int ret = aio_write(ctx->GetAiocbp());
if (0 != ret) {
    // throw something
}

Моя настройка обработки сигналов выглядит следующим образом:

sigemptyset(&m_CurrentSIGHandler.sa_mask);
m_CurrentSIGHandler.sa_sigaction = aio_completion_handler;
m_CurrentSIGHandler.sa_flags = SA_SIGINFO;
sigaction(SIGUSR1, &m_CurrentSIGHandler, &m_PreviousSIGHandler);

и фактический обработчик, как это:

void aio_completion_handler(int signo, siginfo_t *info, void *context)
{
    if (info->si_signo == SIGUSR1) {
        // Get the aio operation
        aio_context *ctx = static_cast<aio_context *>(info->si_value.sival_ptr);

        // THIS ASSERT ALWAYS FAILS - ctx IS NULL
        assert(ctx);

        // next check aio_error and aio_return using the aicb member of the ctx
        // ...
    }
}

Так что проблема в том, что si_value.sival_ptr всегда равен NULL в обработчике сигналов, а не является указателем aio_context, который я установил в структуре aiocb. Должно быть, я что-то не так понял, как это сделать, поэтому кто-нибудь может сказать мне, что я делаю неправильно?

Я работаю на MacOSX 10.6, но я (по крайней мере, пытаюсь) компилировать для 10.5, если это имеет значение.

Кроме того, ответ на этот вопрос, похоже, указывает на то, что AIO следует полностью игнорировать - так ли это на самом деле?

Обновить:

Я нашел кого-то еще с такой же проблемой на http://lists.apple.com/archives/darwin-dev/2008/Oct/msg00054.html.

Я также рассмотрел код ядра по адресу http://www.opensource.apple.com/source/xnu/xnu-1504.9.26/bsd/kern/kern_aio.c и, если я правильно понял, sigev_value действительно полностью игнорируется. Я действительно в недоумении от того, что ожидаемое использование функций aio_* на Mac OS X. Это не тот случай, когда их можно использовать вышеописанным способом в любом случае. Я что-то неправильно понял или функции aio_* тупик для моего варианта использования?

1 ответ

Решение

Mac OS X не поддерживает сигналы реального времени ([RTS] в спецификации posix), это раздел POSIX, который добавляет указатели пользовательских данных к сигналам. Это делает Mac OS X очень сложным для эффективного использования с AIO. Единственный вариант - пройтись по всем выдающимся работам и справиться с теми, которые уже выполнены.

Другие вопросы по тегам