¿De dónde está "uname" obteniendo información?

Respuestas:

31

unameusa la llamada uname(2)al sistema para obtener la información relacionada con el núcleo que muestra.

La sinopsis es:

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

donde uname(2)devuelve información en la estructura señalada por buf. También se puede leer el archivo de cabecera utsname.hde /usr/include/"$(arch)"-linux-gnu/sys/utsname.hcavar más profundo.

Echa un vistazo man 2 unamepara tener más idea sobre esto.

heemayl
fuente
cuando ejecuto "uname -i", la salida es "x86_64". Cuando cruzo la referencia "/usr/include/x86_64-linux-gnu/sys/utsname.h", no veo nada que haga referencia a "x86_64". Hice referencia al "man 2 uname" y dice que parte de la información de utsname se hace referencia a través de "/ proc / sys / kernel / {ostype}, {hostname}, {osrelease}, {version} y {domainname}" el problema es que ninguno de esos archivos hace referencia a nada que indique "x86_64". ¿Alguna otra recomendación?
Roy Hernández el
@RoyHernandez ¿Cuál es el resultado de locate --regex '^/usr/include/.*/sys/utsname.h$'?
heemayl
El resultado es: "/usr/include/x86_64-linux-gnu/sys/utsname.h"
Roy Hernández el
@RoyHernandez Esto le indica que el archivo existe y que estaba haciendo algo mal ..
heemayl
Cuando ejecuto un uname -ila salida es x86_64. Cuando ejecuto locate --regex '^/usr/include/.*/sys/utsname.h$'la salida vuelve/usr/include/x86_64-linux-gnu/sys/utsname.h
Roy Hernandez
22

El programa stracenos permite ver las llamadas al sistema que puede hacer una aplicación. Con uname -aque es evidente que las únicas openllamadas van a las bibliotecas del sistema, por lo que técnicamente no hay ningún archivo en el sistema de archivos que la unameabre para la lectura. Más bien realiza llamadas al sistema utilizando las bibliotecas C.

Como heemayl señaló correctamente, existe una llamada sys para recuperar la información almacenada en la unameestructura. Es la página de manual, sugiere lo siguiente:

Esta es una llamada al sistema, y ​​el sistema operativo supuestamente conoce su nombre, versión y versión. . . . . . También se puede acceder a parte de la información de utsname a través de / proc / sys / kernel / {ostype, hostname, osrelease, version, domainname}.

También se puede acceder a parte de la información de utsname a través de / proc / sys / kernel / {ostype, hostname, osrelease, version, domainname}.

/procsin embargo, el sistema de archivos es virtual, lo que significa que existe solo mientras el sistema operativo se está ejecutando. Por lo tanto, hasta cierto punto, se establece dentro del núcleo o las bibliotecas del sistema.

Finalmente, leyendo el código fuente del uname.ccual se puede obtener apt-get source coreutils, podemos ver que de hecho usa la utsname.hbiblioteca (impresa con números de línea):

 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 salida:

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
fuente
cuando ejecuto "uname -i", la salida es "x86_64". Cuando cruzo la referencia "/usr/include/x86_64-linux-gnu/sys/utsname.h", no veo nada que haga referencia a "x86_64". Hice referencia al "man 2 uname" y dice que parte de la información de utsname se hace referencia a través de "/ proc / sys / kernel / {ostype}, {hostname}, {osrelease}, {version} y {domainname}" el problema es que ninguno de esos archivos hace referencia a nada que indique "x86_64". ¿Alguna otra recomendación?
Roy Hernández el
@RoyHernandez En C es posible determinar la arquitectura de una CPU en función del tamaño que toma un entero, por ejemplo, consulte aquí . Por lo tanto uname.c, no necesariamente necesita usar una biblioteca para eso; podemos mirar el código fuente, por supuesto, para estar seguros.
Sergiy Kolodyazhnyy
En realidad, se basa en una biblioteca. . . machine.h
Sergiy Kolodyazhnyy
machine.hparece estar salpicada en todo el sistema. ¿En qué machine.harchivo se basa?
Roy Hernández el
@RoyHernandez todos los que figuran machine.hen mi sistema parecen estar en el /usr/src/linux-headers-3.19.0-33directorio. Es muy probable que use la biblioteca proporcionada por el núcleo actualmente en ejecución
Sergiy Kolodyazhnyy
6

Por supuesto, la respuesta de heemayl es correcta.

Solo por diversión, aquí hay un fragmento de C en funcionamiento que muestra los datos devueltos por uname()(una especie de casero unamesi lo desea): compílelo gcc uname.c -o unamey ejecútelo con ./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
fuente
¿De dónde printf("%\n", utsname.machine);saca la información?
Roy Hernández el
@RoyHernandez De la estructura utsname, que se rellena durante la llamada a uname(). El ejemplo probablemente no sea demasiado sencillo para alguien sin los conceptos básicos de C, pero aquí está más o menos lo que sucede: se declara un struct(tipo de datos C) de tipo utsnamellamado utsname(tipo definido en <sys/utsname.h>); luego utsname_ptrse declara un puntero al nombre (ya que uname()acepta un puntero a un structtipo utsnamecomo argumento, aunque esto podría haberse evitado en este caso, pero esa es otra historia).
kos
Entonces, la llamada a uname()tiene el efecto de llenar la estructura utsname, que en el momento de la printf()llamada contiene los diversos valores dentro de los diversos campos. Desafortunadamente, si no está familiarizado con C, esto probablemente no será fácil de comprender en detalle, pero el punto es que uname()puebla una estructura de datos construida a propósito, cuyos campos se imprimen más tarde printf().
kos
4

Como una adición a la respuesta de heemayl, puede obtener información como en el unamecomando /proc/version.

Eduardo Cola
fuente
/ proc / version contiene "Linux versión 3.19.0-47-generic (buildd @ lgw01-19) (gcc versión 4.8.2 (Ubuntu 4.8.2-19ubuntu1)) # 53 ~ 14.04.1-Ubuntu SMP lun 18 de enero 16 : 09: 14 UTC 2016 "y la salida" uname -i "es" x86_64 ".
Roy Hernández el