“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이것에 대해 더 생각을 할 수 있습니다.


"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"를 언급하는 것은 없습니다. 다른 권장 사항이 있습니까?
Roy Hernandez

@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
Roy Hernandez

22

이 프로그램을 strace통해 응용 프로그램이 수행 할 수있는 시스템 호출을 볼 수 있습니다. 으로 uname -a는 명백한 유일한 것을 open호출 때문에 기술적으로는 그 파일 시스템에 파일이 없습니다, 시스템 라이브러리로 이동 uname읽기 열립니다. 오히려 C 라이브러리를 사용하여 시스템 호출을합니다.

Heemayl이 올바르게 지적했듯이 uname구조에 저장된 정보를 검색하라는 sys 호출이 있습니다 . 맨 페이지이며 다음을 제안합니다.

이것은 시스템 호출이며 운영 체제는 아마도 이름, 릴리스 및 버전을 알고있을 것입니다. . . . . . utsname 정보의 일부는 / proc / sys / kernel / {ostype, hostname, osrelease, version, domainname}을 통해 액세스 할 수도 있습니다.

utsname 정보의 일부는 / proc / sys / kernel / {ostype, hostname, osrelease, version, domainname}을 통해 액세스 할 수도 있습니다.

/proc그러나 파일 시스템은 가상이므로 OS가 실행되는 동안에 만 존재합니다. 따라서 어느 정도 확장하려면 커널 또는 시스템 라이브러리 내에 설정됩니다.

마지막으로 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"를 언급하는 것은 없습니다. 다른 권장 사항이 있습니까?
Roy Hernandez

@RoyHernandez C에서는 정수의 크기에 따라 CPU의 아키텍처를 결정할 수 있습니다 (예 : 여기 참조) . 따라서 uname.c반드시 라이브러리를 사용할 필요는 없습니다. 물론 소스 코드를 살펴볼 수도 있습니다.
Sergiy Kolodyazhnyy

실제로, 그것은 라이브러리에 의존합니다. . . machine.h
Sergiy Kolodyazhnyy

machine.h시스템 전체에 후추를 뿌린 것 ​​같습니다. 어떤 machine.h파일에 의존합니까?
Roy Hernandez

@RoyHernandez machine.h내 시스템에 나열된 모든 것이 /usr/src/linux-headers-3.19.0-33디렉토리 에있는 것 같습니다 . 현재 실행중인 커널이 제공하는 라이브러리를 사용하고있을 가능성이 높습니다
Sergiy Kolodyazhnyy

6

물론 헤 마일의 대답은 맞습니다.

재미있게, 여기에 의해 반환 된 데이터 uname()( uname원하는 경우 수제 종류)를 보여주는 작동하는 C 스 니펫 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);오는가?
Roy Hernandez

@RoyHernandez utsname호출하는 동안 채워지 는 구조체 에서 uname(). 예는 아마도 너무 여기에 C의 기초없이 누군가에게 간단하지만 아니에요 발생하는 다소의하십시오 struct(C 데이터 형식) 형식의 utsname이름 utsname(유형 정의 <sys/utsname.h>) 선언; 그런 다음 명명 된 포인터 utsname_ptr가 선언됩니다 ( 이 경우에는 피할 수는 있지만 유형에 uname()대한 포인터를 인수로 허용하므로 다른 이야기입니다). structutsname
kos

그런 다음에 대한 호출 uname()은 struct를 채우는 효과가 utsname있으며, printf()호출시 다양한 필드 내부의 다양한 값이 포함됩니다. 불행히도 C에 익숙하지 않다면 아마도 자세히 이해하기 쉽지 않을 것입니다.하지만 요점은 uname()목적에 따라 작성된 데이터 구조 를 채우고 나중에 필드를 통해 인쇄하는 것 printf()입니다.
kos

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 1 월 18 일 16 일이 포함되어 있습니다. : 09 : 14 UTC 2016 "및"uname -i "출력은"x86_64 "입니다.
Roy Hernandez
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.