답변:
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
, 주석을 참조). 의 릴리스 문자열 uname -r
은 컴파일 타임에 구성을 통해 설정할 수 있지만 sysname 필드는 Linux 커널이므로 다른 것을 사용할 이유가 없습니다.
그러나 오픈 소스이기 때문에 원하는 sysname을 사용하도록 소스 코드를 변경하고 커널을 다시 컴파일 할 수 있습니다.
uname
명령은 시스템 호출에서 정보를 얻습니다. 그리고 시스템 호출은 어디에서 정보를 얻습니까? (여기서 다른 포스터에서 제공하는 답변 : 컴파일 타임에 커널에 하드 코딩되어 있습니다.)
machine
변할까요? 하드웨어에 적응할 수 있기 때문에 커널에 하드 코딩되지 않을 수도 있지만, 부팅시 설정되고 그 후에는 변경되지 않습니다. 그러나 아니오 : 프로세스 당 설정할 수 있습니다 (예 : i686
x86_64에서 처리 된 32 비트로 보고 ). 그건 그렇고, release
프로세스별로 어느 정도 사용자 정의 할 수 있습니다 (try 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
또는 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
unshare
. 어떻게 든 오늘 까지이 명령을 놓쳤습니다. 감사!
는 A의 도움으로 리눅스 상호 참조 및 당신의 언급 /proc/sys/kernel/ostype
, 나는 추적 ostype
할 수 / 리눅스 / sysctl.h 포함 코멘트가 이름을 호출하여 추가 말한다 곳 register_sysctl_table
.
어디에서 호출 합니까? 한 곳은 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
명령 줄에 옵션 을 전달하면 진정한 마술을 쉽게 발견 할 수 있습니다 . 세부 정보를 볼 수 있으며 그 중 하나는 스크립트 호출 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는 모듈이 작동하는지 여부를 로컬 버전 문자열인지 확인하는 데 사용했습니다.
scripts/mkcompile_h
v4.19에서이 파일은를 생성 include/generated/compile.h
하고 다음과 같은 흥미로운 부분을 포함합니다 /proc/version
. https://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
제어 할 수 없습니다.
다음은 질문의 내용 버전을 변경하는 방법입니다. https : //.com/questions/23424174/how-to-customize-or-remove-extra-linux-kernel-version-details-shown-at-boot
domainname
필드는 설정되어domainname
사용하여, 명령setdomainname
시스템 호출을. 마찬가지로nodename
필드는 시스템 호출을hostname
사용하여 명령으로 설정됩니다sethostname
. (nodename
/hostname
값은에 저장 될 수 있습니다/etc/nodename
.)