Uname lấy thông tin từ đâu?


40

Trường hợp nào uname thực sự có được thông tin của nó từ đâu?

Tôi nghĩ rằng đây là một cái gì đó nên đơn giản. Thật không may, tôi không thể tìm thấy bất kỳ tiêu đề chỉ chứa thông tin đó.

Giả sử ai đó muốn thay đổi đầu ra cơ bản của uname/ uname -s từ Linuxmột thứ khác (về cơ bản, đổi tên kernel).

Làm thế nào anh ấy / cô ấy sẽ làm điều đó theo cách thích hợp (nghĩa là thay đổi nguồn)?

Câu trả lời:


26

Các unametiện ích nhận thông tin từ các uname()cuộc gọi hệ thống. Nó cư trú một cấu trúc như thế này (xem 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
       };

Điều này đến trực tiếp từ kernel đang chạy. Tôi sẽ giả định tất cả các thông tin được mã hóa cứng vào nó, ngoại trừ có lẽ domainname(và khi nó quay ra, cũng nodename, machinerelease, xem ý kiến). Chuỗi phát hành, từ uname -r, có thể được đặt thông qua cấu hình tại thời điểm biên dịch, nhưng tôi nghi ngờ rất nhiều trường sysname có thể - đó là nhân Linux và không có lý do nào có thể hiểu được để sử dụng bất cứ thứ gì khác.

Tuy nhiên, vì nó là nguồn mở, bạn có thể thay đổi mã nguồn và biên dịch lại kernel để sử dụng bất kỳ tên hệ thống nào bạn muốn.


2
Các domainnamelĩnh vực được thiết lập bởi domainnamelệnh, sử dụng các setdomainnamecuộc gọi hệ thống. Tương tự, nodenametrường được đặt bằng hostnamelệnh, sử dụng lệnh sethostnamegọi hệ thống. ( Giá trị nodename/ hostnamecó thể được lưu trữ trong /etc/nodename.)
Scott

2
Điều này là không liên quan - câu hỏi hỏi nơi để thay đổi điều này. Vì vậy, có, unamelệnh nhận thông tin từ một cuộc gọi hệ thống. Và hệ thống gọi lấy thông tin ở đâu? (Trả lời, được cung cấp bởi các áp phích khác ở đây: nó được mã hóa cứng trong kernel vào thời gian biên dịch.)
Gilles 'SO- ngừng trở nên xấu xa'

@Gilles: Có gì không liên quan? Nếu câu trả lời là "được cung cấp bởi các áp phích khác ở đây: nó được mã hóa cứng vào kernel ..." thì tôi đã nói chính xác điều tương tự: "Điều này xuất phát trực tiếp từ kernel đang chạy. Tôi cho rằng tất cả thông tin đều khó được mã hóa vào nó ... vì nó là nguồn mở, bạn có thể thay đổi mã nguồn và biên dịch lại kernel để sử dụng bất kỳ tên hệ thống nào bạn muốn . Đây không phải là một tùy chọn cấu hình.
goldilocks

2
@goldilocks Tại sao sẽ machinethay đổi? Nó có thể không được mã hóa cứng vào kernel vì nó có thể thích ứng với phần cứng, nhưng chắc chắn sau đó nó sẽ được đặt vào lúc khởi động và sẽ không thay đổi sau đó. Nhưng không: nó có thể được đặt cho mỗi quy trình (ví dụ: báo cáo i686thành 32 bit được xử lý trên x86_64). Nhân tiện, releasecũng có thể được tùy chỉnh theo quy trình ở một mức độ nào đó (thử setarch i686 --uname-2.6 uname -a).
Gilles 'SO- ngừng trở nên xấu xa'

1
@Gilles Tôi đã chỉnh sửa machine, nodenamereleasevào câu hỏi với một tham chiếu đến các bình luận. Một lần nữa, câu hỏi không thực sự về tất cả các lĩnh vực.
goldilocks

26

Dữ liệu được lưu trữ trong 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);

Bản thân các chuỗi nằm trong bao gồm / created / compile.h:

#define UTS_MACHINE "x86_64"
#define UTS_VERSION "#30 SMP Fri Apr 11 00:24:23 BST 2014"

và bao gồm / created / utsrelease.h:

#define UTS_RELEASE "3.14.0-v2-v"

UTS_SYSNAME có thể được xác định trong tệp bao gồm / linux / uts.h

#ifndef UTS_SYSNAME
#define UTS_SYSNAME "Linux"
#endif

hoặc dưới dạng #define trong tệp tạo tệp

Cuối cùng, tên máy chủ và tên miền có thể được kiểm soát bởi / Proc / sys / kernel / {tên máy chủ, tên miền}. Đây là mỗi không gian tên UTS:

# hostname
hell
# unshare --uts /bin/bash
# echo test > /proc/sys/kernel/hostname 
# hostname
test
# exit
# hostname
hell

Đây thường là một câu trả lời hay và đầy đủ, nhưng nó có thể có giá trị trong khi trả lời câu hỏi của người gửi bài. Tôi tin rằng điều này sẽ lên tới - thay đổi mục liên quan trong tệp có liên quan và biên dịch lại. Bạn đã viết "hoặc dưới dạng #define trong makefiles". Bạn có thể xây dựng?
Faheem Mitha

+1 cho unshare. Bằng cách nào đó tôi đã bỏ lỡ lệnh này cho đến ngày hôm nay. Cảm ơn!
Tino

include/generated/compile.hđược tạo bởi scripts/mkcompile_h: unix.stackexchange.com/a/485962/32558
Ciro Santilli

8

Với sự trợ giúp của Tài liệu tham khảo chéo Linux và đề cập đến của bạn /proc/sys/kernel/ostype, tôi đã theo dõi ostypeđể bao gồm / linux / sysctl.h , trong đó một nhận xét nói rằng tên được thêm bằng cách gọi register_sysctl_table.

Vậy nó được gọi từ đâu? Một nơi là kernel / utsname_sysctl.c , bao gồm / linux / uts.h , nơi chúng tôi tìm thấy:

/*
 * Defines for what uname() should return 
 */
#ifndef UTS_SYSNAME
#define UTS_SYSNAME "Linux"
#endif

Vì vậy, như tài liệu kernel nêu:

Cách duy nhất để điều chỉnh các giá trị này là xây dựng lại kernel

:-)


6

Như đã nhận xét ở nơi khác, thông tin đi kèm với tòa nhà unamechọc trời, thông tin được mã hóa cứng trong kernel đang chạy.

Phần phiên bản thường được đặt khi biên dịch kernel mới bằng Makefile :

VERSION = 3
PATCHLEVEL = 15
SUBLEVEL = 0
EXTRAVERSION =

Khi tôi có thời gian chơi biên dịch hạt nhân của mình, tôi thường thêm những thứ ở đó vào EXTRAVERSION; Điều đó đã cho bạn uname -r những thứ như 3.4.1-mytestkernel.

Tôi không hiểu đầy đủ về nó, nhưng tôi nghĩ rằng phần còn lại của thông tin được thiết lập trong Makefilekhoảng 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

Đối với phần còn lại của dữ liệu, tòa nhà sys_unameđược tạo bằng cách sử dụng macro (theo cách khá phức tạp), bạn có thể bắt đầu từ đây nếu bạn cảm thấy phiêu lưu.

Có lẽ cách tốt nhất để thay đổi thông tin đó là viết mô-đun hạt nhân để ghi đè lên tòa nhà uname; Tôi chưa bao giờ làm điều đó nhưng bạn có thể tìm thấy thông tin trong trang này tại mục 4.2 (xin lỗi, không có liên kết trực tiếp). Tuy nhiên, lưu ý rằng mã đó đang đề cập đến một kernel khá cũ (bây giờ kernel Linux có utskhông gian tên, bất kể ý nghĩa của chúng là gì) vì vậy bạn sẽ cần phải thay đổi nó rất nhiều.


Cảm ơn mọi người. Tôi đã biết nó có liên quan đến uname. Tuy nhiên, điều tôi không thể hiểu là làm thế nào và ở đâu bên trong nguồn "Linux" được định nghĩa. Tất cả những gì tôi biết là nơi tôi có thể tìm thấy thông tin đó trong thời gian chạy (nó chứa bên trong / Proc / sys / kernel / lasype). Tìm hiểu chính xác làm thế nào hạt nhân biết chính xác tên của nó sẽ là một trong những điều thú vị hơn, tôi nói.
dùng237251

@ user237251 có bao nhiêu trường hợp của từ "Linux" xảy ra trong nguồn kernel trong ngữ cảnh chuỗi? Nếu nó không nhiều, bạn chỉ có thể kiểm tra kết quả tìm kiếm văn bản và xem nơi dẫn bạn đến.
JAB

@JAB Cách quá nhiều. May mắn thay, ai đó trên kernelnewbies.org đã giúp tôi giải quyết "bí ẩn". Linux có tên sys của nó từ /include/Linux/uts.h. Xem tại đây: lxr.free-electrons.com/source/include/linux/uts.h?v=3.10
user237251

2

Mặc dù tôi không thể tìm thấy bất cứ điều gì trong nguồn để chỉ ra điều này, tôi tin rằng nó sử dụng tòa nhà chọc trời.

man 2 uname

sẽ cho bạn biết thêm về nó. Nếu đó là trường hợp nó nhận thông tin trực tiếp từ kernel và thay đổi thì có lẽ sẽ cần biên dịch lại.

Bạn có thể thay đổi nhị phân để bạn không làm bất cứ điều gì bạn muốn, chỉ cần viết nó với chương trình w / e bạn muốn. Nhược điểm là một số kịch bản dựa trên đầu ra đó.


3
Nếu bạn làm như vậy strace uname, nó sẽ xác nhận rằng unamecuộc gọi hệ thống được sử dụng.
Graeme

1

Cách thích hợp để thay đổi uname sẽ là thay đổi các tiêu đề biên dịch và biên dịch lại như những người khác đề xuất. Nhưng tôi không chắc tại sao bạn lại muốn trải qua nhiều rắc rối như vậy khi bạn có thể làm điều gì đó như,

alias uname 'uname \\!* | sed s/2.6.13/2.6.52/'

hoặc thậm chí

alias uname 'echo whatever'

0

Câu trả lời của Rmano đã cho tôi một phần, nhưng ma thuật thực sự được phát hiện dễ dàng hơn bằng cách chuyển Q=tùy chọn trong makedòng lệnh của bạn trong thư mục nguồn kernel. nó cho phép bạn xem chi tiết, một trong số đó là lời gọi đến một kịch bản : echo "4.4.19$(/bin/sh ./scripts/setlocalversion .)". thực thi đoạn mã tương tự đó cho số phát hành kernel , 4.4.19-00010-ge5dddbf. nếu bạn nhìn vào tập lệnh, nó sẽ xác định số từ hệ thống tạo phiên bản và chạy nó với bash -xhiển thị quy trình chính xác:

+++ 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

Điều này cho tôi thấy rằng nếu tôi muốn xây dựng một mô-đun hạt nhân để làm việc với hạt nhân đang chạy của mình, thì tôi đã phát hành thẻ được gắn thẻ sai và cam kết sai. Tôi cần sửa nó và xây dựng ít nhất DTBs ( make dtbs) để tạo các tệp được tạo với số phiên bản phù hợp.


Hóa ra, điều đó không đủ. Tôi đã phải thay thế bằng scripts/setlocalversionmột cách đơn giản là:

#!/bin/sh
echo -0710GC0F-44F-01QA

sau đó xây dựng lại các tập tin tự động:

make Q= ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- dtbs

sau đó tôi có thể xây dựng trình điều khiển mẫu của Derek Molloy và đã có thể insmodthành công. Rõ ràng cảnh báo về việc Module.symverskhông có mặt không thành vấn đề. tất cả Linux đã sử dụng để xác định xem mô-đun có hoạt động được không, đó là chuỗi chuyển đổi cục bộ.


0

scripts/mkcompile_h

Trong v4.19, đây là tệp tạo include/generated/compile.hvà chứa một số phần thú vị của /proc/version: https://github.com/torvalds/linux/blob/v4.19/scripts/mkcompile_h

  • các #<version>phần xuất phát từ .versiontập tin trên cây xây dựng, mà được tăng lên bất cứ khi nào liên kết xảy ra (yêu cầu tập tin / cấu hình thay đổi) bởi scripts/link-vmlinux.sh.

    Nó có thể bị ghi đè bởi KBUILD_BUILD_VERSIONbiến môi trường:

    if [ -z "$KBUILD_BUILD_VERSION" ]; then
        VERSION=$(cat .version 2>/dev/null || echo 1)
    else
        VERSION=$KBUILD_BUILD_VERSION
    fi
    
  • ngày chỉ là một datecuộc gọi thô :

    if [ -z "$KBUILD_BUILD_TIMESTAMP" ]; then
        TIMESTAMP=`date`
    else
        TIMESTAMP=$KBUILD_BUILD_TIMESTAMP
    fi
    

    và tương tự tên người dùng đến từ whoami( KBUILD_BUILD_USER) và tên máy chủ từ hostname( KBUILD_BUILD_HOST)

  • Phiên bản trình biên dịch đến từ gcc -vvà dường như không thể kiểm soát được.

Dưới đây là cách thay đổi phiên bản nội dung của câu hỏi: https://stackoverflow.com/questions/23424174/how-to-customize-or-remove-extra-linux-kernel-version-details-shown-at-boot

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.