- комментарий 0:
From: kmeaw
Date: 2021-03-19 06:46:38Z
> отличии от уродского Linux, в FreeBSD даже процессы можно представлять
> в виде файлов
Можно воспользоваться pidfd_open(2):
> A PID file descriptor can be monitored using poll(2), select(2), and
> epoll(7). When the process that it refers to terminates, these
> interfaces indicate the file descriptor as readable.
В портабельных программах для ожидания завершения процессов, которые не
являются прямыми потомками, часто используют pipe, пишущий конец
которого остаётся за дочерним процессом (и закрывается операционной
системой в момент его завершения). Недостаток этого подхода в том, что
дочерний процесс может "симулировать свою смерть", сделав close.
> Дальше всё аналогичное я хочу проделать в экосистеме GNU/Linux.
> я дополнительно
> ограничиваю read/write/kqueue возможности на оставшиеся сокеты -- а в
> seccomp strict режиме они сразу же будут только в read/write
А от чего хочется защититься, ограничивая сокет в режимах read-only или
write-only?
Если действительно необходимо ограничить передачу данных в одном
направлении и не хочется использовать seccomp bpf, то можно
воспользоваться memfd_create(2) и file sealing.
> Плюс kqueue там нет.
Есть epoll.
- комментарий 1:
From: Sergey Matveev
Date: 2021-03-19 07:24:53Z
*** kmeaw [2021-03-19 09:37]:
>Можно воспользоваться pidfd_open(2):
>> Плюс kqueue там нет.
>Есть epoll.
Судя по статьям, который ни в какое сравнение с kqueue не идёт, ибо не
поддерживает слежение на файлами (вместо этого же, насколько слышал,
всякие inotify используют? для AIO ещё что-то отдельное). Возможно
что-то поменялось со временем, но и старые и новые статьи имеют только
критику непродуманности epoll и его ограниченность. kqueue умеет ещё и
пачкой сразу получать cобытия.
https://long-zhou.github.io/2012/12/21/epoll-vs-kqueue.html
https://www.opennet.ru/base/dev/kqueue_vs_epoll.txt.html (хотя это 2003г)
ну и автор libev очень нелестного о нём мнения:
http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#FUNCTIONS_CONTROLLING_EVENT_LOOPS
Это конечно не отменяет того что с epoll на GNU/Linux придётся работать,
куда деваться (там где select/poll не подойдут).
>В портабельных программах для ожидания завершения процессов, которые не
>являются прямыми потомками, часто используют pipe, пишущий конец
>которого остаётся за дочерним процессом
Да, я это так и применяю. Просто через pipe не отловить точно ли он
упал, был ли убит или ещё чего. Сейчас я временно делаю ещё и третий
процесс который только и делает waitpid (всё остальное запрещено, грубо
говоря) и в pipe пишет статус завершения. Wrapper который waitpid
результат сериализует в pipe. Но в целом можно жить и с: или получаем
штатно данные из pipe-а, или отлавливаем close, что говорит о том что
нештатно процесс завершился.
>А от чего хочется защититься, ограничивая сокет в режимах read-only или
>write-only?
Просто так :-). Но в seccomp уже увидел и на практике проверил что там
через BPF режим фильтрации можно довольно легко чётко сказать какие
вызовы на какой файловый дескриптор разрешены.
>Если действительно необходимо ограничить передачу данных в одном
>направлении и не хочется использовать seccomp bpf, то можно
>воспользоваться memfd_create(2) и file sealing.
Спасибо за информацию! Ещё на эту тему нашёл: https://lwn.net/Articles/591108/
Но пока BPF режима seccomp хватает для этого. Сильно углубляться в
GNU/Linux-specific вещи не хочется совершенно.
- комментарий 2:
From: kmeaw
Date: 2021-03-19 17:31:23Z
>>Есть epoll.
> Судя по статьям, который ни в какое сравнение с kqueue не идёт
Статьи посмотрел. kqueue и epoll решают одну и ту же задачу похожим
способом - создают специальную сущность (обладающую состоянием) для
слежения за объектами, разделяя interest и ready set.
В статьях жалуются по сути на три проблемы:
1. epoll не умеет следить за чем-то.
Эта проблема решается, новые ядра умеют всё больше объектов представлять
в виде файловых дескрипторов или данных, которые по ним передаются. В
Linux даже есть signalfd и timerfd. Семантику семафоров можно
реализовать через eventfd с флагом EFD_SEMAPHORE.
inotify и pidfd защёлкнуть в epoll можно. Даже epoll можно защёлкнуть в
epoll. То, что пока нельзя завернуть в epoll непосредственно, можно всё
равно засунуть в общий event loop с помощью eventfd и второго потока,
который будет ждать события.
Интересно, а может ли kqueue следить за другим инстансом kqueue?
2. epoll_ctl приходится вызывать несколько раз.
Так можно почти про почти любой системный вызов сказать. Решить эту
проблему до конца можно только сделав интерфейс, который будет
передавать в ядро программу на каком-то ограниченном языке (bpf?),
которая только выполняет системные вызовы и не делает больше ничего.
Такой подход мог бы экономить переключения контекста.
Для наиболее "тяжёлых" операций есть batch-аналоги: векторный
ввод-вывод, AIO, чтение директории и так далее.
Необходимость в ожидании сразу большого числа объектов обычно в сетевых
сервисах в главном цикле обработки событий. Изменения interest set в
таких случаях малы - например, после accept нужно всего один дескриптор
добавить.
Для epoll мне сложно придумать сценарий, когда количество операций,
которые нужно выполнить не является константой. Конечно, всегда лучше,
когда константа равна единице (а ещё лучше - нулю :) ).
> Это конечно не отменяет того что с epoll на GNU/Linux придётся работать,
> куда деваться (там где select/poll не подойдут).
Говорят, есть странный способ взаимодействия с сетью через интерфейсы
AIO, но я так никогда не пробовал делаnь:
https://blog.cloudflare.com/io_submit-the-epoll-alternative-youve-never-heard-about/
3. epoll не умеет какой-то сценарий нотификаций.
Это уже исправлено. Сейчас есть целая куча флажков на любой вкус -
EPOLLRDHUP, EPOLLET, EPOLLONESHOT, EPOLLWAKEUP и даже EPOLLEXCLUSIVE.
- комментарий 3:
From: Sergey Matveev
Date: 2021-03-19 18:16:27Z
*** kmeaw [2021-03-19 20:22]:
>Интересно, а может ли kqueue следить за другим инстансом kqueue?
Бегло судя по man-у не вижу такого.
>2. epoll_ctl приходится вызывать несколько раз.
>Так можно почти про почти любой системный вызов сказать.
И возникает вопрос как часто эти вызовы делаются. А ведь epoll/kqueue
предназначены чтобы рулить большим кол-вом объектов/событий -- поэтому
сразу можно было бы этим озадачиться. Причём libev говорит о том что при
малом кол-ве событий -- epoll даже медленне будет чем select.
>https://blog.cloudflare.com/io_submit-the-epoll-alternative-youve-never-heard-about/
Помню тоже видел эту статью. Далёк ещё от всей этой темы, но со стороны
выглядит как "а давайте AIO, предназначенный для файлов, использовать и
для сетевых вещей", и параллельно "давайте epoll, предназначенный для
сетевых вещей, использовать и для файлов" :-). Тогда как kqueue выглядит
как "давайте сделаем просто систему оповещения о событиях", где ещё и
payload в событиях можно нести сразу же.
Вот весь Linux мне и представляется как нагромождение одного на другое,
потому что плохо всё продумано :-(. И ничего под одну гребёнку нет и не
делается. Capsicum хотели в Linux впилить -- забросили. Seccomp впилили,
а Торвальдс даже выпилить хотел назад. Это из того что последние дни
успел потрогать.
Наверное вопросы вкусовщины, но люто мне не близок подходы GNU/Linux
экосистемы в целом.