Звідки уніме бере інформацію про неї?


40

Звідки уніме насправді бере інформацію?

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

Скажіть, хтось хотів змінити базовий вихід uname/ uname -s з Linuxна щось інше (по суті, перейменувавши ядро).

Як він / вона піде робити це належним чином (тобто змінити джерело)?

Відповіді:


26

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 ядро, і немає ніякої можливої ​​причини використовувати його нічого іншого.

Однак, оскільки він є відкритим кодом, ви можете змінити вихідний код і перекомпілювати ядро, щоб використовувати будь-яке ім'я системи.


2
domainnameПоле задається domainnameкомандою, з допомогою setdomainnameсистемного виклику. Аналогічно nodenameполе встановлюється hostnameкомандою, використовуючи sethostnameсистемний виклик. (Значення nodename/ hostnameзначення може бути збережене в /etc/nodename.)
Скотт,

2
Це не має значення - питання задається, де це змінити. Так, так, unameкоманда отримує свою інформацію з системного виклику. І звідки системний виклик отримує свою інформацію? (Відповідь, надана іншими афішами тут: це важко закодовано в ядрі під час компіляції.)
Жил 'SO- перестань бути злим'

@Gilles: Що нерелевантно? Якщо відповідь "надано іншими плакатами тут: це важко закодовано в ядро ​​..." Примітка. Я сказав саме те саме: "Це надходить безпосередньо з запущеного ядра. Я б припустив, що вся інформація є важкою -кодування в нього ... оскільки воно є відкритим кодом, ви можете змінити вихідний код і перекопіювати ядро, щоб використовувати будь-яке ім'я системи . Це не варіант налаштування.
goldilocks

2
@goldilocks Чому б machineколи-небудь змінити? Це може бути не жорстко закодовано в ядро, оскільки воно може адаптуватися до обладнання, але, безумовно, воно буде встановлено під час завантаження і не зміниться після цього. Але ні: він може бути встановлений для кожного процесу (наприклад, для звітування i686в 32-бітній обробці на x86_64). До речі, releaseтакож можна певною мірою налаштувати під кожен процес (спробуйте setarch i686 --uname-2.6 uname -a).
Жил 'ТАК - перестань бути злим'

1
@Gilles Я редагував machine, nodenameі releaseв це питання з посиланням на коментарі. Знову ж таки, питання було насправді не про всі ці поля.
золотинок

26

Дані зберігаються в 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);

Самі рядки містяться в / включає / генерує / компілює.h:

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

і включити / згенерувати / utsrelease.h:

#define UTS_RELEASE "3.14.0-v2-v"

UTS_SYSNAME може бути визначений у включенні / linux / uts.h

#ifndef UTS_SYSNAME
#define UTS_SYSNAME "Linux"
#endif

або як #define у ​​makefiles

Нарешті, ім'я хоста та доменне ім’я можна керувати за допомогою / proc / sys / kernel / {хост, ім'я домену}. Вони є на простір імен UTS:

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

Це, як правило, гарна і повна відповідь, але, можливо, варто, відповівши на запитання плаката безпосередньо. Я вважаю, що це означало б - змінити відповідний запис у відповідному файлі та перекомпілювати. Ви написали "або як #define у ​​makefiles". Чи можете ви докладно?
Faheem Mitha

+1 для unshare. Якось мені вдалося пропустити цю команду до сьогодні. Дякую!
Тіно

І include/generated/compile.hпороджується scripts/mkcompile_h: unix.stackexchange.com/a/485962/32558
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

8

За допомогою Cross Reference Linux і ваше згадка /proc/sys/kernel/ostype, я розшукав , ostypeщоб вмикати / Linux / sysctl.h , де коментар каже , що імена додаються по телефону register_sysctl_table.

То звідки це називається ? Одне місце займає ядро / utsname_sysctl.c , яке включає include / linux / uts.h , де ми знаходимо:

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

Отже, як зазначено в документації на ядро :

Єдиний спосіб налаштування цих значень - це відновлення ядра

:-)


6

Як коментується в іншому місці, інформація надходить із системою unamesccall, інформація якої жорстко кодується в запущеному ядрі.

Частина версії зазвичай встановлюється при компілюванні нового ядра за допомогою Makefile :

VERSION = 3
PATCHLEVEL = 15
SUBLEVEL = 0
EXTRAVERSION =

коли я встиг пограти, компілюючи свої ядра, я додавав речі туди в EXTRAVERSION; що дав вам uname -r такі речі 3.4.1-mytestkernel.

Я не повністю його розумію, але думаю, що решта інформації встановлюється Makefileтакож у рядку 944:

# ---------------------------------------------------------------------------

# KERNELRELEASE can change from a few different places, meaning version.h
# needs to be updated, so this check is forced on all builds

uts_len := 64
define filechk_utsrelease.h
    if [ `echo -n "$(KERNELRELEASE)" | wc -c ` -gt $(uts_len) ]; then \
      echo '"$(KERNELRELEASE)" exceeds $(uts_len) characters' >&2;    \
      exit 1;                                                         \
    fi;                                                               \
    (echo \#define UTS_RELEASE \"$(KERNELRELEASE)\";)
endef

define filechk_version.h
    (echo \#define LINUX_VERSION_CODE $(shell                         \
    expr $(VERSION) \* 65536 + 0$(PATCHLEVEL) \* 256 + 0$(SUBLEVEL)); \
    echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))';)
endef

$(version_h): $(srctree)/Makefile FORCE
    $(call filechk,version.h)

include/generated/utsrelease.h: include/config/kernel.release FORCE
    $(call filechk,utsrelease.h)

PHONY += headerdep
headerdep:
    $(Q)find $(srctree)/include/ -name '*.h' | xargs --max-args 1 \
    $(srctree)/scripts/headerdep.pl -I$(srctree)/include

Для решти даних sys_unameсистемний виклик генерується за допомогою макросів (досить скрученим способом). Ви можете почати звідси, якщо відчуваєте пригод.

Напевно, найкращий спосіб змінити таку інформацію - це написання модуля ядра для зміни unameсистемного виклику; Я ніколи цього не робив, але ви можете знайти інформацію на цій сторінці в розділі 4.2 (вибачте, прямого посилання немає). Однак зауважте, що цей код посилається на досить старе ядро ​​(тепер ядро ​​Linux має utsпростори імен, що б вони не означали), тому вам, мабуть, доведеться багато чого змінити.


Дякую всім. Я вже знав, що це має відношення до унаме. Однак те, що я не можу зрозуміти, - це те, як і де всередині джерела визначається рядок "Linux". Все, що я знаю, - це те, де я можу знайти цю інформацію під час виконання (вона міститься всередині / proc / sys / kernel / ostype). Я б сказав, як саме ядро ​​знає, що його власне ім'я було б однією з найцікавіших речей.
user237251

@ user237251, скільки екземплярів слова "Linux" зустрічається у джерелі ядра в рядкових контекстах? Якщо їх не так багато, ви можете просто вивчити результати текстового пошуку і побачити, куди це веде вас.
JAB

@JAB Шлях занадто багато. На щастя, хтось на kernelnewbies.org допоміг мені розгадати "таємницю". Linux отримує своє sys ім'я від /include/Linux/uts.h. Дивіться тут: lxr.free-electrons.com/source/include/linux/uts.h?v=3.10
user237251

2

Хоча я не зміг знайти нічого в джерелі, щоб вказати на це, я вважаю, що він використовує функцію unme syscall.

man 2 uname

повинен розповісти вам більше про це. Якщо це так, то отримання інформації безпосередньо з ядра та її зміна, ймовірно, вимагатиме перекомпіляції.

Ви можете змінити бінарне для вас невідомим, щоб робити все, що завгодно, хоч просто напишіть його за допомогою програми, яка вам подобається. Мінус у тому, що деякі сценарії покладаються на цей результат.


3
Якщо це зробити strace uname, він підтвердить, що використовується unameсистемний виклик.
Graeme

1

Правильним способом зміни неможливо було б змінити заголовки компіляції та перекомпілювати так, як пропонують інші. Але я не впевнений, чому ви хочете пережити стільки неприємностей, коли можете зробити щось на кшталт,

alias uname 'uname \\!* | sed s/2.6.13/2.6.52/'

або навіть

alias uname 'echo whatever'

0

Відповідь Рмано отримала мені почастування, але справжню магію легше виявити, передавши Q=параметр у вашому makeкомандному рядку у каталозі джерела ядра. вона дозволяє побачити деталі, один з яких є виклик скрипта: echo "4.4.19$(/bin/sh ./scripts/setlocalversion .)". виконуючи той же фрагмент коду дає ядро номер версії, 4.4.19-00010-ge5dddbf. якщо ви подивитеся на скрипт, він визначає номер у системі версій, а запуск його bash -xпоказує точний процес:

+++ git rev-parse --verify --short HEAD
++ head=e5dddbf
+++ git describe --exact-match
++ '[' -z '' ']'
++ false
+++ git describe
++ atag=release/A530_os_1.0.0-10-ge5dddbf
++ echo release/A530_os_1.0.0-10-ge5dddbf
++ awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}'
++ git config --get svn-remote.svn.url
++ git diff-index --name-only HEAD
++ grep -qv '^scripts/package'
++ return
+ res=-00010-ge5dddbf
+ echo -00010-ge5dddbf
-00010-ge5dddbf

що це мені показує, що якщо я хочу створити модуль ядра для роботи зі своїм запущеним ядром, я перебуваю в неправильному тезі випуску та неправильній комісії. Мені потрібно виправити це і створити принаймні DTB ( make dtbs), щоб створити згенеровані файли з правильним номером версії.


виявляється, навіть цього було недостатньо. Мені довелося замінити scripts/setlocalversionтой, який просто робить:

#!/bin/sh
echo -0710GC0F-44F-01QA

потім відновіть автоматично створені файли:

make Q= ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- dtbs

тоді я міг би створити зразок драйвера Дерека Моллой і зміг би insmodйого успішно. мабуть, попередження про Module.symversвідсутність присутності не мало значення. весь Linux використовував, щоб визначити, чи буде працювати модуль, це локальний рядок перетворення.


0

scripts/mkcompile_h

У версії v4.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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.