LINUX.ORG.RU

Блокирующие системные вызовы

 


0

4

Читаю документацию по некой библиотеке `Async`, там пишут что для работы с IO используют гибридную модель евентлуп + распараллеливание, аргументируя тем, что `некоторые системные вызовы не имеют неблокирующих альтернатив`. А что это за вызовы? Сходу такая веб-макака как я ничего не нагуглила.

★★★★★

рискну предположить что большинство системных вызовов

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

Я уже прочитал сам, но всё равно спасибо за снисхождение :).

Virtuos86 ★★★★★
()

Сходу приходит только getaddrinfo() — он сходит к ns в случае промаха.

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

пипец на лоре грамотеи. read/write есть как блокирующий (без O_NONBLOCK) так и не блокирующий. В первом случае он ждет и возвращает полный объём переданных данных, а во втором возвращает объём данных, которые смог передать за вызов или ошибку (EAGAIN или что там ещё на вашей системе).

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

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

для io всегда есть неблокирующие альтернативы хотя бы в виде poll/select

Я говорил о файловом I/O, а для него нет.

Сходу приходит только getaddrinfo() — он сходит к ns в случае промаха.

Кстати, трансляцию адресов можно делать и через getaddrinfo_a.

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

read/write есть как блокирующий (без O_NONBLOCK) так и не блокирующий

Стоит ли говорить, что для файлов O_NONBLOCK практически бесполезен, read и write всегда заблокируются на время чтения/записи. Есть вариант, конечно, использовать mmap/madvise, там можно лишь нехило соснуть и заблочиться только при munmap, вроде, но и здесь далеко не всё радужно. Ну или ядерный AIO остаётся, который никто, включая glibc, не использует, уж не знаю в силу каких его проблем.

mix_mix ★★★★★
()
Последнее исправление: mix_mix (всего исправлений: 3)
Ответ на: комментарий от mix_mix

Стоит ли говорить, что для файлов O_NONBLOCK практически бесполезен, read и write всегда заблокируются на время чтения/записи.

Можешь про это подробнее. Откуда информация, как проверить? Я всегда был уверен, что как для сети, так и для файловых операций read из неблокирующего файлового дескриптора отдаст данные, которые уже есть в буферах ядра (соответственно epoll вернет доступность на чтение при наличии данных в буфере ядра). Ну, а write что блокирующий, что нет всегда скопирует данные в буфер ядра и вернет количество скопированных данных. Вернуть ошибку E_AGAIN он может только, когда все буферы для данного дескриптора заняты и данные после предыдущей записи еще не успели попасть на диск (в сеть). Можешь сказать, где тут я не прав? И как это проверить? Тока достаточно подробно и понятно.

prefetch
()
Ответ на: комментарий от mix_mix

Ну да, бесполезен. А он там и не нужен, собственно.

read и write всегда заблокируются на время чтения/записи

Он не заблокируется, он будет сразу читать/писать, так как ждать ничего не надо. Пока он читает, естественно юзерспейс подождет, а как ты ещё хотел? Всё равно, что вызов функции — управление будет внутри функции, а та, что сделала вызов, будет «ждать»

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

Ман прочитать, вот как проверить. Вот из аналогичного механизма в FreeBSD:

VFILT_READ          Takes a descriptor as the identifier, and returns whenever
		    there is data available to read.  The behavior of the fil-
		    ter	is slightly different depending	on the descriptor
		    type.

		    Sockets
			Sockets	which have previously been passed to listen()
			return when there is an	incoming connection pending.
			data contains the size of the listen backlog.

			Other socket descriptors return	when there is data to
			be read, subject to the	SO_RCVLOWAT value of the
			socket buffer.	This may be overridden with a per-fil-
			ter low	water mark at the time the filter is added by
			setting	the NOTE_LOWAT flag in fflags, and specifying
			the new	low water mark in data.	 On return, data con-
			tains the number of bytes of protocol data available
			to read.

			If the read direction of the socket has	shutdown, then
			the filter also	sets EV_EOF in flags, and returns the
			socket error (if any) in fflags.  It is	possible for
			EOF to be returned (indicating the connection is gone)
			while there is still data pending in the socket
			buffer.

		    Vnodes
			Returns	when the file pointer is not at	the end	of
			file.  data contains the offset	from current position
			to end of file,	and may	be negative.

		    Fifos, Pipes
			Returns	when the there is data to read;	data contains
			the number of bytes available.

			When the last writer disconnects, the filter will set
			EV_EOF in flags.  This may be cleared by passing in
			EV_CLEAR, at which point the filter will resume	wait-
			ing for	data to	become available before	returning.

		    BPF	devices
			Returns	when the BPF buffer is full, the BPF timeout
			has expired, or	when the BPF has ``immediate mode''
			enabled	and there is any data to read; data contains
			the number of bytes available.

     EVFILT_WRITE   Takes a descriptor as the identifier, and returns whenever
		    it is possible to write to the descriptor.	For sockets,
		    pipes and fifos, data will contain the amount of space
		    remaining in the write buffer.  The	filter will set	EV_EOF
		    when the reader disconnects, and for the fifo case,	this
		    may	be cleared by use of EV_CLEAR.	Note that this filter
		    is not supported for vnodes	or BPF devices.

		    For	sockets, the low water mark and	socket error handling
		    is identical to the	EVFILT_READ case.

Я всегда был уверен, что как для сети, так и для файловых операций read из неблокирующего файлового дескриптора отдаст данные, которые уже есть в буферах ядра

Откуда при чтении файла в каких-то буферах заранее что-то есть?

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

Ну, в принципе, ты прав, примерно всё оно так себя и ведёт. Вот только к обычным файлам это поведение никакого отношения не имеет, равно как к директориям и блочным устройствам. Об этом везде пишут: http://stackoverflow.com/questions/16513973 (там ссылки на источники).

mix_mix ★★★★★
()
Последнее исправление: mix_mix (всего исправлений: 1)
Ответ на: комментарий от anonymous

Пока он читает, естественно юзерспейс подождет, а как ты ещё хотел?

Я бы хотел aio_*. Пока данных нет (в случае медленного устройства, вынужденной работы планировщика, etc.), можно было бы и чем-нибудь полезным заняться.

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

Это если мы не пишем БД. В любом случае, мне больше интересно чем ядерный AIO так плох, что его никто не использует.

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

Если ты всегда можешь селектнуть нулевым таймаутом набор дескрипторов без O_NONBLOCK, то это и есть неблокирующее io-мультиплексирование by definition. А если ты собираешься с пеной у рта доказывать, что read/write с эффективным O_NONBLOCK и схема с poll/select чем-то принципиально отличаются разрезе сабжа, то будь добр исчезни.

read/write есть как блокирующий (без O_NONBLOCK) так и не блокирующий

Вот ты сейчас глаза просто всем открыл.

не «альтернатива» а некая система сообщений, которая слушает несколько сокетов

//_0

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

Справедливости ради надо заметить, что анон прав, и под блокирующими вызовами обычно понимаются те вызовы, которые могут усыпить тред на indeterminate amount of time, например операция с сокетом. Подгрузку страницы с диска и ее копирование в юзерспейс линукс почему-то считает вполне предсказуемыми по времени, но может быть он так устроен, что есть гарантии (или это не так важно именно для дискового ио, например).

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

Ну это вопрос терминологии, не более. Суть в том, что приложение может висеть без дела в сисколле, когда могло бы в это время заняться чем-нибудь полезным.

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

Всегда можно отцепить io-тред и общаться через очередь, это нифига не сложнее асинхронки.
Сабжевая либа наверное так и делает.

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

Разумеется. Так делает даже glibc в aio_*. ОП как раз и интересовалась для чего подобное поведение.

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

В линуксе AIO плох следующим:

- Требует включения directio (O_DIRECT). То есть, копировать данные будет не ядро, а DMA, но кеш ФС использоватся не будет. На подавляющем большинстве задач (кроме БД, которые делают рандомный доступ к случайным концам гигантских файлов), это даст больше минусов, чем плюсов. Либо писать своё подобие файлового кеша, как и делают БД.

- directio же требует, чтобы начало и конец чтения были выровнены по некоторой специфичной для конкретной ФС границе (что-то около 512 байт), невыровненные части будут считываться без directio и без aio. То есть требуется либо сильно избыточное чтение, либо очень аккуратная работа с целевой платформой.

Поэтому на линуксе для симуляции файлового aio обычно юзают пул тредов, которые лочатся на read/write.

Во FreeBSD, вроде бы, ситуация лучше, но я не интересовался этим, так как ось мёртвая.

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