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