uname은 어디서 정보를 얻나요?

uname은 어디서 정보를 얻나요?

uname은 실제로 어디서 정보를 얻나요?

나는 이것이 간단해야 할 일이라고 생각합니다. 안타깝게도 해당 정보만 포함된 헤더를 찾을 수 없습니다.

uname누군가가 / uname -s from 의 기본 출력을 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(그리고 결과적으로 nodename, machinerelease, 주석 참조) 를 제외하고 모든 정보가 여기에 하드 코딩되어 있다고 가정합니다 . from 의 릴리스 문자열은 uname -r컴파일 타임에 구성을 통해 설정할 수 있지만 sysname 필드가 그럴 수 있을지 의심스럽습니다. 이는 Linux 커널이므로 다른 것을 사용할 이유가 없습니다.

그러나 오픈 소스이기 때문에 소스 코드를 변경하고 커널을 다시 컴파일하여 원하는 sysname을 사용할 수 있습니다.

답변3

의 도움으로리눅스 상호 참조그리고 에 대한 당신의 언급을 추적 /proc/sys/kernel/ostype했습니다.ostypeinclude/linux/sysctl.h, 주석에는 를 호출하여 이름이 추가된다는 내용이 있습니다 register_sysctl_table.

그럼 그게 어디야?에서 전화? 한 곳은커널/utsname_sysctl.c, 이는 다음을 포함합니다include/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/version.https://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
    

    마찬가지로 사용자 이름은 whoami( KBUILD_BUILD_USER)에서, 호스트 이름은 hostname( KBUILD_BUILD_HOST) 에서 옵니다.

  • 컴파일러 버전은 에서 제공되며 gcc -v제어할 수 없는 것 같습니다.

질문의 내용 버전을 변경하는 방법은 다음과 같습니다.https://stackoverflow.com/questions/23424174/how-to-customize-or-remove-extra-linux-kernel-version-details-shown-at-boot

관련 정보