답변:
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변할까요? 하드웨어에 적응할 수 있기 때문에 커널에 하드 코딩되지 않을 수도 있지만, 부팅시 설정되고 그 후에는 변경되지 않습니다. 그러나 아니오 : 프로세스 당 설정할 수 있습니다 (예 : i686x86_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.
나는 그것을 완전히 이해하지 못하지만 나머지 정보는 Makefile944 줄에 설정되어 있다고 생각합니다 .
# ---------------------------------------------------------------------------
# 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_unamesyscall은 매크로를 사용하여 (매우 복잡한 방식으로) 생성됩니다 . 모험심이 느껴지면 여기 에서 시작할 수 있습니다 .
아마도 이러한 정보를 변경하는 가장 좋은 방법은 unamesyscall 을 무시하기 위해 커널 모듈을 작성하는 것입니다 . 나는 그렇게하지 않았지만 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.)