LINUX.ORG.RU

Гарантированно асинхронная запись в Linux?

 , , ,


2

3

Вопрос прост как 3 копейки:

Есть ли в Linux системный вызов «запиши в файловый дескриптор вот эти 4096 байт, но не блокируй меня на всё время записи, а отправь 4096 байт в буфер на стороне ядра и вот тебе коллбек, который нужно будет вызвать у меня, когда реальная запись будет завершена».

Таким образом реализуется, либо цепочка записей, когда внутри коллбека будет использован тот же системный вызов и в качестве возврата - опять же этот коллбек, либо - просто запись в хаотичном порядке, когда пишущей стороне вообще глубоко до лампочки, записались данные или нет (хотя если коллбек обнаружит сбой записи - может быть и вызвано исключение, why not).

К чему вопрос? К тому, что легко и просто находится select, позволяющий начать запись только тогда, когда не нужно будет ждать завершения чьей-то предыдущей записи - и это прекрасно. Но хотелось бы и саму запись в асинхронном режиме: я просто отправляю в буферы ядра данные для записи, и после этого мне «хоть трава не расти» - я могу свободно заниматься дальнейшей полезной работой.

Наверняка же есть такое?

★★★★★

Последнее исправление: DRVTiny (всего исправлений: 2)

Насколько мне известно Linux в принципе не умеет в асинхронный I/O.

itn ★★★
()
Ответ на: комментарий от Dark_SavanT

Чего-то я не догоняю, где в aio_write прописать адрес процедуры обратного вызова?

Кстати, на мой взгляд, неплохой вариант - для каждой записи использовать свободный поток из некоего списка потоков, предназначенных специально для того, чтобы делать write() и блокироваться. Тогда фактический код возврата придёт в поток ввода/вывода, который может аинхронно вернуть информацию потоку управления... Гм, сигналом?

Косяк такого подхода - в том, что при задержках записи мы наплодим потоков и несколько под(насолим) ядру, загадив память ненужным хламом в виде структур, связанных с потоками, в т.ч. структур планировщика, стеков (по 8Мб на поток вроде?) и, собственно, буферизированных данных для записи.

Кстати, лавинообразная буферизация данных для записи - в принципе проблема асинхронных вызовов write в любом виде, что с тредами, что без: при низком уровне «вежливости» код программы может вообще не ждать освобождения дескриптора файла для записи (select) и сразу делать aio_write, не заботясь о последствиях.

DRVTiny ★★★★★
() автор топика

Наверняка же есть такое?

Отдельная нитка-логгер с очередью. В ядро такое запихнуть просто глупо, ибо «трава не расти» слишком никудышное ТЗ для сискола ядра.

vodz ★★★★★
()

Это поведение определяется подсистемой или драйвером обрабатывающим твой write(). Для дискового ввода-вывода почти всегда именно так и проиходит.

cvv ★★★★★
()

Гарантированно нельзя, иное означало бы неограниченный буфер на стороне ядра, а значит и гарантированный DOS через исчерпание ядерной памяти. Только поток и своя очередь.

slovazap ★★★★★
()

Наверняка же есть такое?

Есть. Называется pthread: в одном потоке ставишь задачу, а другой ее исполняет, пока первый занимается чем-то своим.

kawaii_neko ★★★★
()
Ответ на: комментарий от kawaii_neko

ОК, мне нужно сделать 100500 операций записи в секунду. А устройство принимает 1500 записей в секунду. Сколько я должен наплодить потоков для записи после часа работы приложения?

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от slovazap

Ядро может выделить процессу лимитированное количество буферной памяти и бить по лицу errno в случае слишком наглого aio_write'а.

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

Механизм выхода из ситуации errno=буфер_заполнен_жди_сволочь - select в цикле, пафосно называемом циклом обработки событий, ждать доступности дескриптора на запись. Если доступен - значит, и буфер не в потолок забит, и само устройство не занято записью по состоянию на момент select'а.

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от DRVTiny

Механизм выхода из ситуации errno=буфер_заполнен_жди_сволочь

Угу, а потом начнутся визги: ааа, дайте нам флаги управления этим буфером, нам надо удалить первые 10 сообщений и вообще вот это пропихнуть без очереди, переключив временно в LIFO...

vodz ★★★★★
()

Нравится как в этой теме все оправдываются за отсутствие async io в линуксе.

anonymous
()
Ответ на: комментарий от DRVTiny

обратный вызов придётся делать самому. есть поле aio_sigevent, в котором можно сказать как тебя уведомить о том, что операция завершилась: никак, сигнал или sigev_thread, который какое-то хитрое колдунство, которе я ни разу не использовал.

Dark_SavanT ★★★★★
()
Ответ на: комментарий от DRVTiny

thread pool с очередью задач же! Но всё равно упадёт когда память на очередь кончится.

Dark_SavanT ★★★★★
()

Есть ли в Linux системный вызов «запиши в файловый дескриптор вот эти 4096 байт, но не блокируй меня на всё время записи, а отправь 4096 байт в буфер на стороне ядра и вот тебе коллбек, который нужно будет вызвать у меня, когда реальная запись будет завершена».

вообще это лучше через поток делать, aio в линуксе не очень

annulen ★★★★★
()

В линуксе этого, в отличие от винды, нет.

Придется эмулировать через epoll и пул тредов.

lovesan ★★
()
Ответ на: комментарий от anonymous

в каком плане не очень? медленный?

Требует O_DIRECT и выравнивания по границе блока

annulen ★★★★★
()

лол можит ты ещё хочеш штобы тебе 12309 пофиксили?

.\_/.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.