В компьютерных сетях STREAMS — это собственный фреймворк в Unix System V для реализации драйверов символьных устройств , сетевых протоколов и межпроцессного взаимодействия . В этом фреймворке поток — это цепочка сопрограмм , которые передают сообщения между программой и драйвером устройства (или между парой программ). STREAMS возник в версии 8 Research Unix как Streams (не с заглавной буквы).
STREAMS представляет собой модульную архитектуру для реализации полнодуплексного ввода-вывода между ядром и драйверами устройств. Наиболее часто он использовался при разработке терминального ввода-вывода ( линейная дисциплина ) и сетевых подсистем. В System V Release 4 весь терминальный интерфейс был переписан с использованием STREAMS. [1] Важной концепцией в STREAMS является возможность объединять драйверы — пользовательские модули кода, которые могут изменять функциональность сетевого интерфейса или другого устройства — вместе для формирования стека. Несколько таких драйверов можно объединить в цепочку по порядку.
STREAMS была основана на подсистеме Streams I/O, представленной в Eighth Edition Research Unix (V8) Деннисом Ритчи , где она использовалась для терминальной подсистемы I/O и набора протоколов Интернета . Эта версия, еще не названная STREAMS заглавными буквами, соответствовала новой функциональности в рамках существующих системных вызовов ввода-вывода устройств ( open , close , read , write и ioctl ), [2] и ее применение было ограничено терминальным вводом-выводом и протоколами, обеспечивающими конвейерную семантику ввода-вывода.
Эта система ввода-вывода была перенесена в System V Release 3 Робертом Израилем, Джилом Макгратом, Дэйвом Оландером, Хер-Доу Че и Мори Бахом как часть более широкой структуры, предназначенной для поддержки различных транспортных протоколов, включая TCP, транспорт ISO Class 4, SNA LU 6.2 и протокол AT&T NPACK (используемый в RFS ). [3] Впервые она была выпущена с пакетом Network Support Utilities (NSU) UNIX System V Release 3. [4] Этот порт добавил системные вызовы putmsg , getmsg и poll , которые по своему назначению почти эквивалентны вызовам send , recv и select из сокетов Беркли. Системные вызовы putmsg и getmsg изначально назывались send и recv , [5] но были переименованы, чтобы избежать конфликта пространств имен. [6] В System V Release 4 STREAMS был расширен и использовался для терминальной инфраструктуры ввода-вывода и каналов, предоставляя новые полезные функции, такие как двунаправленные каналы и передача файловых дескрипторов . [3] Также был создан порт для UNICOS . Эрик С. Рэймонд цитирует Ритчи, который говорит о сложности System V STREAMS по сравнению с его V8 Streams, что «Streams означает нечто иное, когда его кричат». [7]
Одновременно с портом System V Release 3 компания AT&T разработала протоколонезависимые руководства по передаче сообщений STREAMS для уровня связи [8] , сети [9] и транспортного уровня [10] модели OSI (уровни 2–4). Из-за типично тесной связи реализации сетевых и транспортных протоколов в заданном стеке протоколов и типичной практики реализации уровней 5–7 вне ядра , позднее X/Open стандартизировала только интерфейсы служб STREAMS уровня связи [8] и транспортного уровня [11] . В сочетании с моделью передачи транспортных сообщений был определен интерфейс транспортного уровня (позже принятый как транспортный интерфейс X/Open ) для предоставления API, независимого от транспортного протокола, для разработки приложений. Кроме того, библиотека, поддерживающая уровни сеанса , представления и приложения [12], была определена и позднее стандартизирована The Open Group . [13]
STREAMS требовался для соответствия Единой спецификации UNIX версий 1 (UNIX 95) и 2 (UNIX 98), но в результате отказа разработчиков BSD и Linux предоставить STREAMS, [ требуется ссылка ] был отмечен как необязательный для соответствия POSIX группой Austin в версии 3 (UNIX 03). POSIX.1-2008 с TC1 (IEEE Std 1003.1, издание 2013 г.) обозначил STREAMS как «отмеченный устаревший» [14] [15], что означает, что указанная функциональность может быть удалена в будущей версии спецификации. Однако конкретное определение «устаревшего», использованное [16], также гласит, что строго соответствующие POSIX приложения «не должны использовать устаревшие функции».
В версии 7 Unix команда была подключена к терминалу (клавиатура и экран, или клавиатура и принтер ) через механизм, называемый дисциплиной линии, который буферизовал одну строку ввода, т. е. ждал, пока пользователь нажмет клавишу Return, прежде чем отправлять ввод в программу для обработки; это позволяло просто исправлять ошибки. Потоки заменили это набором модулей обработки, организованных в линейную цепочку, которая позволяла двунаправленную связь между соседними модулями. Программы могли «проталкивать» новый модуль на один конец цепочки, чтобы изменить поведение терминала или другого символьного устройства. Ритчи приводит пример цепочки терминального модуля, соединенного с сетевым модулем Datakit, для достижения удаленного входа в систему по сети. [5] Помимо символов (байтов), идущих от программы к устройству и наоборот , потоки могли переносить управляющие сообщения, такие как «hangup» (сброс соединения) и сообщения ioctl .
Потоки также могли использоваться для межпроцессного взаимодействия , путем подключения двух процессов к псевдотерминалам . Эта функциональность была реализована в оконной системе mpx для графического терминала Blit , который мог отображать несколько окон эмулятора терминала . Каждое окно было процессом, который взаимодействовал с оконной системой через псевдотерминал, на котором был установлен драйвер дисциплины линии, отправляя ему набранные символы и получая текст (и графику) для отображения. Управляющие сигналы обозначали желание пользователя переключаться между окнами или закрывать их. [17] [18] : 348–350
Фактические модули Streams находятся в пространстве ядра в Unix и устанавливаются (проталкиваются) и удаляются (выталкиваются) системным вызовом ioctl. Например, чтобы установить вышеупомянутую дисциплину линии на файловом дескрипторе fd
, ссылающемся на терминальное устройство, можно написать (на C ): [18] : 347
ioctl ( fd , PUSH , TTYLD );
Для выполнения ввода/вывода в потоке используются либо системные вызовы read
и write
, как в случае с обычными файловыми дескрипторами, либо набор функций, специфичных для STREAMS, для отправки управляющих сообщений. [19]
Ритчи признался, что сожалеет о необходимости реализовать потоки в ядре, а не как процессы, но чувствовал необходимость сделать это по соображениям эффективности. [5] Более поздняя реализация Plan 9 действительно реализовала модули как процессы на уровне пользователя. [20]
STREAMS в основном использовался в мире System V Unix; однако существуют и другие реализации:
Linux не включает в себя функциональность STREAMS без сторонних дополнений. Caldera «настояла» на включении STREAMS в Linux около 1998 года для поддержки своего Netware для Linux, но это было полностью отвергнуто разработчиками ядра Linux по техническим причинам (в основном производительность). [25] Уровни совместимости в Linux для других операционных систем преобразуют операции STREAMS в сокеты как можно раньше. [26] Реализацией, используемой Caldera, была «LiS» компании GCOM; позже она фигурировала в юридических баталиях преемника Caldera, SCO Group , против Linux, при этом SCO утверждала, что Linux со STREAMS нарушал то, что она считала своими авторскими правами на System V. [25]