
Откуда на самом деле 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