Почему в ядре Linux более 15 миллионов строк кода? [закрыто]

109

Каково содержание этой монолитной кодовой базы?

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

Какие исторические и текущие причины драйверы включены в базу кода ядра?

Включают ли эти 15 с лишним миллионов строк каждый драйвер для каждого компонента оборудования? Если это так, то возникает вопрос, почему драйверы встроены в ядро, а не в отдельные пакеты, которые автоматически определяются и устанавливаются из идентификаторов оборудования?

Является ли размер базы кода проблемой для устройств с ограниченным хранилищем или памятью?

Кажется, это увеличило бы размер ядра для устройств ARM с ограниченным пространством, если бы все это было встроено. Много ли строк отбраковано препроцессором? Назовите меня сумасшедшим, но я не могу представить себе машину, требующую столько логики для запуска, как я понимаю, роли ядра.

Есть ли доказательства того, что размер будет проблемой через 50 с лишним лет из-за его, казалось бы, постоянно растущей природы?

Включение драйверов означает, что оно будет расти по мере изготовления оборудования.

РЕДАКТИРОВАТЬ : Для тех, кто думает, что это природа ядер, после некоторых исследований я понял, что это не всегда. Ядро не обязательно должно быть таким большим, так как микроядро Карнеги-Меллона было приведено в качестве примера «обычно под 10000 строк кода».

Джонатан
источник
9
Еще в 2012 году было более 5 миллионов строк только для водителей. 1,9 миллиона строк для поддержки различных процессорных архитектур. Больше информации h-online.com/open/features/…
Стив
11
Да, я написал код для компилятора, лексического анализатора и генератора байтового кода для языка, и он был полностью завершен плюс рекурсия, и он не занимал 10 000 строк.
Джонатан
5
(посмотрел на него сейчас, было около 2700 строк)
Джонатан
4
Вы должны скачать и настроить, make menuconfigчтобы увидеть, сколько кода можно включить / отключить до сборки.
Кейси
6
@JonathanLeaders: Я закончил тестирование полных компиляторов для языков, подобных LISP, менее чем в 100 строк, с тестовыми программами, отображающими Мандельброта. Всегда зависит.
Френель

Ответы:

43

Драйверы поддерживаются в ядре, поэтому, когда изменение ядра требует глобального поиска и замены (или поиска и изменения вручную) для всех пользователей функции, это делает человек, который вносит изменения. Обновление вашего драйвера людьми, вносящими изменения в API, является очень хорошим преимуществом, вместо того, чтобы делать это самостоятельно, когда он не компилируется в более новом ядре.

Альтернатива (то, что происходит с драйверами, поддерживаемыми вне дерева), заключается в том, что патч должен быть повторно синхронизирован его сопровождающими, чтобы не отставать от любых изменений.

Быстрый поиск вызвал дискуссию по поводу разработки драйверов внутри дерева и вне дерева .

Поддержание Linux в основном заключается в сохранении всего в основном репо. Сборка небольших урезанных ядер поддерживается параметрами конфигурации для управления #ifdefs. Таким образом, вы можете создавать крошечные урезанные ядра, которые компилируют только крошечную часть кода во всем репо.

Широкое использование Linux во встраиваемых системах привело к лучшей поддержке отказа от вещей, чем Linux имел годы назад, когда дерево исходных текстов ядра было меньше. Супер-минимальное ядро ​​4.0, вероятно, меньше супер-минимального ядра 2.4.0.

Питер Кордес
источник
4
Теперь ЭТО имеет смысл для меня, почему логично собрать весь код вместе, это экономит человеческие часы за счет ресурсов компьютера и чрезмерных зависимостей.
Джонатан
8
@JonathanLeaders: да, это позволяет избежать гниения для водителей с не очень активным обслуживанием. Также возможно полезно иметь весь код драйвера при рассмотрении изменений ядра. Поиск во всех вызывающих программах какого-либо внутреннего API может привести к тому, что драйвер будет использовать его так, как вы и не думали, что может повлиять на изменение, о котором вы думали.
Питер Кордес
1
@JonathanLeaders приходят на xd, как будто эти дополнительные строки занимают намного больше места, в современных измерениях установки его на ПК.
Junaga
3
@Junaga: вы понимаете, что Linux очень переносим и масштабируем, верно? Потеря 1 МБ постоянно используемой памяти ядра во встроенной системе 32 МБ является большой проблемой. Размер исходного кода не важен, но размер скомпилированного двоичного файла все еще важен. Память ядра не выгружается, поэтому даже с пространством подкачки вы не сможете ее вернуть.
Питер Кордес
1
@ Рольф: Это большой, но это не спагетти. В настоящее время он достаточно хорошо спроектирован без двусторонних зависимостей между основным кодом и драйверами. Драйверы могут быть оставлены без нарушения ядра ядра. Когда внутренняя функция или API подвергается рефакторингу, поэтому драйверы должны использовать его по-другому, драйверы могут нуждаться в замене, но это нормально для рефакторинга.
Питер Кордес
79

Согласно Cloc, работающему против 3.13, Linux содержит около 12 миллионов строк кода.

  • 7 миллионов LOC в драйверах /
  • 2 миллиона LOC в арке /
  • всего 139 тыс. LOC в ядре /

lsmod | wc на моем ноутбуке Debian показано 158 модулей, загруженных во время выполнения, поэтому динамическая загрузка модулей - это популярный способ поддержки аппаратного обеспечения.

Надежная система конфигурации (например make menuconfig) используется для выбора кода для компиляции (и, более того, какой код не компилировать). Встраиваемые системы определяют свои собственные .configфайлы только с помощью аппаратной поддержки, которая им нужна (включая поддержку аппаратного обеспечения, встроенного в ядро ​​или в виде загружаемых модулей).

drewbenn
источник
3
подсчета модулей недостаточно, многое может быть встроено в конфигурацию
Alex
5
Я думаю, что из этого мы можем сделать вывод, что ядро ​​Linux огромно, потому что оно поддерживает всевозможные конфигурации устройств, а не потому, что оно чрезвычайно сложно. Мы видим здесь, что очень мало из 15-метровых линий фактически используется. Хотя, как и почти все, это может быть слишком сложно, по крайней мере, мы можем спать по ночам, зная, что это разумно
Джонатан
2
@JonathanLeaders: Да, а также модули для странных устройств, есть модули для скрытых файловых систем, сетевых протоколов и т. Д.
psmears
6
@JonathanLeader Я помню, когда Linux запускался - даже заставить установщик работать (если у него даже был установщик!) Было огромной болью - все еще есть некоторые дистрибутивы, где вам нужно выбрать драйвер мыши вручную. Создание таких вещей, как создание сетей или, не дай бог, X-Window, работа, было обрядом обряда. При первой установке Red Hat мне пришлось написать собственный графический драйвер, потому что было доступно только три (!) Драйвера. Работа с базовыми компонентами по умолчанию является признаком зрелости, и, очевидно, вы можете позволить себе гораздо больше настроек встроенной системы, в которой всего несколько комбинаций HW.
Luaan
2
@JonathanLeaders Как я думаю, вы поняли, что LOC в источнике более или менее не имеет значения. Если вы хотите узнать, сколько памяти использует ядро, есть гораздо более прямые способы .
Златовласка
67

Для любого любопытного, вот разбивка строки счета для зеркала GitHub:

=============================================
    Item           Lines             %
=============================================
  ./usr                 845        0.0042
  ./init              5,739        0.0283
  ./samples           8,758        0.0432
  ./ipc               8,926        0.0440
  ./virt             10,701        0.0527
  ./block            37,845        0.1865
  ./security         74,844        0.3688
  ./crypto           90,327        0.4451
  ./scripts          91,474        0.4507
  ./lib             109,466        0.5394
  ./mm              110,035        0.5422
  ./firmware        129,084        0.6361
  ./tools           232,123        1.1438
  ./kernel          246,369        1.2140
  ./Documentation   569,944        2.8085
  ./include         715,349        3.5250
  ./sound           886,892        4.3703
  ./net             899,167        4.4307
  ./fs            1,179,220        5.8107
  ./arch          3,398,176       16.7449
  ./drivers      11,488,536       56.6110
=============================================

driversвносит большой вклад в количество строк.

user3276552
источник
19
Это интересно. Еще более интересны потенциально слабые места в коде, где программисты были недовольны:grep -Pir "\x66\x75\x63\x6b" /usr/src/linux/ | wc -l
jimmij
4
@jimmij '\ x73 \ x68 \ x69 \ x74' может быть более распространенным явлением в соответствии с этим новаторским (если немного датированным) исследованием .
Ник Т
3
Случайный факт: документация находится в папке, которая ближе к 600 000 LOC, оцененных ОП.
Davidmh
1
./documentationимеет более 500 000 строк кода? ....что?
C_B
1
@ drewbenn Я понял это больше как "документация не пуста?"
Изката
43

Пока что ответы кажутся «да, кода много», и никто не решает вопрос с наиболее логичным ответом: 15M +? И ЧТО? Какое отношение имеет 15 миллионов строк исходного кода к цене рыбы? Что делает это таким невообразимым?

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

  • Не все скомпилировано. Система сборки Kernel позволяет быстро определять конфигурации, которые выбирают наборы исходного кода. Некоторые экспериментальные, некоторые старые, некоторые просто не нужны для каждой системы. Посмотрите на /boot/config-$(uname -r)(на Ubuntu), make menuconfigи вы увидите, сколько исключено.

    И это настольный дистрибутив с переменной целью. Конфигурация для встроенной системы будет включать только то, что ей нужно.

  • Не все встроено. В моей конфигурации большинство функций ядра построены в виде модулей:

    grep -c '=m' /boot/config-`uname -r`  # 4078
    grep -c '=y' /boot/config-`uname -r`  # 1944
    

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

  • Модули загружаются динамически. Даже когда в системе есть тысячи доступных ей модулей, система позволит вам загружать именно то, что вам нужно. Сравните результаты:

    find /lib/modules/$(uname -r)/ -iname '*.ko' | wc -l  # 4291
    lsmod | wc -l                                         # 99
    

    Почти ничего не загружается.

  • Микроядра не одно и то же. Всего 10 секунд просмотра ведущего изображения на странице Википедии, на которую вы ссылаетесь , покажут, что они созданы совершенно по-другому.

    Драйверы Linux являются внутренними (в основном динамически загружаемыми модулями), а не пользовательским пространством, и файловые системы также являются внутренними. Почему это хуже, чем использование внешних драйверов? Почему микро лучше для вычислений общего назначения?


Комментарии снова подчеркивают, что вы не получаете это. Если вы хотите развернуть Linux на дискретном оборудовании (например, в аэрокосмическом пространстве, TiVo, планшете и т. Д.), Вы конфигурируете его для сборки только необходимых вам драйверов . Вы можете сделать то же самое на вашем рабочем столе с make localmodconfig. В итоге вы получите крошечную сборку ядра с нулевой гибкостью.

Для таких дистрибутивов, как Ubuntu, допустим один пакет ядра размером 40 МБ. Нет, откажитесь от этого, на самом деле, это предпочтительнее сценария массового архивирования и загрузки, в котором хранится более 4000 плавающих модулей в виде пакетов. Он использует меньше дискового пространства для них, легче упаковывать во время компиляции, легче хранить и лучше для своих пользователей (у которых есть система, которая просто работает).

Будущее тоже не проблема. Скорость процессора, плотность диска / цены и пропускная способность кажутся намного быстрее, чем рост ядра. Пакет Kernel 200 МБ за 10 лет не станет концом для мира.

Это также не улица с односторонним движением. Код выгоняется, если он не поддерживается.

Oli
источник
2
В основном это касается встраиваемых систем. Как вы показываете, у вас есть 4000 модулей, которые не используются в вашей собственной системе. В некоторых небольших робототехнических или аэрокосмических приложениях (ЧИТАЙТЕ: не вычисления общего назначения) это было бы недопустимой тратой.
Джонатан
2
@JonathanLeaders Я думаю, вы можете безопасно удалить их. При настольной установке они присутствуют на случай, если вы вдруг подключите что-либо к USB-порту или измените какую-либо аппаратную конфигурацию и т. Д.
Дидье А.
1
Да, точно. Я до сих пор удивляюсь предположениям типа: «Вы можете подключить USB-устройство в любое время, поэтому нам нужно 15 млн строк кода», которые записаны на уровне ядра , а не на уровне дистрибутива, поскольку Linux используется в телефоне и отличается встроенные устройства. Ну, я предполагаю , что дистрибутив делает отбраковать список на своем собственном. Я бы просто подумал, что поддержка подключаемости должна быть аддитивной, а не вычитающей, то есть дистрибутив IE вроде бы «соглашается» на него, добавляя источники пакетов, в отличие от встроенных конфигураций ARM, сообщающих ядру, что он составляет один процент от его текущего размера
Джонатан
5
@JonathanLeaders, вы бы никогда не запустили ядро, настроенное для рабочего стола во встроенной системе. Наша встроенная система имеет 13 модулей и убрала всю аппаратную поддержку, которая нам не нужна (наряду с множеством других настроек). Прекратите сравнивать рабочие столы со встроенными системами. Linux работает хорошо , потому что он поддерживает все , и может быть настроен только включать то , что вы заботитесь о. И эти модули 4k действительно хороши для настольных систем: когда мой последний ноутбук умер, я просто вставил жесткий диск в гораздо более новый ноутбук, и все просто заработало .
Дрюбенн
3
В противном случае этот хороший / ценный ответ страдает от явно сердитого и боевого тона. -1.
TypeIA
19

Linux tinyconfig скомпилированные исходники количество строк пузырьковый график tinyconfig svg (скрипка)

сценарий оболочки для создания json из сборки ядра, используйте с http://bl.ocks.org/mbostock/4063269


Редактировать : оказалось, unifdefимеют некоторые ограничения ( -Iигнорируется и -includeне поддерживается, последний используется для включения сгенерированного заголовка конфигурации), в данный момент использование catне сильно меняется:

274692 total # (was 274686)

Сценарий и процедура обновлены.


Помимо драйверов, архива и т. Д., Много условного кода скомпилировано или нет в зависимости от выбранной конфигурации, код не обязательно в динамически загружаемых модулях, но встроен в ядро.

Итак, скачал исходники linux-4.1.6 , выбрал tinyconfig , он не включает модули, и я, честно говоря, не знаю, что он включает или что пользователь может делать с ним во время выполнения, в любом случае, сконфигурируйте ядро:

# tinyconfig      - Configure the tiniest possible kernel
make tinyconfig

построил ядро

time make V=1 # (should be fast)
#1049168 ./vmlinux (I'm using x86-32 on other arch the size may be different)

В процессе сборки ядра оставляются скрытые файлы, вызываемые *.cmdиз командной строки, которые также используются для создания .oфайлов, для обработки этих файлов и извлечения копии цели и зависимостей script.shниже и использования ее с find :

find -name "*.cmd" -exec sh script.sh "{}" \;

это создает копию для каждой зависимости цели с .oименем.o.c

.c код

find -name "*.o.c" | grep -v "/scripts/" | xargs wc -l | sort -n
...
   8285 ./kernel/sched/fair.o.c
   8381 ./kernel/sched/core.o.c
   9083 ./kernel/events/core.o.c
 274692 total

.h заголовки (санированные)

make headers_install INSTALL_HDR_PATH=/tmp/test-hdr
find /tmp/test-hdr/ -name "*.h" | xargs wc -l
...
  1401 /tmp/test-hdr/include/linux/ethtool.h
  2195 /tmp/test-hdr/include/linux/videodev2.h
  4588 /tmp/test-hdr/include/linux/nl80211.h
112445 total
Alex
источник
@JonathanLeaders было интересно работать над этим, радуясь кто - то вроде него
Alex
9

Компромиссы между монолитными ядрами обсуждались между Тананбаумом и Торвальдсом публично с самого начала. Если вам не нужно переходить в пользовательское пространство для всего, тогда интерфейс к ядру может быть проще. Если ядро ​​монолитное, то оно может быть более оптимизировано (и более грязно!) Внутри.

У нас были модули как компромисс в течение достаточно долгого времени. И это продолжается с такими вещами, как DPDK (удаление большей сетевой функциональности из ядра). Чем больше ядер добавлено, тем важнее избежать блокировки; так что больше вещей переместится в пользовательское пространство и ядро ​​сократится.

Обратите внимание, что монолитные ядра - не единственное решение. На некоторых архитектурах граница ядро ​​/ пользовательское пространство не дороже, чем любой другой вызов функции, что делает микроядра привлекательными.

обкрадывать
источник
1
«На некоторых архитектурах граница ядро ​​/ пользовательское пространство не дороже, чем любой другой вызов функции» - интересно! Какая это будет архитектура? Выглядит невероятно сложно, если вы просто не отказываетесь от какой-либо защиты памяти.
Во
1
Я просмотрел все видеофильмы Ивана Годдарда millcomputing.com (процессор / ремень, очень похожий на VLIW). Эта конкретная претензия является центральной темой, и ее последствия не очевидны, пока вы не перейдете к видео по безопасности. Это POC-архитектура в симуляции, но, вероятно, это не единственная архитектура с этим свойством.
Роб
1
Ах, это объясняет это. По моему опыту (и я буду первым, кто признает, что я не очень внимательно слежу за отраслью), есть много смоделированных архитектур, и лишь немногие оправдывают свои требования, как только резиновые рули отправляются в путь, т.е. на реальном оборудовании. Хотя идея, стоящая за этим, может быть интересна в любом случае - не первый раз, когда упоминается конкретный процессор. Если вы когда-нибудь найдете существующую архитектуру, обладающую этим свойством, мне было бы очень интересно.
Во
1
Кстати, вот больше ресурсов по обсуждению, которое вы упомянули: en.wikipedia.org/wiki/Tanenbaum%E2%80%93Torvalds_debate
Джонатан