Откуда uname берет информацию?

Откуда uname берет информацию?

Откуда на самом деле uname берет информацию?

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

Допустим, кто-то захотел изменить базовый вывод uname/ uname -s на Linuxчто-то другое (по сути, переименовать ядро).

Как бы он/она сделал(а) это правильно (то есть изменил(а) источник)?

решение1

Данные хранятся в init/version.c:

struct uts_namespace init_uts_ns = {
        .kref = {
                .refcount       = ATOMIC_INIT(2),
        },
        .name = {
                .sysname        = UTS_SYSNAME,
                .nodename       = UTS_NODENAME,
                .release        = UTS_RELEASE,
                .version        = UTS_VERSION,
                .machine        = UTS_MACHINE,
                .domainname     = UTS_DOMAINNAME,
        },
        .user_ns = &init_user_ns,
        .proc_inum = PROC_UTS_INIT_INO,
};
EXPORT_SYMBOL_GPL(init_uts_ns);

Сами строки находятся в include/generated/compile.h:

#define UTS_MACHINE "x86_64"
#define UTS_VERSION "#30 SMP Fri Apr 11 00:24:23 BST 2014"

и в include/generated/utsrelease.h:

#define UTS_RELEASE "3.14.0-v2-v"

UTS_SYSNAME может быть определен в include/linux/uts.h

#ifndef UTS_SYSNAME
#define UTS_SYSNAME "Linux"
#endif

или как #define в makefiles

Наконец, имя хоста и имя домена можно контролировать с помощью /proc/sys/kernel/{hostname,domainname}. Они соответствуют пространству имен UTS:

# hostname
hell
# unshare --uts /bin/bash
# echo test > /proc/sys/kernel/hostname 
# hostname
test
# exit
# hostname
hell

решение2

Утилита unameполучает информацию из uname()системного вызова. Она заполняет структуру, подобную этой (см.man 2 uname):

       struct utsname {
           char sysname[];    /* Operating system name (e.g., "Linux") */
           char nodename[];   /* Name within "some implementation-defined
                                 network" */
           char release[];    /* Operating system release (e.g., "2.6.28") */
           char version[];    /* Operating system version */
           char machine[];    /* Hardware identifier */
       #ifdef _GNU_SOURCE
           char domainname[]; /* NIS or YP domain name */
       #endif
       };

Это напрямую из работающего ядра. Я бы предположил, что вся информация жестко закодирована в нем, за исключением, возможно domainname(и как оказалось, также nodename, machine, и release, см. комментарии). Строка релиза из uname -rможет быть установлена ​​через конфигурацию во время компиляции, но я очень сомневаюсь, что поле sysname может быть установлено — это ядро ​​Linux, и нет никаких разумных причин для использования чего-либо еще.

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

решение3

С помощьюПерекрестная ссылка Linuxи ваше упоминание о /proc/sys/kernel/ostype, я отследил ostypeдовключить/linux/sysctl.h, где в комментарии говорится, что имена добавляются путем вызова register_sysctl_table.

Так где же это?звонил из? Одно место - этоядро/utsname_sysctl.c, которая включает в себявключить/linux/uts.h, где мы находим:

/*
 * Defines for what uname() should return 
 */
#ifndef UTS_SYSNAME
#define UTS_SYSNAME "Linux"
#endif

Итак, какдокументация ядрасостояния:

Единственный способ настроить эти значения — пересобрать ядро.

:-)

решение4

scripts/mkcompile_h

В версии 4.19 это файл include/generated/compile.h, который генерирует и содержит несколько интересных частей /proc/version:https://github.com/torvalds/linux/blob/v4.19/scripts/mkcompile_h

  • часть #<version>берется из .versionфайла в дереве сборки, который увеличивается каждый раз, когда происходит связывание (требуется изменение файла/конфигурации) на scripts/link-vmlinux.sh.

    Его можно переопределить с помощью KBUILD_BUILD_VERSIONпеременной окружения:

    if [ -z "$KBUILD_BUILD_VERSION" ]; then
        VERSION=$(cat .version 2>/dev/null || echo 1)
    else
        VERSION=$KBUILD_BUILD_VERSION
    fi
    
  • дата — это просто сырой dateвызов:

    if [ -z "$KBUILD_BUILD_TIMESTAMP" ]; then
        TIMESTAMP=`date`
    else
        TIMESTAMP=$KBUILD_BUILD_TIMESTAMP
    fi
    

    и аналогично имя пользователя происходит из whoami( KBUILD_BUILD_USER), а имя хоста из hostname( KBUILD_BUILD_HOST)

  • Версия компилятора взята из gcc -v, и, по-видимому, не может контролироваться.

Вот как изменить версию вопроса:https://stackoverflow.com/questions/23424174/how-to-customize-or-remove-extra-linux-kernel-version-details-shown-at-boot

Связанный контент