Откуда «uname» извлекает информацию?

Ответы:

31

unameиспользует системный вызов uname(2)для получения информации, относящейся к ядру.

Краткое содержание:

#include <sys/utsname.h>
int uname(struct utsname *buf);

где uname(2)возвращает информацию в структуре, на которую указывает buf. Также вы можете прочитать файл заголовка utsname.hиз /usr/include/"$(arch)"-linux-gnu/sys/utsname.hкопать глубже.

Посмотрите, man 2 unameчтобы получить больше представления об этом.

heemayl
источник
когда я запускаю "uname -i", выводится "x86_64". Когда я пересекаю ссылку "/usr/include/x86_64-linux-gnu/sys/utsname.h", я не вижу ничего, что ссылается на "x86_64". Я сослался на "man 2 uname", и в нем говорится, что на часть информации utsname ссылаются через "/ proc / sys / kernel / {ostype}, {hostname}, {osrelease}, {version} и {domainname}" проблема что ни один из этих файлов не ссылается на что-либо с указанием «x86_64». Любые другие рекомендации?
Рой Эрнандес
@RoyHernandez Каков выход locate --regex '^/usr/include/.*/sys/utsname.h$'?
Heemayl
Вывод: "/usr/include/x86_64-linux-gnu/sys/utsname.h"
Рой Эрнандес
@RoyHernandez Это говорит о том, что файл существует, и вы делали что-то не так ..
Heemayl
Когда я запускаю uname -iвывод x86_64. Когда я запускаю locate --regex '^/usr/include/.*/sys/utsname.h$'выходной возвращается/usr/include/x86_64-linux-gnu/sys/utsname.h
Рой Эрнандес
22

Программа straceпозволяет нам просматривать системные вызовы, которые может выполнять приложение. С uname -aэто очевидно , что только openзвонки идут в системные библиотеки, так что технически нет файла в файловой системе , что unameоткрывает для чтения. Скорее это делает системные вызовы, используя библиотеки C.

Как правильно указал Heemayl, существует системный вызов для извлечения информации, хранящейся в unameструктуре. Это страница руководства, предлагает следующее:

Это системный вызов, и операционная система предположительно знает его имя, версию и версию. , , , , , Часть информации о имени пользователя также доступна через / proc / sys / ядро ​​/ {ostype, hostname, osrelease, version, domainname}.

Часть информации о имени пользователя также доступна через / proc / sys / ядро ​​/ {ostype, hostname, osrelease, version, domainname}.

/procОднако файловая система является виртуальной, то есть она существует только во время работы ОС. Таким образом, в некоторой степени это устанавливается в ядре или системных библиотеках.

Наконец, читая исходный код, uname.cкоторый можно получить с помощью apt-get source coreutils, мы видим, что он действительно использует utsname.hбиблиотеку (напечатанную с номерами строк):

 19 
 20 #include <config.h>
 21 #include <stdio.h>
 22 #include <sys/types.h>
 23 #include <sys/utsname.h>
 24 #include <getopt.h>
 25 

strace выход:

skolodya@ubuntu:$ strace uname -a
execve("/bin/uname", ["uname", "-a"], [/* 58 vars */]) = 0
brk(0)                                  = 0x1478000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efee6935000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=137226, ...}) = 0
mmap(NULL, 137226, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7efee6913000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\320\37\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1840928, ...}) = 0
mmap(NULL, 3949248, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7efee6350000
mprotect(0x7efee650b000, 2093056, PROT_NONE) = 0
mmap(0x7efee670a000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1ba000) = 0x7efee670a000
mmap(0x7efee6710000, 17088, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7efee6710000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efee6912000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efee6910000
arch_prctl(ARCH_SET_FS, 0x7efee6910740) = 0
mprotect(0x7efee670a000, 16384, PROT_READ) = 0
mprotect(0x606000, 4096, PROT_READ)     = 0
mprotect(0x7efee6937000, 4096, PROT_READ) = 0
munmap(0x7efee6913000, 137226)          = 0
brk(0)                                  = 0x1478000
brk(0x1499000)                          = 0x1499000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=7216688, ...}) = 0
mmap(NULL, 7216688, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7efee5c6e000
close(3)                                = 0
uname({sys="Linux", node="eagle", ...}) = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efee6934000
uname({sys="Linux", node="eagle", ...}) = 0
uname({sys="Linux", node="eagle", ...}) = 0
write(1, "Linux eagle 4.1.0-040100rc2-gene"..., 113Linux eagle 4.1.0-040100rc2-generic #201505032335 SMP Mon May 4 03:36:35 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
) = 113
close(1)                                = 0
munmap(0x7efee6934000, 4096)            = 0
close(2)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++
Сергей Колодяжный
источник
когда я запускаю "uname -i", выводится "x86_64". Когда я пересекаю ссылку "/usr/include/x86_64-linux-gnu/sys/utsname.h", я не вижу ничего, что ссылается на "x86_64". Я ссылался на "man 2 uname", и в нем говорится, что на часть информации utsname ссылаются через "/ proc / sys / kernel / {ostype}, {hostname}, {osrelease}, {version} и {domainname}", проблема в том, что что ни один из этих файлов не ссылается на что-либо с указанием «x86_64». Любые другие рекомендации?
Рой Эрнандес
@RoyHernandez В C возможно определить архитектуру ЦП, основываясь, например, на размере, который принимает целое число - см. Здесь . Так что для uname.cэтого не обязательно использовать библиотеку - мы можем, конечно, взглянуть на исходный код.
Сергей Колодяжный
На самом деле, это зависит от библиотеки. , , machine.h
Сергей Колодяжный
machine.hкажется, пронизано всей системой. На какой machine.hфайл он опирается?
Рой Эрнандес
@RoyHernandez все перечисленные machine.hв моей системе, похоже, находятся в /usr/src/linux-headers-3.19.0-33каталоге. Весьма вероятно, что он использует библиотеку, предоставляемую в настоящее время работающим ядром
Сергей Колодяжный
6

Конечно, ответ Химейла правильный.

Просто для удовольствия, вот рабочий фрагмент C, демонстрирующий возвращаемые данные uname()(своего рода самодельный, unameесли хотите): скомпилируйте его gcc uname.c -o unameи запустите с помощью ./uname:

#include <stdio.h> // printf()
#include <sys/utsname.h> // uname()

int main() {
        int ret; // stores the return value of uname()
        struct utsname utsname; // stores the data returned by uname()
        struct utsname *utsname_ptr = &utsname; // pointer to the struct holding the data returned by uname()

        ret = uname(utsname_ptr); // calls uname() on utsname_ptr and stores its return value in ret

        /* prints the fields of utsname */

        printf("%s\n", utsname.sysname);
        printf("%s\n", utsname.nodename);
        printf("%s\n", utsname.release);
        printf("%s\n", utsname.version);
        printf("%s\n", utsname.machine);

        /* returns the return value of uname() */

        return(ret);
}
% ./uname 
Linux
user-X550CL
4.2.0-25-generic
#30-Ubuntu SMP Mon Jan 18 12:31:50 UTC 2016
x86_64
кос
источник
откуда printf("%\n", utsname.machine);берется информация?
Рой Эрнандес
@RoyHernandez Из структуры utsname, которая заполняется во время вызова uname(). Этот пример, вероятно, не слишком прост для тех, кто не знает основ C, но вот более или менее то, что происходит: объявлен struct(тип данных C) типа utsnamenamed utsname(тип, определенный в <sys/utsname.h>); затем utsname_ptrобъявляется указатель на него с именем (так как в качестве аргумента uname()принимает указатель на structтип utsname, хотя этого можно было бы избежать в этом случае, но это уже другая история).
Кос
Затем вызов to uname()заполняет структуру utsname, которая во время printf()вызова содержит различные значения внутри различных полей. К сожалению, если вы не знакомы с C, это, вероятно, не будет легко понять подробно, но дело в том, что uname()заполняет структуру данных, созданную специально, поля которой впоследствии распечатываются printf().
Кос
4

В дополнение к ответу Heemayl, вы можете получить некоторую информацию, как в unameкоманде от /proc/version.

Эдуардо Кола
источник
/ proc / version содержит "Linux версии 3.19.0-47-generic (buildd @ lgw01-19) (gcc версия 4.8.2 (Ubuntu 4.8.2-19ubuntu1)) # 53 ~ 14.04.1-Ubuntu SMP Mon Jan 18 16 : 09: 14 UTC 2016 "и вывод" uname -i "-" x86_64 ".
Рой Эрнандес