Как получить пользовательские данные для обработчика сигналов 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_ * - тупик для моего варианта использования?


person villintehaspam    schedule 25.02.2011    source источник


Ответы (1)


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

person Arvid    schedule 15.03.2011
comment
Спасибо за указатель, я ошибочно подумал, что только конкретные RT-сигналы, где часть сигналов реального времени штука, а не возможность отправлять пользовательские данные обработчикам. Как вы отметили, единственный вариант - просмотреть операции и проверить, выполнены ли они. Вместе с требованием, чтобы обработчики сигналов были асинхронно безопасными для сигналов, решение становится настолько громоздким и неинтуитивным, что, по крайней мере, для моего варианта использования намного проще просто запускать все операции io в отдельном потоке. - person villintehaspam; 15.03.2011