LINUX.ORG.RU

Чем в линуксах(актуальных версиях ядра) отличаются друг от друга системные вызовы splice и sendfile?

 , , , ,


0

2

Основной вопрос в заглавии. Единственное значимое отличие я увидел в том, что для splice надо чтоб один из файловых дескрипторов был pipe. Получается что sendfile для pipe работать не будет? Если так, почему б не сделать один системный вызов, который бы и к пайпам, и к сокетам, и к обычным файловым дескрипторам был применим?

Есть вообще какие-то правила, которым надо следовать в плане системных вызовов? Например если я свою ОС вздумаю написать, какие системные вызовы лучше делать? Я понимаю что есть какой-то там стандарт POSIX, SUS и проч, где оговариваются какие-то функции, но они могут быть имплементированы в glibc а не непосредственно системными вызовами.

★★★★★

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

Если так, почему б не сделать один системный вызов

splice появился позже sendfile. А userspace API в линуксе принято не ломать.

который бы и к пайпам, и к сокетам, и к обычным файловым дескрипторам был применим?

Ограничения по видам fd в splice - технического характера, когда-нибудь допилят это, если ещё не.

Например если я свою ОС вздумаю написать, какие системные вызовы лучше делать?

Какие считаешь нужным, твоя же ОС.

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

Это вроде про sendfile(), начиная с версии 2.6.33.

xaizek ★★★★★
()

Оба вызова не являются вызовами общего назначения. Они оптимизации частных случаев. sendfile() для отправки файла по сети для каких-нибудь серверов. Потом подобное понадобилось для pipe, но sendfile() отображает источник на память, что не будет работать с pipe. Для всех возможных случаев такой API особо не нужен, а лишнее в ядре городить тоже не очень (разные типы файлов могут требовать разных оптимальных реализаций и обработки ошибок).

Есть вообще какие-то правила, которым надо следовать в плане системных вызовов?

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

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

ОК, если я хочу создать свой аналог dd но быстрее(чтоб более напрямую было) то что мне лучше использовать, sendfile или splice?

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

splice же требует pipe в одном из дескрипторов, так что не сработает в большенстве случаев и sendfile выходит универсальнее. А если он упадёт с ошибкой, то можно копировать вручную (можно два mmap, posix_fadvice и потом memcpy). А так анонимус дело говорит, надо проверять и сравнивать результаты.

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

У vmsplice() схоже. Я прозреваю, что сделано это было ради zero copy IPC.

kirk_johnson ★☆
()

pipe на самом деле является буфером, находящимся в пространстве ядра. При пересылке из произвольного дескриптора в произвольный в любом случае потребовался бы механизм буферизации, решили воспользоваться готовым. При этом через обычный fcntl мы можем настраивать размер этого буфера, не плодятся новые сисколлы. Функции, которые есть, на самом деле просто обёртки над этим буфером: передать кусок памяти в буфер, скопировать один буфер в другой, записать/прочитать в буфер из fd. То есть это всё, что мы можем делать с обычным read/write и char buf[], но запихнуто в ядро и вынесено в такой лаконичный интерфейс.

vzzo ★★★
()
Последнее исправление: vzzo (всего исправлений: 1)
29 октября 2016 г.
Ответ на: комментарий от xaizek

splice же требует pipe в одном из дескрипторов, так что не сработает в большенстве случаев

Вообще-то, типичный сценарий использования splice - это копирование из fd1 во пайп, а затем копирование из пайпа в fd2, блоками по 64К так как больше в пайп не влезет. Поэтому все наоборот, это splice более универсален, так как у sendfile источник обязательно должен быть файлом

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

Вообще-то, типичный сценарий использования splice - это копирование из fd1 во пайп, а затем копирование из пайпа в fd2

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

блоками по 64К так как больше в пайп не влезет.

До 1 МиБ влазит при расширении и можно увеличивать:

$ cat /proc/sys/fs/pipe-max-size
1048576
Полагаться, конечно, надо на меньшее.

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