Я хотел бы знать не только различия на стороне пользователя, но и различия/общие части в реализации ядра Linux.
Есть ли разница между socketpair и парой неназванных труб?
Ответ 1
- Трубы
-
являются однонаправленными, поэтому вам нужно иметь две трубы для двунаправленной связи, тогда как гнездовая пара двунаправлена.
-
трубы всегда ориентированы на поток, тогда как сокеты-пары могут быть ориентированы на датаграммы.
-
socketpairs являются нормальными
AF_UNIX
сокетами, что означает, что через них могут передаваться вспомогательные сообщения типаSCM_RIGHTS
иSCM_CREDENTIALS
.
В ядре каналы реализованы в коде файловой системы и сокетах в сетевом коде.
Ответ 2
Возможности сокета-парама shutdown()
и SCM_RIGHTS
необходимы для обеспечения устойчивой к расовой связи связи с подпроцессами в многопоточной программе.
Трубы могут быть продублированы случайно в случае нескольких потоков pipe()
и fork()
одновременно; в этом случае конец записи трубы никогда не может быть закрыт, и EOF никогда не может произойти на считываемом конце, что вызывает тупик. Даже для тех программ, которые используют fork()
только для подпроцессов (т.е. Все fork()
оперативно сопровождаются execve()
в дочернем элементе), захват канала параллельным fork()
еще продолжается с настройкой бита FD_CLOEXEC
, запрет использования не переносимого системного вызова Linux pipe2()
, который принимает O_CLOEXEC
.
Решение этой угрозы переносимым образом, также для программ, которые fork()
без вызова execve()
, включает в себя socketpairs:
- Для исходящего канала (т.е. записи из основной программы в подпроцесс): используйте сокет-пак вместо канала и вызовите
shutdown()
доclose()
от родителя, чтобы вызвать условие безопасности EOF, независимо от того, был дублирован файловый дескриптор. - Для входящего канала (т.е. чтения из подпроцесса) создайте канал в дочернем элементе (так, чтобы конец записи никогда не был виден в родительском объекте для случайного дублирования) и отправлял только конец чтения родительскому элементу через сокет с a
SCM_RIGHTS
.