AIO в OS X против Linux - почему он не работает в Mac OS X 10.6

Мой вопрос действительно прост. Почему приведенный ниже код работает в Linux, а не в Mac OS X 10.6.2 Snow Leopard.

Для компиляции сохраните файл в aio.cc и скомпилируйте с помощью g++ aio.cc -o aio -lrt в Linux и g++ aio.cc -o aio в Mac OS X. Я использую Mac OS X 10.6.2 для тестирования на Mac и ядро ​​Linux 2.6 для тестирования в Linux.

Ошибка, которую я вижу в OS X: aio_write завершается с ошибкой -1 и устанавливает errno на EAGAIN, что просто означает «Ресурс временно недоступен». Почему это так?

extern "C" {
#include <aio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>
#include <signal.h>
}
#include <cassert>
#include <string>
#include <iostream>

using namespace std;

static void
aio_completion_handler(int signo, siginfo_t *info, void *context)
{
  using namespace std;
  cout << "BLAH" << endl;
}


int main()
{
  int err;

  struct sockaddr_in sin;
  memset(&sin, 0, sizeof(sin));

  sin.sin_port = htons(1234);
  sin.sin_addr.s_addr = inet_addr("127.0.0.1");
  sin.sin_family = PF_INET;

  int sd = ::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (sd == -1) {
    assert(!"socket() failed");
  }

  const struct sockaddr *saddr = reinterpret_cast<const struct sockaddr *>(&sin);
  err = ::connect(sd, saddr, sizeof(struct sockaddr));
  if (err == -1) {
    perror(NULL);
    assert(!"connect() failed");
  }

  struct aiocb *aio = new aiocb();
  memset(aio, 0, sizeof(struct aiocb));

  char *buf = new char[3];
  buf[0] = 'a';
  buf[1] = 'b';
  buf[2] = 'c';
  aio->aio_fildes = sd;
  aio->aio_buf = buf;
  aio->aio_nbytes = 3;

  aio->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
  aio->aio_sigevent.sigev_signo = SIGIO;
  aio->aio_sigevent.sigev_value.sival_ptr = &aio;

  struct sigaction sig_act;

  sigemptyset(&sig_act.sa_mask);
  sig_act.sa_flags = SA_SIGINFO;
  sig_act.sa_sigaction = aio_completion_handler;

  sigaction(SIGIO, &sig_act, NULL);

  errno = 0;
  int ret = aio_write(aio);
  if (ret == -1) {
    perror(NULL);
  }  
  assert(ret != -1);  
}

ОБНОВЛЕНИЕ (февраль 2010 г.): OSX вообще не поддерживает AIO для сокетов. Вот досада!

4 голоса | спросил invalidopcode 6 FebruaryEurope/MoscowbSat, 06 Feb 2010 06:52:46 +0300000000amSat, 06 Feb 2010 06:52:46 +030010 2010, 06:52:46

4 ответа


0

Представленный код был протестирован на Mountain Lion 10.8.2. Работает с небольшой коррекцией. Линия
    "aio-> aio_fildes = sd;"

следует изменить, например, на:
     aio-> aio_fildes = open ("/dev /null", O_RDWR);

, чтобы получить ожидаемый результат.

см. руководство. «Функция aio_write () позволяет вызывающему процессу выполнять асинхронную запись в ранее открытый файл.»

ответил Val 28 Jam1000000amMon, 28 Jan 2013 07:53:24 +040013 2013, 07:53:24
0

У меня есть код, очень похожий на ваш на 10.6.2 (но пишущий в файл), работающий без каких-либо проблем - так что можно делать то, что вы пытаетесь.

Просто из любопытства, какое значение вы используете для константы SIGIO? Я обнаружил, что недопустимое значение здесь в OS X может привести к сбою aio_write - так Я всегда прохожу SIGUSR1.

Может быть, проверить возвращаемое значение sigaction (), чтобы проверить детали сигнала?

ответил robin demetriades 18 FebruaryEurope/MoscowbThu, 18 Feb 2010 01:59:42 +0300000000amThu, 18 Feb 2010 01:59:42 +030010 2010, 01:59:42
0

Все пункты, поднятые в ваших ссылках, указывают на другой способ получения уведомлений о завершении io (например, kqueue, который является механизмом, специфичным для BSD), но на самом деле не отвечают на ваш вопрос о методах POSIX для асинхронных операций. и работают ли они на Дарвина.

Мир UNIX действительно представляет собой массу решений для этого, и было бы очень хорошо, если бы было одно испытанное решение, которое работало на всех платформах, увы, в настоящее время его нет - POSIX - это то, что нацелено на большинство последовательность.

Это что-то вроде удара в темноте, но может быть полезно также установить неблокирование на дескрипторе сокета (т.е. установить опцию сокета O_NONBLOCK), а также использовать SIGUSR1

Если у меня будет время, я поработаю с вашим примером сокета и посмотрю, смогу ли я что-нибудь из этого извлечь.

Удачи.

ответил robin demetriades 19 FebruaryEurope/MoscowbFri, 19 Feb 2010 00:50:16 +0300000000amFri, 19 Feb 2010 00:50:16 +030010 2010, 00:50:16
0

OSX Позволяет использовать сокеты через (CF) RunLoop. Или получать обратные вызовы из runloop. Это самый элегантный способ использования асинхронного ввода-вывода на Mac. Вы можете использовать свой существующий сокет и сделать CFSocketCreateWithNative. И зарегистрируйте обратные вызовы на вашем runloop.

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

// This will setup a readCallback 
void SocketClass::setupCFCallback() {   
CFSocketContext     context = { 0, this, NULL, NULL, NULL };

if (CFSocketRef macMulticastSocketRef = CFSocketCreateWithNative(NULL, socketHandle_, kCFSocketReadCallBack,readCallBack, &context)) {
    if (CFRunLoopSourceRef macRunLoopSrc = CFSocketCreateRunLoopSource(NULL, macMulticastSocketRef, 0)) {
        if (!CFRunLoopContainsSource(CFRunLoopGetCurrent(), macRunLoopSrc, kCFRunLoopDefaultMode)) {
            CFRunLoopAddSource(CFRunLoopGetCurrent(), macRunLoopSrc, kCFRunLoopDefaultMode);
            macRunLoopSrc_ = macRunLoopSrc;
        }
        else
            CFRelease(macRunLoopSrc);
    }
    else
        CFSocketInvalidate(macMulticastSocketRef);
    CFRelease(macMulticastSocketRef);
}
}



void SocketClass::readCallBack(CFSocketRef inref, CFSocketCallBackType  type,CFDataRef , const void *, void *info) {
if (SocketClass*    socket_ptr = reinterpret_cast<SocketClass*>(info))
    socket_ptr->receive(); // do stuff with your socket

}
ответил Jesper 25 FebruaryEurope/MoscowbFri, 25 Feb 2011 19:06:17 +0300000000pmFri, 25 Feb 2011 19:06:17 +030011 2011, 19:06:17

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132