смотрим чем наиболее он существенно синтаксически отличается
Ну вот и следующий вопрос - а почему вы взяли именно эти синтаксические отличия, а не, например, динамическую типизацию, "batteries included" и предельное облегчение интерактивной работы? А отступы много где есть как синтаксический элемент...
Как-то забыл эту тему, случайно вспомнил... мы рядом чуть глубже обсуждали, но таки лучше вынести в отдельное сообщение:
Пофикшено в RFC 8260 чанками I-DATA.
Нет. Нету раздельного приёмного окна для каждого потока, значит, ты говоришь о чём-то другом, но не том, что я имею в виду. Возможность передавать огромные сообщения по кусочкам это, конечно, прикольно, но такой разрез с чуть большей затратой можно сделать и в юзерленде (добавить, например, один байт с теми же однобитовыми флагами B и E, или вообще впихнуть их в PPID).
Когда потоков много, общий ACK будет гораздо эффективнее
И он будет означать только то, что что-то услышано, но не что данные приняты - это если в пакете были чанки нескольких потоков, из которых из одного данные приняты, а другого - нет, потому что окна нету. Увы.
Ну, по крайней мере, стараются минимизировать сбрасывание через PCIDы. И для новых процессоров уже необязательно делать ограничения через TLB. Вот из моего лаптопного i7-12650H пропал флаг bugs: cpu_meltdown (а в старом десктопе ещё есть). Есть оба spectre, но их плясками с TLB не лечат.
Ну так на это есть таймеры. Они могут быть сделаны тоже в стиле файлов (достаточно часто) или нет, но должны обеспечивать возможность проснуться раз в пару десятков миллисекунд и отправить несколько килобайт в буфер звуковухи. С видео сложнее, но сама карта эту сложность компенсирует в себе.
То есть cat не "просто" применяет read к мыши, а получает от неё какие-то события?
Что есть "просто" у вас, не знаю, но этот метод состоит в том, чтобы в цикле читать порцию данных (обычно фиксированного размера), если что-то происходит, то read() срабатывает и данные приходят. И это не только мышь, сейчас так стараются все входные источники обрабатывать.
Ну да, цена обработки системного вызова даже в простейшем случае это примерно как 20-50 косвенных переходов по адресу или ветвлений по непредсказанной ветке. А вот TLB не сбрасывают, это не переход на другую нитку (даже другого процесса, чтобы надо было менять сам корневой каталог трансляции).
Где "новизна"? "Каталог" как раз более старый термин. "Директория" это продукт тупых переводчиков 90-х. А "папка", как перевод "folder", имеет более широкий смысл: папка может быть и виртуальной (в Windows Explorer полно таких, Dolphin из KDE тоже такое умеет).
Вообще формально ничто не мешает запретить любому интерпретатору именно мапить файл скрипта в память. То, что пара распространённых не делает это, не показатель.
Но он всё таки действует умнее и сначала удаляет существующий файл.
Я б тут даже поправил: идеальный вариант такого менеджера пишет новый файл рядом и затем вызывает rename(), который атомарная операция.
Но пару раз я видел последствия того, как ничего из таких защитных мер не было сделано, или сделано неверно (записано поверх существующего файла): пример. Хотя я тут не уверен, что в библиотеке фонтов не было логики однажды открыть файл и закэшировать смещения.
Не подходит для мест, где у файла может быть много потоков (OS X) или дырки (все Unix).
А ещё "поток" как-то не предполагает свободное позиционирование в нём, изменение размера (Unix сисколл truncate() может как урезать, так и расширять, в том числе дырками), или чтение разных данных на каждой операции чтения. И это только вспомнившееся с ходу.
То, что вы предложили, это хороший типаж (trait) для доступа, когда требуется только последовательное чтение или запись, как в моём примере с grep входа с stdin. Но не для всего, что зовётся файлом.
Не пойдёт там, где в файле может быть несколько потоков (Windows, OS X) или дырки (все Unix, OS X).
И, по-моему, именно слово "файл" вводит в заблуждение
Я бы начал с вопроса, можем ли мы разделить понятия файла на диске, файла как сущности виртуального дерева и файла как объекта, адресуемого дескриптором - разделить (и дать разные названия) без того, чтобы отправить мозговые крыши большинства ITшников в далёкие тёплые края. И вот тут у меня начинают вырастать колоссальные сомнения.
А раз реализация различна, то и должен быть способ через системные вызовы обратиться к какой-то конкретной реализации.
Он есть. socket, bind, connect, {set|get}sockopt параметризуются. Остальным - не нужно.
Наворачивание абстракций над этими двумя версиями протокола только усложняют реализацию - требуют в ядре или if городить, или вызовы через указатели, или как-то ещё.
В ядре это делают один раз и опытные разработчики. Если это делать в юзерленде, придётся делать каждому отдельно. Концентрация ошибок подымется в сотни раз.
Или же это закончится тем, что будет универсальная библиотека уже в юзерленде, которая будет делать то же самое. Что-то похожее делалось в SysV XTI (конкурент BSD sockets): в универсальный объект сокета складывались специальными ioctlʼями модули: IPv4, потом TCP, потом какой-нибудь фильтр... И что вы думаете - тоже умерло, остался BSD sockets.
Поэтому я предлагаю от них избавиться, имея различные API для различного функционала, а абстракции реализовывать уже в коде прикладной программы.
В которых не будет реализовано 99% того, что нужно. Функциональность упадёт, совместимость разрушится в обе стороны. Или опять же всё свалят на библиотеки. Вангую, что этим и закончится, после многолетнего бардака.
Почему различать IPv4 и IPv6 - перебор? Пользовательская программа использует или одно, или другое.
Потому что у них одинаково всё, кроме адресов. И то, адреса пересекаются (в Linux v6 слушающий сокет автоматом цепляется и на v4, если не отменить). Когда 99.99+% функциональности одинаково, разделение становится искусственным.
Ну а в BSD sockets это различие загнали под одно поле параметра функций bind() и connect(), избавившись от необходимости дублирования всего остального.
Условно говоря есть классы IPv4Stream и IPv6Stream, реализующие на основе разных системных API интерфейс вроде IAbstractTCPStream.
И различие исчезает с момента коннекта.
Я начинаю недоумевать, как вы программируете с таким нежеланием понимать и поддерживать абстракции.
Ваша идея понятна. Но принять я её такую не могу: просто нет смысла усложнять на ровном месте то, что делается проще и универсально - и, главное, с возможностью развития.
Сравните это с ООП. Какой бы вариант его ни был, он старается поддерживать LSP, который есть принцип совместимости интерфейсов и определённых ожиданий контракта от прочих участников. С ним я могу применять любую реализацию того, что отвечает интерфейсу и контракту. Вы же требуете определённой фиксированной реализации. Зато на шелл ложится вся ноша разбора, как писать в файл, как в сокет... а где граница? Почему в сокет, который связан с сервером в локалке, и сервером на другом континенте, пишем одинаково? Там ведь тоже различие в деталях, типа обычной round-trip задержки, которая кому-то существенна.
Вы не разрешаете абстрагироваться от излишнего. Индустрия уже показала свой выбор.
Если из него можно прочитать данные батареи - значит, он их хранит.
Нет, хранит не он. Он их просто представляет в некотором удобном для чего-то виде. Пусть рядом будут uevent_json и uevent_cbor, где то же самое, но в другом формате; они меняться будут синхронно.
И, конечно же, он расположен за пределами адресного пространства процесса.
Почему? В том же адресном пространстве - по крайней мере на x86 и ARM. Просто юзерленду недоступен именно как содержимое памяти, ещё и представлен в каких-то запутанных структурах.
Видите, вот стали чуть внимательнее смотреть в детали - и всё определение поплыло.
Да, file descriptor это больше descriptor чем file.
Но его продолжают именовать file descriptor. А не, как в Windows, "handle" неважно чего.
Меня уже подводит память, но кажется, что основная дискуссия происходила лет на 5 раньше. Это уже повторная, в сообщениях есть явное упоминание про это. Я пытался искать и не нашёл. Но гугл хранит не все сообщения, или даёт плохой поиск по ним.
Ну вот и следующий вопрос - а почему вы взяли именно эти синтаксические отличия, а не, например, динамическую типизацию, "batteries included" и предельное облегчение интерактивной работы?
А отступы много где есть как синтаксический элемент...
Этому есть подтверждение? (опрос/анализ UX от приличного агенства)
Как-то забыл эту тему, случайно вспомнил... мы рядом чуть глубже обсуждали, но таки лучше вынести в отдельное сообщение:
Нет. Нету раздельного приёмного окна для каждого потока, значит, ты говоришь о чём-то другом, но не том, что я имею в виду. Возможность передавать огромные сообщения по кусочкам это, конечно, прикольно, но такой разрез с чуть большей затратой можно сделать и в юзерленде (добавить, например, один байт с теми же однобитовыми флагами B и E, или вообще впихнуть их в PPID).
И он будет означать только то, что что-то услышано, но не что данные приняты - это если в пакете были чанки нескольких потоков, из которых из одного данные приняты, а другого - нет, потому что окна нету. Увы.
Ну, по крайней мере, стараются минимизировать сбрасывание через PCIDы. И для новых процессоров уже необязательно делать ограничения через TLB. Вот из моего лаптопного i7-12650H пропал флаг bugs: cpu_meltdown (а в старом десктопе ещё есть). Есть оба spectre, но их плясками с TLB не лечат.
Видимо, ваша реплика оказалась слишком неоднозначна. Если вы имели в виду что-то другое, то уточните.
Ну так на это есть таймеры. Они могут быть сделаны тоже в стиле файлов (достаточно часто) или нет, но должны обеспечивать возможность проснуться раз в пару десятков миллисекунд и отправить несколько килобайт в буфер звуковухи. С видео сложнее, но сама карта эту сложность компенсирует в себе.
Что есть "просто" у вас, не знаю, но этот метод состоит в том, чтобы в цикле читать порцию данных (обычно фиксированного размера), если что-то происходит, то read() срабатывает и данные приходят. И это не только мышь, сейчас так стараются все входные источники обрабатывать.
Ну да, цена обработки системного вызова даже в простейшем случае это примерно как 20-50 косвенных переходов по адресу или ветвлений по непредсказанной ветке. А вот TLB не сбрасывают, это не переход на другую нитку (даже другого процесса, чтобы надо было менять сам корневой каталог трансляции).
В 2009 ещё не производилась TLC, ну а флэшку могли заказать из более надёжной серии (стенки транзисторов толще, легирование точнее, и т.д.)
Где "новизна"? "Каталог" как раз более старый термин. "Директория" это продукт тупых переводчиков 90-х. А "папка", как перевод "folder", имеет более широкий смысл: папка может быть и виртуальной (в Windows Explorer полно таких, Dolphin из KDE тоже такое умеет).
Вообще формально ничто не мешает запретить любому интерпретатору именно мапить файл скрипта в память. То, что пара распространённых не делает это, не показатель.
И защиты ядром в таком случае у них не будет.
Я б тут даже поправил: идеальный вариант такого менеджера пишет новый файл рядом и затем вызывает rename(), который атомарная операция.
Но пару раз я видел последствия того, как ничего из таких защитных мер не было сделано, или сделано неверно (записано поверх существующего файла): пример. Хотя я тут не уверен, что в библиотеке фонтов не было логики однажды открыть файл и закэшировать смещения.
Это пока не начинаются проблемы типа таких. Или флэш-память с более 2 уровнями заряда (MLC, QLC и далее).
Дырявые абстракции — они такие.
Не подходит для мест, где у файла может быть много потоков (OS X) или дырки (все Unix).
А ещё "поток" как-то не предполагает свободное позиционирование в нём, изменение размера (Unix сисколл truncate() может как урезать, так и расширять, в том числе дырками), или чтение разных данных на каждой операции чтения. И это только вспомнившееся с ходу.
То, что вы предложили, это хороший типаж (trait) для доступа, когда требуется только последовательное чтение или запись, как в моём примере с grep входа с stdin. Но не для всего, что зовётся файлом.
Не пойдёт там, где в файле может быть несколько потоков (Windows, OS X) или дырки (все Unix, OS X).
Я бы начал с вопроса, можем ли мы разделить понятия файла на диске, файла как сущности виртуального дерева и файла как объекта, адресуемого дескриптором - разделить (и дать разные названия) без того, чтобы отправить мозговые крыши большинства ITшников в далёкие тёплые края. И вот тут у меня начинают вырастать колоссальные сомнения.
Он есть. socket, bind, connect, {set|get}sockopt параметризуются. Остальным - не нужно.
В ядре это делают один раз и опытные разработчики. Если это делать в юзерленде, придётся делать каждому отдельно. Концентрация ошибок подымется в сотни раз.
Или же это закончится тем, что будет универсальная библиотека уже в юзерленде, которая будет делать то же самое. Что-то похожее делалось в SysV XTI (конкурент BSD sockets): в универсальный объект сокета складывались специальными ioctlʼями модули: IPv4, потом TCP, потом какой-нибудь фильтр... И что вы думаете - тоже умерло, остался BSD sockets.
В которых не будет реализовано 99% того, что нужно. Функциональность упадёт, совместимость разрушится в обе стороны. Или опять же всё свалят на библиотеки. Вангую, что этим и закончится, после многолетнего бардака.
Спасибо, не надо нам такого "счастья".
Потому что у них одинаково всё, кроме адресов. И то, адреса пересекаются (в Linux v6 слушающий сокет автоматом цепляется и на v4, если не отменить). Когда 99.99+% функциональности одинаково, разделение становится искусственным.
Ну а в BSD sockets это различие загнали под одно поле параметра функций bind() и connect(), избавившись от необходимости дублирования всего остального.
И различие исчезает с момента коннекта.
Я начинаю недоумевать, как вы программируете с таким нежеланием понимать и поддерживать абстракции.
Ваша идея понятна. Но принять я её такую не могу: просто нет смысла усложнять на ровном месте то, что делается проще и универсально - и, главное, с возможностью развития.
Сравните это с ООП. Какой бы вариант его ни был, он старается поддерживать LSP, который есть принцип совместимости интерфейсов и определённых ожиданий контракта от прочих участников. С ним я могу применять любую реализацию того, что отвечает интерфейсу и контракту. Вы же требуете определённой фиксированной реализации. Зато на шелл ложится вся ноша разбора, как писать в файл, как в сокет... а где граница? Почему в сокет, который связан с сервером в локалке, и сервером на другом континенте, пишем одинаково? Там ведь тоже различие в деталях, типа обычной round-trip задержки, которая кому-то существенна.
Вы не разрешаете абстрагироваться от излишнего. Индустрия уже показала свой выбор.
Пишется номер начального кластера. Это подходит под критерий уникальности.
Нет, хранит не он. Он их просто представляет в некотором удобном для чего-то виде. Пусть рядом будут uevent_json и uevent_cbor, где то же самое, но в другом формате; они меняться будут синхронно.
Почему? В том же адресном пространстве - по крайней мере на x86 и ARM. Просто юзерленду недоступен именно как содержимое памяти, ещё и представлен в каких-то запутанных структурах.
Видите, вот стали чуть внимательнее смотреть в детали - и всё определение поплыло.
Но его продолжают именовать file descriptor. А не, как в Windows, "handle" неважно чего.
Меня уже подводит память, но кажется, что основная дискуссия происходила лет на 5 раньше. Это уже повторная, в сообщениях есть явное упоминание про это. Я пытался искать и не нашёл. Но гугл хранит не все сообщения, или даёт плохой поиск по ним.
Но на эти тоже можно частично опереться.