use*_*251 48 linux source kernel
uname 真正从哪里获取信息?
我认为这应该是直截了当的。不幸的是,我找不到任何仅包含该信息的标题。
假设有人想将uname
/ uname -s
from的基本输出更改Linux
为其他内容(本质上是重命名内核)。
他/她将如何以正确的方式(即更改源)进行操作?
V13*_*V13 29
数据存储在 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);
Run Code Online (Sandbox Code Playgroud)
字符串本身在 include/generated/compile.h 中:
#define UTS_MACHINE "x86_64"
#define UTS_VERSION "#30 SMP Fri Apr 11 00:24:23 BST 2014"
Run Code Online (Sandbox Code Playgroud)
并在 include/generated/utsrelease.h 中:
#define UTS_RELEASE "3.14.0-v2-v"
Run Code Online (Sandbox Code Playgroud)
UTS_SYSNAME 可以在 include/linux/uts.h 中定义
#ifndef UTS_SYSNAME
#define UTS_SYSNAME "Linux"
#endif
Run Code Online (Sandbox Code Playgroud)
或作为makefiles中的#define
最后,主机名和域名可以由 /proc/sys/kernel/{hostname,domainname} 控制。这些是每个 UTS 命名空间:
# hostname
hell
# unshare --uts /bin/bash
# echo test > /proc/sys/kernel/hostname
# hostname
test
# exit
# hostname
hell
Run Code Online (Sandbox Code Playgroud)
gol*_*cks 26
该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
};
Run Code Online (Sandbox Code Playgroud)
这直接来自正在运行的内核。我将承担所有的信息是硬编码到它,也许除了domainname
(和事实证明,还nodename
,machine
和release
见注释)。发布字符串 fromuname -r
可以在编译时通过配置进行设置,但我非常怀疑 sysname 字段可以 - 它是 Linux 内核,没有任何理由让它使用其他任何东西。
但是,由于它是开源的,您可以更改源代码并重新编译内核以使用您想要的任何系统名称。
在Linux 交叉参考和您提到的帮助下/proc/sys/kernel/ostype
,我跟踪ostype
到include/linux/sysctl.h,其中有一条评论说名称是通过调用register_sysctl_table
.
那么它是从哪里调用的呢?一个地方是kernel/utsname_sysctl.c,其中包括include/linux/uts.h,我们可以在其中找到:
Run Code Online (Sandbox Code Playgroud)/* * Defines for what uname() should return */ #ifndef UTS_SYSNAME #define UTS_SYSNAME "Linux" #endif
因此,正如内核文档所述:
调整这些值的唯一方法是重建内核
:-)
正如其他地方所评论的,该信息随uname
系统调用一起提供,该信息在正在运行的内核中进行了硬编码。
版本部分通常在Makefile编译新内核时设置:
VERSION = 3
PATCHLEVEL = 15
SUBLEVEL = 0
EXTRAVERSION =
Run Code Online (Sandbox Code Playgroud)
当我有时间玩编译我的内核时,我曾经在 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
Run Code Online (Sandbox Code Playgroud)
对于其余数据,sys_uname
系统调用是使用宏生成的(以一种非常复杂的方式), 如果您喜欢冒险,可以从这里开始。
可能更改此类信息的最佳方法是编写内核模块来覆盖uname
系统调用;我从未这样做过,但您可以在此页面的第 4.2 节中找到信息(抱歉,没有直接链接)。但是请注意,该代码指的是一个相当旧的内核(现在 Linux 内核具有uts
命名空间,无论它们是什么意思),因此您可能需要对其进行大量更改。
虽然我在源代码中找不到任何内容来表明这一点,但我相信它使用了 uname 系统调用。
man 2 uname
应该告诉你更多相关信息。如果是这种情况,它会直接从内核获取信息并更改它可能需要重新编译。
您可以更改二进制文件,让您的 uname 执行您想做的任何操作,只需用您喜欢的程序重写它即可。缺点是某些脚本依赖于该输出。