В процессе работы над ОС Фантом, которая вообще не Юникс никаким местом, мне, тем не менее, захотелось сделать в нём Unix-compatible подсистему. Не то, чтобы прямо POSIX, но что-то достаточно близкое. Отчасти из любопытства, отчасти для удобства, отчасти как ещё один migration path. (Ну и вообще было интересно, насколько трудно написать простенький Юникс «из головы».) В качестве цели номер 1 была поставлена задача запустить quake 1 for Unix, которая и была достигнута.

В процессе, естественно, появились open/close/r/w/ioctl, и появилось ощущение, что последний неприлично, постыдно устарел. В качестве упражнения для размятия мозга я реализовал (в дополнение к обычному ioctl) некоторый альтернативный API, который бы позволил управлять свойствами устройств более гибким и удобным с точки зрения пользователя способом. Этот API, конечно, имеет свои очевидны минусы, и, в целом, эта статья — RFC, aka request For Comments.

Итак, API на уровне пользователя:

// returns name of property with sequential number nProperty, or error
errno_t listproperties( int fd, int nProperty, char *buf, int buflen );

errno_t getproperty( int fd, const char *pName, char *buf, int buflen );
errno_t setproperty( int fd, const char *pName, const char *pValue );


Правила:

  1. Никаких дефайнов с номерами, только имена.
  2. Никаких бинарных данных, только строки


Это не очень эффективно, но хочется предположить, что установка/чтение свойств — процесс редкий, и потому упираться в его скорость смысла немного, да и само переключение контекста при вызове стоит немало.

Можно несколько оптимизировать интерфейс, например, так:

// returns name of property with sequential number nProperty, or error
errno_t listproperties( int fd, int nProperty, char *buf, int buflen );

// returns property id by name
errno_t property_by_name( int fd, int *nProperty, const char *name );


errno_t getproperty( int fd, int nProperty, char *buf, int buflen );
errno_t setproperty( int fd, int nProperty, const char *pValue );

// fast lane

errno_t getproperty_i32( int fd, int nProperty, int32_t *data );
errno_t setproperty_i32( int fd, int nProperty, int32_t data );


Эта схема для единичного свойства не медленнее, чем ioctl.

Чем она хороша: можно сделать общую команду (напр mode), которая управляет параметрами любого драйвера, не зная о нём ничего — mode /dev/myCrazyDriver выдаст список свойств, а mode /dev/myCrazyDriver name val установит свойство name в значение val.

Реализация внутри драйвера (для которой, конечно, в ядре есть соответствующая незамысловатая инфраструктура) тоже несложна:

static property_t proplist[] =
{
    { pt_int32, "leds", 0, &leds, 0, (void *)set_leds, 0, 0 },
};


Эта строка описывает свойство, которое имеет тип int32, лежит в переменной leds, и если оно изменилось, то надобно вызвать функцию set_leds.

В реальности кроме pt_int32 родились только pt_mstring — malloc'ed strings, что тоже довольно удобно.

Вообще, надо сказать, темпы развития API классического Юникса меня несколько удивляют — есть ощущение, что никто им всерьёз не занимается, хотя, кажется, определённая систематизация ему явно не повредит.

У меня есть ещё несколько дополнений к традиционному POSIX-у, которые мне, Юниксоиду с 30-летним стажем, кажутся просто очевидными. Будет время — опубликую.

Ссылки на реализацию (кожа и кости, но всё же):



Кажется очевидным, но упомяну, что механизм, в принципе, можно применять для любых сущностей, вовсе не только для устройств.

Комментарии (58)


  1. RealFSA
    25.04.2016 18:55

    Хм. Осталось сделать в модулях ядра Linux соответствующие «стандартные» ioctl-ы, и можно продвигать обратную совместимость с ОС Фантом. :)


    1. dzavalishin
      25.04.2016 19:25

      Верно. Но есть более полезный (и более простой организационно) заход для этого упражнения. Напишу позже.


  1. jcmvbkbc
    25.04.2016 19:02
    +2

    хочется предположить, что установка/чтение свойств — процесс редкий

    Установка/чтение свойств — может быть и редкий процесс. Но ioctl — это же не только установка/чтение свойств. Это же универсальный интерфейс для выполнения драйвером обслуживающим файл произвольных действий с передачей произвольных данных.

    можно сделать общую команду (напр mode), которая управляет параметрами любого драйвера, не зная о нём ничего

    Устройства, а не драйвера?

    static property_t proplist[] =
    {
        { pt_int32, "leds", 0, &leds, 0, (void *)set_leds, 0, 0 },
    };
    ...
    
    static void set_leds(void)
    ...
    

    А как set_leds узнает, которому из устройств обслуживаемых драйвером предназначена команда?


    1. dzavalishin
      25.04.2016 19:16

      он же на fd меппится. что open позволяет открыть, то и предмет. захочет драйвер дать открыть не устройство, а себя вообще — будут проперти драйвера.


    1. dzavalishin
      25.04.2016 19:19

      Это же универсальный интерфейс для выполнения драйвером обслуживающим файл произвольных действий с передачей произвольных данных.


      Увы, да. Можно и это поддержать, сделав какой-нибудь ioread( fd, ioctl_id, void *, size_t ), но, кажется, перебор.


      1. dzavalishin
        25.04.2016 19:23

        Кстати, разумный механизм — это через ioctl только переключать стейт, а ввод-вывод всё равно делать через read/write.

        set_property( fd, "iomode", "palette" ); 
        write( fd, &palette, sizeof(palette) );
        


        1. 0xd34df00d
          25.04.2016 19:26
          +4

          Ой, стейтфул, ой, глобальные переменные, только в профиль, ой, а что если второй поток рядом сделает другой set_property?


          1. dzavalishin
            26.04.2016 14:05

            Это тоже правда, но в этом смысле весь позикс — одна сплошная дыра. Впрочем, не давайте fd другому потоку, и всё. Ну или мьютекс возьмите — многопоточное программирование предполагает управление параллельным доступом через примитивы синхронизации, так или иначе.


            1. 0xd34df00d
              26.04.2016 14:51
              +1

              Ну так если у вас есть шанс спроектировать новый API, то почему бы не воспользоваться этим шансом и не сделать сразу хорошо?

              Чем меньше точек синхронизации торчит в пользовательский код, тем лучше. Чем меньше глобального стейта, в конце концов, тем лучше.


              1. dzavalishin
                26.04.2016 14:56

                согласен


        1. jcmvbkbc
          25.04.2016 19:34

          Мне кажется, что современный тренд в том, чтобы через ioctl настраивать прямую связь юзерспейса с железом — IOMMU, аппаратные очереди в адресном пространстве процесса, а дальше они сами разберутся, без ядра.


          1. lorc
            25.04.2016 19:38

            Ну это наверное ближе к духу QNX, чем Linux.


            1. jcmvbkbc
              25.04.2016 19:42

              Это ближе к духу OpenOnload, HSA, OpenCL и т.п., всё оно работает на линуксе.


              1. lorc
                25.04.2016 19:53

                Ну да, я как раз хотел сказать что такие штуки в основном используются для общения с GPU. Это в общем нарушает принципы UNIX, и делается в основном ради увеличения производительности в ущерб стабильности.


                1. jcmvbkbc
                  25.04.2016 19:57

                  Это в общем нарушает принципы UNIX

                  Какие именно и каким образом?

                  делается в основном ради увеличения производительности в ущерб стабильности

                  Ради увеличения производительности — да, в ущерб стабильности — нет.


                  1. lorc
                    25.04.2016 20:09

                    Какие именно и каким образом?

                    Унифицированный доступ к устройствам. Если взять например framebuffer device, то любой драйвер поддерживает стандартный API + какие-то свои расширения. А значит моя программа может открыть /dev/fb0, замапить его себе в память и не задумываясь больше ни о чем работать-работать-работать.
                    Если же мне нужны вычисления на GPU — мне надо недостаточно открыть /dev/dri/card0. Мне надо взять условный libopencl для моей конкретной видеокарты, потому что именно он знает как правильно замапить память видеокарты и как посылать ей комманды которые специфичны именно для неё.

                    Ради увеличения производительности — да, в ущерб стабильности — нет.

                    Ну лично мне неюутно от мысли что любое приложение в юзерспейсе может слать любые команды моей видеокарте. Ведь в данном случае ядро не может контролировать что делается с видеокартой.


                    1. jcmvbkbc
                      25.04.2016 20:37

                      Если же мне нужны вычисления на GPU — мне надо недостаточно открыть /dev/dri/card0. Мне надо взять условный libopencl для моей конкретной видеокарты, потому что именно он знает как правильно замапить память видеокарты и как посылать ей комманды которые специфичны именно для неё.

                      Но вы же не пытаетесь выводить во фреймбуфер текстовым редактором или командой sed? Условный libopencl — это такой же инструмент для вычислений на gpu. При желании из него можно сделать классическую программу-фильтр, принимающую на вход текст кернела и входные данные и выводящую результаты.

                      Ну лично мне неюутно от мысли что любое приложение в юзерспейсе может слать любые команды моей видеокарте. Ведь в данном случае ядро не может контролировать что делается с видеокартой.

                      Частично может — с помощью правильно сконфигурированного IOMMU оно может защитить память не принадлежащую процессу от доступа со стороны видеокарты от имени и по поручению этого процесса. В остальном приложение взаимодействует, в основном, с фирмварью, которую можно считать специализированным «ядром» для видеокарты.


                      1. lorc
                        25.04.2016 20:59

                        Но вы же не пытаетесь выводить во фреймбуфер текстовым редактором или командой sed?

                        Я могу как минимум попытаться. Например я похожим образом несколько раз проверял, работает ли фрейбуфер в моем устройстве или определял какой файл фрейбуффера какому экрану соотвествует. Я даже могу сделать скриншот с помощью команды cat.

                        Частично может — с помощью правильно сконфигурированного IOMMU оно может защитить память не принадлежащую процессу от доступа со стороны видеокарты от имени и по поручению этого процесса.

                        Да, IOMMU (там где оно есть) может защитить память других процессов. Но если приложение решит поиграться с клоками видеокарты, например? Или с управлением скоростью куллеров? Фирмварь видеокарты же не сможет определить от кого приходят команды.

                        Я просто веду к тому, что драйвера стали вылазить за пределы ядра. Пропал общий интерфейс. Сначала это произошло с принтерами и сканерами, из-за чего мы имеем огромный CUPS и несколько алтернативных паков «драйверов» к нему. Теперь то же самое происходит с GPU.

                        Кстати, вот ещё пример почему это плохо. В ядре есть CryptoAPI, который позволяет добавлять свои модули, например для аппаратного ускорения шифрования. Допустим, я хочу использовать OpenCL что бы ускорить AES. Если бы весь интерфейс к видеокарте жил в ядре — проблем бы небыло. Я пишу код для GPU, мой модуль аттачится к DRM, выставляет наружу интерфейс для CryptoAPI и все счастливы. Ядро (и все драйвера) может шифровать с аппаратным ускорением, юзерспейс может шифровать с аппаратным ускорением, все счастливы.
                        При текущем же дизайне мы максимум что можем сделать — это модуль для openssl. Все ядерные клиенты остаются в пролете.


                        1. jcmvbkbc
                          25.04.2016 21:39
                          +1

                          Я даже могу сделать скриншот с помощью команды cat.

                          Точно так же вы можете запустить какой-нибудь стандартный 2х2=4 на gpu.

                          Но если приложение решит поиграться с клоками видеокарты, например?

                          Не решит, не даст ему никто.

                          Фирмварь видеокарты же не сможет определить от кого приходят команды.

                          Сможет. Она же участвует в создании пользовательских очередей. Там же весь дизайн нацелен на то, чтобы протащить нужный контекст до нужного места. Без этого ни один здравомыслящий архитектор не предложил бы такую технологию.

                          Кстати, вот ещё пример почему это плохо. В ядре есть CryptoAPI, который позволяет добавлять свои модули, например для аппаратного ускорения шифрования.

                          У линуксового CryptoAPI не файловый интерфейс. См. http://lwn.net/Articles/410763/, особенно комментарии про socat и т.п.

                          Ядро (и все драйвера) может шифровать с аппаратным ускорением, юзерспейс может шифровать с аппаратным ускорением, все счастливы.

                          И тут не всё гладко. Некоторым драйверам (PPTP например) требуется синхронный интерфейс, потому что они хотят заниматься криптографией из SoftIRQ. Не всякий криптопровайдер на это способен.

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

                          Не всё укладывается в общий файловый интерфейс, и не всё что удаётся уложить — красиво и эффективно.


                          1. dzavalishin
                            26.04.2016 17:17
                            +2

                            Кажется, любой юниксосрач можно завершить этой мудрой мыслью:

                            Не всё укладывается в общий файловый интерфейс, и не всё что удаётся уложить — красиво и эффективно.


                            :)


          1. dzavalishin
            26.04.2016 14:07

            в принципе, да — но, всё же, смысл существования ОС — в виртуализации железа. смысл opengl — обобщить и унифицировать интерфейсы и capabilities железа. обойти его — и ОС превращается в толстый и дорогой MS DOS.


        1. MacIn
          25.04.2016 19:40

          Зачем, если технически это одно и то же: пробросить из/в юзерспейс какие-то буфера, их размеры и команду. А там уж — в зав-ти от вида команды — будь то rw или ioctl трактуем содержимое буфера.


      1. lorc
        25.04.2016 19:36
        +1

        Ну тогда надо будет делать пару ioread/iowrite что нифига не удобно, потому что есть немало вызовов где делается и чтение и запись. Например, педерать параметры команды и получить обратно какие-то результаты. Делать ioread и затем iowrite не выход, потому что появляется состояние и все связанные с ним проблемы. Поэтому опять приходим к нужности единого вызова ioctl. Короче, Томпсон, Ритчи и Ко были не дураки.


        1. MacIn
          25.04.2016 19:42
          +2

          Или тот же самый DeviceIoControl:

          BOOL WINAPI DeviceIoControl(
            _In_        HANDLE       hDevice,
            _In_        DWORD        dwIoControlCode,
            _In_opt_    LPVOID       lpInBuffer,
            _In_        DWORD        nInBufferSize,
            _Out_opt_   LPVOID       lpOutBuffer,
            _In_        DWORD        nOutBufferSize,
            _Out_opt_   LPDWORD      lpBytesReturned,
            _Inout_opt_ LPOVERLAPPED lpOverlapped
          );
          
          


          1. lorc
            25.04.2016 19:53
            +1

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


      1. Shamov
        26.04.2016 11:24

        Не перебор. Это критически важный функционал. Любой драйвер, цепляющийся к сети и регулирующий прохождение трафика, предполагает, что в него во время настройки будет загружена куча правил. И эти правила не имеют имён. В лучшем случае они имеют генерируемые на лету числовые идентификаторы, в худшем — каждое правило идентифицируется лишь собственным содержанием.


  1. 0xd34df00d
    25.04.2016 19:09
    +1

    В дефайнах и прочих енамах хорошо то, что опечатку поймает компилятор. Тут опечатку поймает в лучшем случае рантайм, в худшем — никто. Что, если у вас опечатка в имени свойства в каком-нибудь редком control flow path, например, в коде обработки ошибок?


    1. dzavalishin
      25.04.2016 19:21
      -7

      Это правда.

      Но посмотрите на жизнь с другой стороны.

      Языка Си больше нет.

      Вся современная разработка — переносимые языки с динамическим рантаймом, и никаких дефайнов там нет. Они всё равно мепятся в ioctl через ж. автогеном, и всё равно в рантайме.


      1. 0xd34df00d
        25.04.2016 19:25
        +4

        И компиляторов нет?

        Пишу на C++ (поэтому изначально хотел предложить enum class) и на Haskell. Разработка вроде даже современная, правда, не очень лоу-левел, не на уровне ядра, от ядра мне максимум прямой вызов mmap нужен. Так что зря вы так, не вся.


        1. dzavalishin
          26.04.2016 14:20

          Надеюсь, Вы знаете, на кой хрен Вы до сих пор с С++. Я вижу только две причины: исторические наслоения и те 10% кода, которые правда надо оптимизировать.


          1. 0xd34df00d
            26.04.2016 14:52
            +1

            О, языкосрачик А какой язык вы предлагаете?


            1. dzavalishin
              26.04.2016 17:12
              +2

              Решение требует задачи. Нет смысла выбирать ЯП абстрактно.

              Однако, как 20 лет назад был универсальный ответ «не знаешь, на чём писать — пиши на Си (++)», так сегодня дефолтным ЯП является Ява, если ты юниксоид и С#, если ты хочешь жить и умереть в виндах. Инфраструктура поддержки этих двух ЯП несравнима ни с чем (включая си).

              Если тебе нужно скриптик или страничку — похрен. Хоть на коболе.


              1. 0xd34df00d
                26.04.2016 17:20

                На современных плюсах писать как-то выразительнее, быстрее и приятнее, чем на Яве.


                1. dzavalishin
                  26.04.2016 18:09
                  -1

                  Вы о себе или об индустрии? Строка кода на С++ в 4-5 раз дороже строки на Яве.


                  1. 0xd34df00d
                    26.04.2016 18:12
                    +1

                    О себе, конечно. Вы ж спрашивали, на кой хрен я до сих пор с С++.


                1. MacIn
                  26.04.2016 18:32

                  Можно пример-два? Не срача ради. ПМСМ, чем дальше, тем меньше разницы.


                  1. 0xd34df00d
                    26.04.2016 18:34
                    +1

                    Да хотя бы auto.


                    1. MacIn
                      26.04.2016 18:38

                      Ага, как раз про ауто думал сегодня, читая вот эту статью:
                      https://habrahabr.ru/company/luxoft/blog/278313/


      1. stepik777
        25.04.2016 21:51
        +3

        > Вся современная разработка — переносимые языки с динамическим рантаймом

        Что? Это только какая-то часть современной разработки. Возьмите, например, любую современную AAA игру, она написана на C++.


        1. dzavalishin
          26.04.2016 14:16

          Она написана на GPU, который занимается графикой, и на динамическом языке, на котором пишут AI. Си там — тонкая прослойка между ними, которая написана на Си только в силу стереотипности мышления разрабов. Технически в этом давно нет смысла.

          Скучно это. Я в 90-х наблюдал истерику разработчиков на ассемблере, которым говорили, что асм умер и всё пишут на си. Потом истерику сишников с переходом на яву. Сегодня истерика явистов с переходом на ФП языки.

          (И да, если вы ещё истерите по поводу фразы «си умер в пользу явы», вы проспали поколение — уже пора рассказывать, что ява — это легаси.)


          1. terryP
            27.04.2016 12:50

            Сегодня истерика явистов с переходом на ФП языки.

            Хде истерика-то? На самом деле, явистам пофиг, часть ФП языков приходит в JVM экосистему, то есть является ещё одним инструментов явистов, которым это интересно, а большая часть существующих проектов никогда с явы не слезет, а значит тем явистам, которым не интересно на ближайшие лет 10-15 работы на явы не сильно убавиться. Да, и большинство явистов признает недостатки явы (просто она довольно удобна для некоторых задач энтерпрайза), так что каких-то истерик не ждите. Ну и потихонку ФП идет в java, я говорю о ряде библиотек, которые позволяют вносить ФП конструкции в джаву.


            1. dzavalishin
              27.04.2016 16:58

              Всё верно. Но иногда люди эмоциональны. :)


      1. AlexSky
        26.04.2016 01:22
        +1

        Черт, а я уже столько лет пишу на несуществующем языке.
        Надо завтра черкануть в мэйлинг лист линуксового ядра, чтобы тоже прекращали использовать несуществующий язык и переходили на РНР.


        1. dzavalishin
          26.04.2016 14:45
          +1

          Я всего лет 7 назад помогал в исправлении ошибки в коде на языке Кобол. Кобол. Знаете такой? Джермейн, IBM360, середина прошлого века, слышали? Работает! Используют!

          Так и Си.

          Некоторым не везёт. Некоторые балдеют. Я вот пишу на Си уже тридцать лет, нехреново умею это делать и определённое удовольствие от этого испытываю.

          Но не нужно путать неизбежность (хрен куда Линукс с Си спрыгнет, это ясно), собственные сексуальные предпочтения (писать на си — разновидность онанизма) и ЦЕЛЕСООБРАЗНОСТЬ.

          Писать на Си в 99% случаев — НЕЦЕЛЕСООБРАЗНО. Потому что 3.14здец как дорого и 3.14здец как ненадёжно. Это я говорю вам как человек, который этим языком занимается 30 (тридцать) лет и как создатель нескольких крупнейших софтверных систем в России, типа Я.Маркета и инфраструктуры портала Яндекса, Юлмарта и ещё с сотни проектов помельче.

          И как человек, написавший ОС почти в одно рыло.

          Так вот — почти ПОЛОВИНА кода ОС посвящена заморочкам, которые из Си делают что-то жизнеспособное.

          Всякие референс каунты (ручной ad hoc garbage collection), очереди, списки, эмуляции виртуальных методов, мемберофы, проверки и затычки.

          Другое дело, что в некоторых проектах деваться тупо некуда — gcc поддержан на таком количестве платформ, что его ещё долго не получится забыть. Ну и есть реально тесные платформы типа avr, при паре килобайт памяти не разгуляешься.

          Но это всё — уже история. Как Кобол. Лямбды уверенно вытесняют указатели на функцию.


          1. prefrontalCortex
            26.04.2016 22:45

            Всякие референс каунты (ручной ad hoc garbage collection)
            По-вашему, ОС с ядром на языке со сборкой мусора будет в чём-то лучше конкурентов? Оберон вон как-то не взлетел.


  1. MacIn
    25.04.2016 19:27

    Это не очень эффективно, но хочется предположить, что установка/чтение свойств — процесс редкий, и потому упираться в его скорость смысла немного, да и само переключение контекста при вызове стоит немало.

    В принципе, если properties метод — просто обертки над ioctl кодами, то это не проблема — в случае необходимости можно реализовать вызов напрямую.


  1. MichaelBorisov
    25.04.2016 22:55
    +3

    Никаких дефайнов с номерами, только имена.

    Никаких имен. Только GUID, только хардкор.

    Применение строковых имен чревато их конфликтами, перепутыванием прописных и строчных букв, потерей пробелов, знаков препинания и т.д. Кроме того, обработка C-строк менее эффективна, чем обработка данных фиксированной длины, таких как GUID.
    Никаких бинарных данных, только строки

    Ну и это ни к чему. Появляется парсинг строк, диагностика синтаксических и прочих ошибок, уязвимости парсера. Эта современная мода на текстовое представление всего и вся — она годится только для малых объемов данных и в тех случаях, где производительность некритична. Даже XML-файл прочитать на несколько десятков мегабайт может не каждая библиотека.


  1. vanxant
    25.04.2016 23:05

    Ну я бы не сказал, что ioctl прям вот всегда процесс редкий. Если какой-нибудь сервер принимает кучу коротких входящих соединений, то там соотношение Ioctl и fread вполне может быть близко к 1/1.


  1. lumag
    26.04.2016 02:33

    Properties получаются альтернативой sysfs (где тоже строковые ключи и значения), а не ioctl.


    1. dzavalishin
      26.04.2016 15:00

      реализую похожую модель, но в приложении к другому объекту.
      с другой стороны, возможно, правильная схема именно fs:

      /dev/tty0
      /dev/tty0.speed
      /dev/tty0.stop_bits


  1. alecv
    26.04.2016 11:44
    +2

    Ага, ага. Понятно во что оно мигрирует:
    — Сделать «невидимые» атрибуты, например начинающиеся с _ или $ в стиле MS
    — Сделать систему безопасности, каждый атрибут должен иметь список на чтение-запись-просмотр
    — Сделать иерархическую систему атрибутов, объединив похожие атрибуты в каталоги атрибутов по типу Registry
    — Невидимость атрибутов можно реализовать через систему безопасности атрибутов и каталоги атрибутов конечно же
    — Сделать «метаатрибуты», в которых будут хранится свойства атрибутов, в частности их тип, по образцу SNMP OID

    P.S. В принципе тут уже упомянули sysfs. Надо только добавить, что заниматься этим должен обязательно systemd.

    [sarcasm mode off]


    1. dzavalishin
      26.04.2016 14:10

      ls /proc

      это, в общем, тот же путь, да.


      1. lumag
        26.04.2016 14:39

        /proc — помойка, в той части, которая к PID не привязана. Раскидывание свойств по устройствам — это sysfs.


        1. dzavalishin
          26.04.2016 14:47

          Любой нейминг без централизованного управления приходит в состояние помойки. Вопрос времени. :)


          1. lumag
            26.04.2016 15:31

            В целом — согласен. Есть разница в том, что sysfs — это ,, проекция'' реальных структур ядра в файловую систему. Т.е. основа в виде каталогов всегда будет осмысленной. А в /proc каждый кидал что и как хотел.


            1. dzavalishin
              26.04.2016 17:08

              Да, это помогает. Должно, по крайней мере. Семантика диктует структуру.


  1. monah_tuk
    27.04.2016 17:12

    AVDictionary из FFmpeg вспомнились и сразу проблемы (которые, в принципе, все выше перечислены):


    • опечатки, как в именах, так и в значениях
    • конфликт имён и типов значений
    • отсутствие проверки со стороны компилятора и
    • как следствие — валится в рантайме в самый неподходящий момент

    Кстати, интерфейс словаря можно и тут добавить — что бы за вызов сразу пачку параметров изменить/получить. В FFmpeg после вызова в словаре остаются записи, которые примениться не смогли.


    1. dzavalishin
      27.04.2016 23:15

      проблема только с именами, и то — частичная. рантайм вернёт ошибку. Всё остальное есть у ioctl в полный рост. никто и никак не проверит бинарный номер и формат структуры. а так же выравнивание полей.