Здравствуйте, Pzz, Вы писали:
CK>>Я делаю оптимизацию под SSD + есть кое какие требования, которые проще всего реализовать через O_DIRECT+асинхронность.
Pzz>Мне кажется, для SSD использование асинхронного ввода-вывода не даст сколь либо ощутимой оптимизации.
Я пробовал. По моим измерениям таки дает. Правда я использовал uv.
Pzz>1) Под ниткой здесь и далее я имею ввиду ту нитку, в которой крутится event loop, а под сокетом — файловый дескриптор, которым нам интересен на предмет poll() (но он может быть и не сокетом, а пайпом и т.п.). Можно сделать несколько таких ниток, но каждый сокет должен быть привязан к своей нитке.
Pzz>2) В нитке маскируем SIGIO (man pthread_sigmask)
Pzz>3) Все файловые сокеты, которые мы собираемся poll()'ить, настраиваем так, чтобы от них приходил SIGIO. См. man fcntl на предмет F_SETSIG, F_SETOWN_EX, O_ASYNC и O_NONBLOCK. Я писал это под более старое ядро, чем сегодняшние, поэтому работающего куска кода не покажу, но в мане вроде все просто. В общем, надо, чтобы приходил SIGIO, причем конкретно той нитке, которая будет ждать, а не первой попавшейся
Pzz>4) Ожидание выглядит следующим образом:
Pzz>Pzz> volatile bool got_signal = false;
Pzz> sigjmp_buf jmp_buf;
Pzz> if (sigsetjmp(jmp_buf, true))
Pzz> got_signal = true;
Pzz> else {
Pzz> pthread_sigmask(...); // Размаскируем SIGIO
Pzz> io_getevents(...); // Ждем дискового ввода-вывода
Pzz> pthread_sigmask(...); // Маскируем SIGIO
Pzz> }
Pzz>
Pzz>5) Обработчик SIGIO делает siglongjmp(jmp_buf, 1);
Pzz>6) Поскольку в случае прихода сигнала мы не можем знать, успели ли мы вызвать io_getevents(), то значение, которое эта функция возвращает, для нас бессмысленно, и мы вынуждены сканировать массив struct io_event после вызова io_getevents(), заполнив его нулями до вызова, чтобы понять, успел ли он вернуть сколько-нибудь событий.
Pzz>7) Если после выхода из ожидания got_signal = true, разбираемся с сокетами используя любой механизм (select/poll/epoll) с нулевым таймаутом.
Pzz>Как-то примерно так...
Спасибо, будет с чего начать