De onde “uname” extrai informações?

24

De onde está uname -itirando a informação?

Os detalhes existem /etc/?

Os detalhes existem /proc/?

Em caso afirmativo, qual arquivo está fazendo referência para gerar esses detalhes?

Roy Hernandez
fonte
Relacionado: de onde o uname obtém suas informações?
Mark Plotnick

Respostas:

31

unameusa a chamada do sistema uname(2)para obter as informações relacionadas ao kernel que mostra.

A sinopse é:

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

onde uname(2)retorna informações na estrutura apontada por buf. Além disso, você pode ler o arquivo utsname.hdo cabeçalho /usr/include/"$(arch)"-linux-gnu/sys/utsname.hpara se aprofundar.

Dê uma olhada man 2 unamepara ter mais idéia sobre isso.

heemail
fonte
quando executo "uname -i", a saída é "x86_64". Quando cruzo a referência "/usr/include/x86_64-linux-gnu/sys/utsname.h", não vejo nada que faça referência a "x86_64". Mencionei o "man 2 uname" e ele afirma que parte das informações do nome do usuário é referenciada por "/ proc / sys / kernel / {ostype}, {hostname}, {osrelease}, {version} e {domainname}". que nenhum desses arquivos faz referência a algo declarando "x86_64". Alguma outra recomendação?
Roy Hernandez
@RoyHernandez Qual é o resultado locate --regex '^/usr/include/.*/sys/utsname.h$'?
precisa saber é
A saída é: "/usr/include/x86_64-linux-gnu/sys/utsname.h"
Roy Hernandez
@RoyHernandez Isto diz que o arquivo existe e que você estava fazendo algo errado ..
heemayl
Quando executo um, uname -ia saída é x86_64. Quando eu executo locate --regex '^/usr/include/.*/sys/utsname.h$'a saída retorna/usr/include/x86_64-linux-gnu/sys/utsname.h
Roy Hernandez
22

O programa stracenos permite visualizar as chamadas do sistema que um aplicativo pode fazer. Como uname -aé evidente, as únicas openchamadas são para as bibliotecas do sistema; portanto, tecnicamente, não há nenhum arquivo no sistema de arquivos que ele unameabra para leitura. Em vez disso, ele faz chamadas de sistema usando as bibliotecas C.

Como o heemayl apontou corretamente, existe o sys call para recuperar as informações armazenadas na unameestrutura. É a página de manual, sugere o seguinte:

Essa é uma chamada do sistema, e o sistema operacional provavelmente sabe seu nome, release e versão. . . . . . Parte das informações do nome do usuário também pode ser acessada via / proc / sys / ker‐ nel / {ostype, nome do host, liberação do sistema, versão, nome do domínio}.

Parte das informações do nome do usuário também pode ser acessada via / proc / sys / ker‐ nel / {ostype, nome do host, liberação do sistema, versão, nome do domínio}.

/procO sistema de arquivos, no entanto, é virtual, o que significa que existe apenas enquanto o sistema operacional está em execução. Assim, até certo ponto, ele é definido nas bibliotecas do kernel ou do sistema.

Finalmente, lendo o código fonte do uname.cqual pode ser obtido apt-get source coreutils, podemos ver que ele realmente usa a utsname.hbiblioteca (impressa com números de linha):

 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 saída:

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 +++
Sergiy Kolodyazhnyy
fonte
quando executo "uname -i", a saída é "x86_64". Quando cruzo a referência "/usr/include/x86_64-linux-gnu/sys/utsname.h", não vejo nada que faça referência a "x86_64". Mencionei o "man 2 uname" e ele afirma que parte das informações do nome do usuário é referenciada por "/ proc / sys / kernel / {ostype}, {hostname}, {osrelease}, {version} e {domainname}". que nenhum desses arquivos faça referência a algo declarando "x86_64". Alguma outra recomendação?
Roy Hernandez
@RoyHernandez Em C, é possível determinar a arquitetura de uma CPU com base no tamanho que o número inteiro leva, por exemplo - consulte aqui . Portanto, uname.cnão é necessário usar uma biblioteca para isso - podemos ver o código fonte, é claro, para ter certeza.
Sergiy Kolodyazhnyy
Na verdade, ele depende de uma biblioteca. . . machine.h
Sergiy Kolodyazhnyy
machine.hparece estar apimentado em todo o sistema. Em qual machine.harquivo ele se baseia?
Roy Hernandez
@RoyHernandez todos os listados machine.hno meu sistema parecem estar no /usr/src/linux-headers-3.19.0-33diretório É muito provável que ele use a biblioteca fornecida pelo kernel atualmente em execução
Sergiy Kolodyazhnyy
6

É claro que a resposta de heemayl está correta.

Apenas por diversão, aqui está um trecho de C em funcionamento que mostra os dados retornados por uname()(uma espécie de caseiro, unamese você quiser): compile-o gcc uname.c -o unamee execute-o com ./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
kos
fonte
de onde estão as printf("%\n", utsname.machine);informações?
Roy Hernandez
@RoyHernandez A partir da estrutura utsname, que é preenchida durante a chamada para uname(). O exemplo provavelmente não é muito simples para alguém sem o básico de C, mas aqui está mais ou menos o que acontece: um struct(tipo de dados C) do tipo utsnamenomeado utsname(tipo definido em <sys/utsname.h>) é declarado; então, um ponteiro para o nome utsname_ptré declarado (uma vez que uname()aceita um ponteiro para um structdo tipo utsnamecomo argumento, embora isso possa ter sido evitado nesse caso, mas essa é outra história).
kos
Em seguida, a chamada para uname()tem o efeito de preencher a estrutura utsname, que no momento da printf()chamada contém os vários valores dentro dos vários campos. Infelizmente, se você não estiver familiarizado com C, isso provavelmente não será fácil de entender em detalhes, mas o ponto é que uname()preenche uma estrutura de dados criada de propósito, cujos campos são impressos posteriormente printf().
kos
4

Como complemento à resposta de heemayl, você pode obter algumas informações, como no unamecomando /proc/version.

Eduardo Cola
fonte
/ proc / version contém "Linux versão 3.19.0-47-generic (buildd @ lgw01-19) (versão gcc 4.8.2 (Ubuntu 4.8.2-19ubuntu1)) # 53 ~ 14.04.1-Ubuntu SMP seg 18 de janeiro de 16 : 09: 14 UTC 2016 "e" uname -i "são" x86_64 ".
Roy Hernandez