unameは実際にどこから情報を取得しますか?
これは簡単なことだと思います。残念ながら、その情報だけを含むヘッダーは見つかりません。
セイは、誰かがの基本的な出力変更したいuname
/をuname -s
からLinux
(カーネルの名前を変更し、基本的に)何か他のものに。
彼/彼女はそれを適切な方法(つまり、ソースの変更)でどのように実行しますか?
unameは実際にどこから情報を取得しますか?
これは簡単なことだと思います。残念ながら、その情報だけを含むヘッダーは見つかりません。
セイは、誰かがの基本的な出力変更したいuname
/をuname -s
からLinux
(カーネルの名前を変更し、基本的に)何か他のものに。
彼/彼女はそれを適切な方法(つまり、ソースの変更)でどのように実行しますか?
回答:
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
(また、それは結局のところ、およびnodename
、machine
、およびrelease
、コメントを参照してください)。リリース文字列fromはuname -r
、構成時にコンパイル時に設定できますが、sysnameフィールドができることは非常に疑問です。Linuxカーネルであり、他のものを使用する理由は考えられません。
ただし、オープンソースなので、ソースコードを変更し、必要なsysnameを使用するようにカーネルを再コンパイルできます。
uname
コマンドはシステムコールから情報を取得します。そして、システムコールはどこで情報を取得しますか?(ここで他のポスターから提供された回答:コンパイル時にカーネルにハードコードされています。)
machine
変わるのでしょうか?ハードウェアに適応する可能性があるため、カーネルにハードコーディングされていない可能性がありますが、確実にブート時に設定され、その後は変更されません。ただし、プロセスごとに設定できます(i686
x86_64で処理された32ビットにレポートするなど)。ところで、release
プロセスごとにある程度カスタマイズすることもできます(試してみてくださいsetarch i686 --uname-2.6 uname -a
)。
machine
、nodename
とrelease
のコメントを参照して、質問に。繰り返しますが、質問は実際にはそれらすべてのフィールドに関するものではありませんでした。
データは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
またはメイクファイルの#defineとして
最後に、ホスト名とドメイン名は/ proc / sys / kernel / {hostname、domainname}で制御できます。これらはUTS名前空間ごとです。
# hostname
hell
# unshare --uts /bin/bash
# echo test > /proc/sys/kernel/hostname
# hostname
test
# exit
# hostname
hell
unshare
。どういうわけか私は今日までこのコマンドを見逃していました。ありがとう!
助けを借りてLinuxのクロスリファレンスとのあなたの言及/proc/sys/kernel/ostype
、私が追跡ostype
するために/ linuxの/ sysctl.h含まコメントは名前を呼び出すことによって追加されたことを述べている場合は、register_sysctl_table
。
それはどこから呼び出されるのですか?1つの場所はkernel / utsname_sysctl.cで、include / linux / uts.hが含まれています。
/* * Defines for what uname() should return */ #ifndef UTS_SYSNAME #define UTS_SYSNAME "Linux" #endif
したがって、カーネルのドキュメントには次のように記載されています。
これらの値を調整する唯一の方法は、カーネルを再構築することです
:-)
他の場所でコメントされているように、情報uname
は実行中のカーネルにハードコードされているsyscallに付属しています。
Makefileで新しいカーネルをコンパイルするとき、バージョン部分は通常設定されます:
VERSION = 3
PATCHLEVEL = 15
SUBLEVEL = 0
EXTRAVERSION =
カーネルのコンパイルをする時間があったとき、EXTRAVERSIONでそこに物を追加していました。それはのuname -r
ようなものを与えた3.4.1-mytestkernel
。
私はそれを完全には理解していませんが、残りの情報はMakefile
944行目付近にも設定されていると思います。
# ---------------------------------------------------------------------------
# KERNELRELEASE can change from a few different places, meaning version.h
# needs to be updated, so this check is forced on all builds
uts_len := 64
define filechk_utsrelease.h
if [ `echo -n "$(KERNELRELEASE)" | wc -c ` -gt $(uts_len) ]; then \
echo '"$(KERNELRELEASE)" exceeds $(uts_len) characters' >&2; \
exit 1; \
fi; \
(echo \#define UTS_RELEASE \"$(KERNELRELEASE)\";)
endef
define filechk_version.h
(echo \#define LINUX_VERSION_CODE $(shell \
expr $(VERSION) \* 65536 + 0$(PATCHLEVEL) \* 256 + 0$(SUBLEVEL)); \
echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))';)
endef
$(version_h): $(srctree)/Makefile FORCE
$(call filechk,version.h)
include/generated/utsrelease.h: include/config/kernel.release FORCE
$(call filechk,utsrelease.h)
PHONY += headerdep
headerdep:
$(Q)find $(srctree)/include/ -name '*.h' | xargs --max-args 1 \
$(srctree)/scripts/headerdep.pl -I$(srctree)/include
残りのデータについては、sys_uname
マクロを使用して(かなり複雑な方法で)syscallが生成されます 。冒険心があれば、ここから開始できます。
おそらく、そのような情報を変更する最良の方法は、uname
syscall をオーバーライドするカーネルモジュールを作成することです。私はそれをやったことはありませんが、このページのセクション4.2で情報を見つけることができます(申し訳ありませんが、直接リンクはありません)。ただし、そのコードは非常に古いカーネルを参照していることに注意してください(現在のLinuxカーネルにはuts
名前空間があります)。
ソースにこれを示すものは見つかりませんでしたが、uname syscallを使用していると思います。
man 2 uname
それについてもっと教えてください。その場合は、カーネルから情報を直接取得し、変更するにはおそらく再コンパイルが必要になります。
あなたが好きなことをするためにあなたのためにバイナリを変更することもできますが、w / eプログラムでそれを上書きしてください。一部のスクリプトの欠点は、その出力に依存しています。
strace uname
すると、uname
システムコールが使用されていることが確認されます。
Rmanoの答えは途中で得られましたが、本当の魔法はカーネルソースディレクトリのコマンドラインでQ=
オプションを渡すことで簡単に発見できますmake
。詳細を確認できます。詳細の1つは、スクリプトの呼び出しですecho "4.4.19$(/bin/sh ./scripts/setlocalversion .)"
。同じスニペットを実行すると、カーネルのリリース番号が得られます4.4.19-00010-ge5dddbf
。スクリプトを見ると、バージョン管理システムから番号を判別し、それを実行するとbash -x
正確なプロセスが表示されます。
+++ git rev-parse --verify --short HEAD
++ head=e5dddbf
+++ git describe --exact-match
++ '[' -z '' ']'
++ false
+++ git describe
++ atag=release/A530_os_1.0.0-10-ge5dddbf
++ echo release/A530_os_1.0.0-10-ge5dddbf
++ awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}'
++ git config --get svn-remote.svn.url
++ git diff-index --name-only HEAD
++ grep -qv '^scripts/package'
++ return
+ res=-00010-ge5dddbf
+ echo -00010-ge5dddbf
-00010-ge5dddbf
これが私に示しているのは、実行中のカーネルで動作するカーネルモジュールを構築したい場合、間違ったタグ付きリリースと間違ったコミットをしているということです。make dtbs
適切なバージョン番号で生成されたファイルを作成するために、それを修正し、少なくともDTB()をビルドする必要があります。
でも、それでも十分ではありませんでした。私はscripts/setlocalversion
単にするものに置き換える必要がありました:
#!/bin/sh
echo -0710GC0F-44F-01QA
次に、自動生成されたファイルを再構築します。
make Q= ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- dtbs
その後、Derek Molloyのサンプルドライバーを構築でき、insmod
正常に実行できました。どうやらModule.symvers
存在しないという警告は重要ではなかったようです。モジュールが動作するかどうかを判断するためにLinuxが使用していたのは、そのlocalversion文字列のみでした。
scripts/mkcompile_h
v4.19では、これはを生成するファイルでありinclude/generated/compile.h
、https/proc/version
://github.com/torvalds/linux/blob/v4.19/scripts/mkcompile_hの興味深い部分がいくつか含まれています
#<version>
一部はから来ている.version
リンクはで(ファイル/設定の変更が必要となる)が起こるたびにインクリメントされますビルドツリー、上のファイルscripts/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
同様に、ユーザー名はwhoami
(KBUILD_BUILD_USER
)から、ホスト名はhostname
(KBUILD_BUILD_HOST
)から
コンパイラのバージョンはに由来しgcc -v
、制御できないようです。
質問のスタッフバージョンを変更する方法は次のとおりです。
domainname
フィールドがで設定されているdomainname
使用して、コマンドsetdomainname
システムコールを。同様に、nodename
フィールドはシステムコールhostname
を使用してコマンドによって設定されsethostname
ます。(nodename
/hostname
値に格納されてもよい/etc/nodename
。)