De onde é que “uname” extrai informação?

24

Em que uname -i está retirando as informações?

Os detalhes existem em /etc/ ?

Os detalhes existem em /proc/ ?

Em caso afirmativo, qual arquivo está se referenciando para produzir esses detalhes?

    
por Roy Hernandez 22.01.2016 / 20:58

4 respostas

31

uname usa a chamada de sistema uname(2) para obter as informações relacionadas ao kernel mostradas.

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 de cabeçalho utsname.h de /usr/include/"$(arch)"-linux-gnu/sys/utsname.h para ir mais fundo.

Dê uma olhada em man 2 uname para ter mais ideia sobre isso.

    
por heemayl 22.01.2016 / 21:11
22

O programa strace nos permite visualizar as chamadas do sistema que um aplicativo pode fazer. Com uname -a , é evidente que as únicas chamadas de open vão para as bibliotecas do sistema, portanto, tecnicamente, não há arquivo no sistema de arquivos que o uname seja aberto para leitura. Em vez disso, faz chamadas do sistema usando as bibliotecas C.

Como o heemayl apontou corretamente, existe uma chamada sys para recuperar as informações armazenadas na estrutura uname . É man page, sugere o seguinte:

This is a system call, and the operating system presumably knows its name, release and version . . . . . . Part of the utsname information is also accessible via /proc/sys/ker‐ nel/{ostype, hostname, osrelease, version, domainname}.

Part of the utsname information is also accessible via /proc/sys/ker‐ nel/{ostype, hostname, osrelease, version, domainname}.

O sistema de arquivos

/proc , no entanto, é virtual, o que significa que existe apenas enquanto o sistema operacional está em execução. Assim, de alguma forma, é definido dentro de bibliotecas de kernel ou sistema.

Finalmente, lendo o código-fonte de uname.c , que pode ser obtido com apt-get source coreutils , podemos ver que ele realmente usa a biblioteca utsname.h (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 output:

[email protected]:$ 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, "7ELF
 19 
 20 #include <config.h>
 21 #include <stdio.h>
 22 #include <sys/types.h>
 23 #include <sys/utsname.h>
 24 #include <getopt.h>
 25 
[email protected]:$ 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, "7ELF%pre%%pre%%pre%%pre%%pre%%pre%%pre%%pre%%pre%%pre%>%pre%%pre%%pre%%pre%0%pre%%pre%%pre%%pre%%pre%"..., 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 +++
%pre%%pre%%pre%%pre%%pre%%pre%%pre%%pre%>%pre%%pre%%pre%%pre%0%pre%%pre%%pre%%pre%%pre%"..., 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 +++
    
por Sergiy Kolodyazhnyy 22.01.2016 / 22:24
6

É claro que a resposta do heemayl está correta.

Apenas por diversão, aqui está um trecho de código C mostrando os dados retornados por uname() (uma espécie de uname caseiro, se você quiser): compile-o com gcc uname.c -o uname e 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
    
por kos 23.01.2016 / 10:58
4

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

    
por Eduardo Cola 22.01.2016 / 21:50