uname はどこから情報を入手しているのでしょうか?

uname はどこから情報を入手しているのでしょうか?

uname は実際にどこから情報を入手しているのでしょうか?

これは簡単なはずだと私は思います。残念ながら、その情報だけを含むヘッダーは見つかりません。

uname誰かが/の基本出力を別のものに変更したい(つまり、カーネルの名前を変更する)としuname -s ますLinux

適切な方法(つまり、ソースの変更)でそれを実行するにはどうすればよいでしょうか?

答え1

データは init/version.c に保存されます。

struct uts_namespace init_uts_ns = {
        .kref = {
                .refcount       = ATOMIC_INIT(2),
        },
        .name = {
                .sysname        = UTS_SYSNAME,
                .nodename       = UTS_NODENAME,
                .release        = UTS_RELEASE,
                .version        = UTS_VERSION,
                .machine        = UTS_MACHINE,
                .domainname     = UTS_DOMAINNAME,
        },
        .user_ns = &init_user_ns,
        .proc_inum = PROC_UTS_INIT_INO,
};
EXPORT_SYMBOL_GPL(init_uts_ns);

文字列自体は include/generated/compile.h にあります。

#define UTS_MACHINE "x86_64"
#define UTS_VERSION "#30 SMP Fri Apr 11 00:24:23 BST 2014"

include/generated/utsrelease.h では次のようになります:

#define UTS_RELEASE "3.14.0-v2-v"

UTS_SYSNAMEはinclude/linux/uts.hで定義される可能性があります。

#ifndef UTS_SYSNAME
#define UTS_SYSNAME "Linux"
#endif

またはmakefile内の#defineとして

最後に、ホスト名とドメイン名は /proc/sys/kernel/{hostname,domainname} によって制御できます。これらは UTS 名前空間ごとにあります。

# hostname
hell
# unshare --uts /bin/bash
# echo test > /proc/sys/kernel/hostname 
# hostname
test
# exit
# hostname
hell

答え2

このunameユーティリティはシステムコールから情報を取得しますuname()。次のような構造体に値を設定します(man 2 uname):

       struct utsname {
           char sysname[];    /* Operating system name (e.g., "Linux") */
           char nodename[];   /* Name within "some implementation-defined
                                 network" */
           char release[];    /* Operating system release (e.g., "2.6.28") */
           char version[];    /* Operating system version */
           char machine[];    /* Hardware identifier */
       #ifdef _GNU_SOURCE
           char domainname[]; /* NIS or YP domain name */
       #endif
       };

これは実行中のカーネルから直接取得されます。おそらく を除いて、すべての情報がハードコードされていると思いますdomainname(実際、nodenamemachine、もハードコードされていますrelease。コメントを参照してください)。 からのリリース文字列は、uname -rコンパイル時に構成で設定できますが、 sysname フィールドが設定できるかどうかは非常に疑問です。これは Linux カーネルであり、他のものを使用する理由は考えられません。

ただし、オープンソースなので、ソース コードを変更してカーネルを再コンパイルし、任意の sysname を使用することができます。

答え3

の助けを借りてLinux クロスリファレンスそしてあなたの言及/proc/sys/kernel/ostype、私は追跡しostypeましたインクルード/linux/sysctl.h、コメントには、 を呼び出すことによって名前が追加されると書かれていますregister_sysctl_table

それでそれはどこにあるのですかから呼び出された? 1つの場所はカーネル/utsname_sysctl.c、これには含める/linux/uts.h、そこには次のような記述があります:

/*
 * Defines for what uname() should return 
 */
#ifndef UTS_SYSNAME
#define UTS_SYSNAME "Linux"
#endif

だから、カーネルドキュメント状態:

これらの値を調整する唯一の方法はカーネルを再構築することです

:-)

答え4

scripts/mkcompile_h

v4.19 では、これは を生成するファイルでありinclude/generated/compile.h、 のいくつかの興味深い部分が含まれています/proc/versionhttps://github.com/torvalds/linux/blob/v4.19/scripts/mkcompile_h

  • この部分はビルド ツリー上のファイル#<version>から取得され、リンクが発生するたびに (ファイル/構成の変更が必要) 増加します。.versionscripts/link-vmlinux.sh

    環境変数によって上書きできますKBUILD_BUILD_VERSION:

    if [ -z "$KBUILD_BUILD_VERSION" ]; then
        VERSION=$(cat .version 2>/dev/null || echo 1)
    else
        VERSION=$KBUILD_BUILD_VERSION
    fi
    
  • 日付は単なる生のdate呼び出しです:

    if [ -z "$KBUILD_BUILD_TIMESTAMP" ]; then
        TIMESTAMP=`date`
    else
        TIMESTAMP=$KBUILD_BUILD_TIMESTAMP
    fi
    

    同様にユーザー名はwhoamiKBUILD_BUILD_USER)から、ホスト名はhostnameKBUILD_BUILD_HOST)から取得されます。

  • コンパイラのバージョンは から取得されgcc -v、制御できないようです。

質問の変更方法に関するバージョンは次のとおりです。https://stackoverflow.com/questions/23424174/how-to-customize-or-remove-extra-linux-kernel-version-details-shown-at-boot

関連情報