「uname」はどこから情報を引き出していますか?


回答:


31

unameシステムコールuname(2)を使用して、表示されるカーネル関連情報を取得します。

概要は次のとおりです。

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

where 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」と記載されているものを参照していません。他の推奨事項はありますか?
ロイエルナンデス

@RoyHernandezの出力はlocate --regex '^/usr/include/.*/sys/utsname.h$'何ですか?
-heemayl

出力は次のとおりです。「/ usr / include / x86_64
Hernandez

.. @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構造体に格納されている情報を取得する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」を示すものを参照していないこと。他の推奨事項はありますか?
ロイエルナンデス

@RoyHernandez Cでは、整数のサイズに基づいてCPUのアーキテクチャを決定することができます。たとえば、こちらを参照してください。そのため、uname.c必ずしもそのためにライブラリを使用する必要はありません-もちろん、ソースコードを確認できます。
セルギーKolodyazhnyy

実際には、ライブラリに依存しています。。。machine.h
セルギーKolodyazhnyy

machine.hシステム全体に散らばっているようです。どのmachine.hファイルに依存していますか?
ロイエルナンデス

@RoyHernandez machine.hは、システムにリストされているすべてのものが/usr/src/linux-headers-3.19.0-33ディレクトリにあるようです。それは、現在実行中のカーネルが提供するライブラリ使用していることは非常に可能性があります
Sergiy Kolodyazhnyy

6

もちろん、heemaylの答えは正しいです。

ちょっとおもしろいのは、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);からの情報を引っ張って?
ロイヘルナンデス

@RoyHernandez utsnameの呼び出し中に生成される構造体からuname()。この例はおそらく、Cの基本がない人には簡単ではないかもしれませんが、多かれ少なかれ何が起こるかです:struct(Cのデータ型)utsnameという名前の型utsname(で定義された型<sys/utsname.h>)が宣言されています その後、名前のそれへのポインタはutsname_ptr(以降宣言されているuname()へのポインタを受け入れるstructタイプのutsname、これはこの場合には回避されている可能性がにもかかわらず、引数として、それはまた別の話です)。
コス

次に、への呼び出しにuname()は、struct utsnameprintf()値を設定する効果があります。これには、呼び出しの時点で、さまざまなフィールド内のさまざまな値が含まれています。不幸なことに、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」です。
ロイエルナンデス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.