Uname bu bilgiyi nereden alıyor?


40

Uname gerçekten bilgisini nereden alıyor?

Bunun basit olması gereken bir şey olduğunu düşünüyorum. Ne yazık ki, sadece bu bilgiyi içeren herhangi bir başlık bulamıyorum.

De ki birisi temel çıkışını değiştirmek istedim uname/ ' uname -s dan Linux(kernel yeniden adlandırma, esasen) başka bir şeye.

Bunu doğru şekilde yapmaya (yani, kaynağı değiştirmeye) nasıl devam edecek?

Yanıtlar:


26

Yardımcı unameprogram bilgisini uname()sistem çağrısından alır. Böyle bir yapıyı doldurur (bkz. 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
       };

Bu doğrudan çalışan çekirdekten gelir. Ben, tüm bilgiler kodlanmış içine olduğunu varsayalım belki hariç ediyorum domainname(ve çıkıyor gibi, aynı zamanda nodename, machineve release, yorum bakınız). Yayın dizisi, uname -rderleme zamanında konfigürasyon yoluyla ayarlanabilir, ancak sysname alanının yapabileceğinden çok şüpheliyim - bu Linux çekirdeğidir ve başka bir şey kullanması için makul bir sebep yoktur.

Ancak, açık kaynak olduğundan, kaynak kodunu değiştirebilir ve çekirdeği istediğiniz sysname adını kullanmak için yeniden derleyebilirsiniz.


2
domainnameAlan tarafından ayarlanır domainnamekullanarak, komuta setdomainnamesistemi çağrısı. Benzer şekilde, nodenamealan sistem çağrısı hostnamekullanılarak komut tarafından ayarlanır sethostname. ( nodename/ hostnameDeğeri saklanabilir /etc/nodename.)
Scott

2
Bu konu dışı - soru bunun nerede değiştirileceğini sordu. Yani evet, unamekomut bilgilerini sistem çağrısından alır. Peki sistem çağrısı nereden bilgi alıyor? (Buradaki diğer posterler tarafından verilen cevap: derleme zamanında çekirdeğe kodlanmış
durumdadır

@Gilles: Alakasız olan nedir? Cevap "burada diğer posterler tarafından sağlanıyorsa: çekirdeğe kodlanmış ..." notu Aynı şeyi söyledim: "Bu doğrudan çalışan çekirdekten geliyor. Tüm bilgilerin zor olduğunu varsayıyorum . içine kodlanmış ... açık kaynak olduğundan, kaynak kodunu değiştirebilir ve çekirdeği istediğiniz herhangi bir sysname adını kullanmak için yeniden derleyebilirsiniz . Bu bir yapılandırma seçeneği değildir
goldilocks

2
@goldilocks Neden değişsin ki machine? Donanıma kodlanmış olmayabilir, çünkü donanıma adapte olabilir, ancak kesinlikle önyükleme sırasında ayarlanır ve bundan sonra değişmez. Ancak hayır: işlem başına ayarlanabilir (örn i686. X86_64'te işlenen 32 bit'e raporlama ). Bu arada, releaseişlem başına bir dereceye kadar da özelleştirilebilir (deneyin setarch i686 --uname-2.6 uname -a).
Gilles 'SO- kötülük olmayı bırak'

1
@Gilles Düzenleme yaptığım machine, nodenameve releaseyorumların bir başvuru ile gündeme. Yine, soru aslında tüm bu alanlar hakkında değildi.
goldilocks

26

Veriler init / version.c dosyasında saklanır:

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);

Dizelerin kendileri include / generation / compile.h dosyasındadır:

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

ve dahil / içinde / utsrelease.h:

#define UTS_RELEASE "3.14.0-v2-v"

UTS_SYSNAME / linux / uts.h dosyasında tanımlanabilir

#ifndef UTS_SYSNAME
#define UTS_SYSNAME "Linux"
#endif

veya makefiles içinde #define olarak

Son olarak, hostname ve domainname / proc / sys / kernel / {hostname, domainname} tarafından kontrol edilebilir. Bunlar UTS ad alanına göre:

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

Bu genellikle iyi ve eksiksiz bir cevaptır, ancak posterin doğrudan sorusuna cevap verirken faydalı olabilir. Bunun, ilgili dosyadaki ilgili girişi değiştirip yeniden derleyeceğine inanıyorum. "Veya makefiles içinde #define olarak" yazdınız. Ayrıntılı olabilir misiniz?
Faheem Mitha

İçin +1 unshare. Her nasılsa bugüne kadar bu komutu kaçırmayı başardım. Teşekkürler!
Tino

Ve include/generated/compile.hşu kişiler tarafından üretilir scripts/mkcompile_h: unix.stackexchange.com/a/485962/32558
Ciro Santilli 事件 改造 中心 法轮功 六四 事件

8

Bir yardımıyla Linux Çapraz Referans ve bahis ile /proc/sys/kernel/ostype, ben takip ostypeetmek / linux / sysctl.h dahil Yorum adlandıran arayarak eklenir yazan yere register_sysctl_table.

Peki bu nereden denir ? Bir yerdir çekirdek / utsname_sysctl.c , içeren / linux / uts.h dahil , biz bulmak burada:

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

Böylece, çekirdek belgelerinde belirtildiği gibi:

Bu değerleri ayarlamanın tek yolu çekirdeği yeniden inşa etmektir.

:-)


6

Başka bir yerde yorumlandığı gibi, bilgiler unameçalışan çekirdeğe kodlanmış olan sistem çağrısı ile birlikte gelir .

Sürüm kısmı normalde Makefile tarafından yeni bir çekirdek derlenirken ayarlanır :

VERSION = 3
PATCHLEVEL = 15
SUBLEVEL = 0
EXTRAVERSION =

çekirdeklerimi derlemek için zamanım olduğunda, şuraya EXTRAVERSION'da şeyler eklerdim; Bu sana uname -r gibi şeyler verdi 3.4.1-mytestkernel.

Tam olarak anlamıyorum, ancak bilgilerin geri kalanının Makefile944 hattı boyunca da kurulduğunu düşünüyorum:

# ---------------------------------------------------------------------------

# 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

Verilerin geri kalanı için, sys_unamesistem çağrılan makrolar (oldukça sarsılmış bir şekilde) kullanılarak üretilir, maceracı hissediyorsanız buradan başlayabilirsiniz .

Muhtemelen bu tür bilgileri değiştirmenin en iyi yolu, unamesistem çağrısını geçersiz kılmak için bir çekirdek modülü yazmaktır; Bunu hiç yapmadım ama bu sayfada bilgileri bölüm 4.2'de bulabilirsiniz (özür dilerim, doğrudan bağlantı yok). Bununla birlikte, bu kodun oldukça eski bir çekirdeğe (artık Linux çekirdeğinin utsad alanları vardır, ne demek istediklerine) atıfta bulunduğuna dikkat edin, bu yüzden muhtemelen çok fazla değiştirmeniz gerekecektir.


Herkese teşekkürler. İsimsiz bir şey yapabileceğini zaten biliyordum. Ancak, anlayamadığım şey kaynağın içinde ve nerede "Linux" dizgisinin tanımlanmasıdır. Tek bildiğim, çalışma sırasında bu bilgiyi nerede bulabileceğimdir (/ proc / sys / kernel / ostype içinde bulunur). Çekirdeğin kendisinin doğru adın ne olduğunu tam olarak bildiğini bulmak, daha ilginç şeylerden biri olacağını söyleyebilirim.
user237251

@ user237251 string bağlamında çekirdek kaynağında "Linux" sözcüğünün kaç örneği var? Çok fazla değilse, yalnızca metinsel bir aramanın sonuçlarını inceleyebilir ve bunun sizi nereye götürdüğünü görebilirsiniz.
JAB,

@JAB Way çok fazla. Neyse ki, kernelnewbies.org'daki biri "gizemi" çözmeme yardım etti. Linux, sys adını /include/Linux/uts.h adresinden alır. Buraya bakın: lxr.free-electrons.com/source/include/linux/uts.h?v=3.10
user237251

2

Bunu belirtmek için kaynağında hiçbir şey bulamadığım halde, unys çağrısını kullandığını düşünüyorum.

man 2 uname

sana daha fazla anlatmalıyım. Bu durumda bilgiyi doğrudan çekirdekten alıyor ve değiştirmek de muhtemelen yeniden derlenmeyi gerektiriyor.

İstediğiniz şeyi yapmak için uname için ikili dosyasını değiştirebilirsiniz, sadece üzerine istediğiniz programı yazın. Dezavantajı bazı scriptler olması bu çıktıya dayanıyor.


3
Bunu yaparsanız strace uname, unamesistem çağrısının kullanıldığını onaylar .
Graeme

1

Uname'i değiştirmenin doğru yolu, derleme başlıklarını değiştirmek ve diğerlerinin önerdiği gibi yeniden derlemektir. Ama neden böyle bir şey yapabileceğin zaman bu kadar belaya girmek istediğinden emin değilim.

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

ya da

alias uname 'echo whatever'

0

Rmano'nun cevabı beni yarı yolda bıraktı , ancak asıl sihir, çekirdek kaynak dizinindeki komut satırında bulunan Q=seçeneği ileterek daha kolay keşfedilebilir make. Eğer bir komut dosyası için bir çağrıdır bunlardan biri ayrıntıları görmenizi sağlar: echo "4.4.19$(/bin/sh ./scripts/setlocalversion .)". aynı snippet'in çalıştırılması, çekirdeğin sürüm numarasını verir 4.4.19-00010-ge5dddbf. Eğer betiğe bakarsanız, versiyonlama sistemindeki sayıyı belirler ve çalıştırarak bash -xkesin işlemi gösterir:

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

Bunun bana gösterdiği şey, çalışan çekirdeğimle çalışmak için bir çekirdek modülü kurmak istersem, yanlış etiketlenmiş sürümde ve yanlış işlemlerde bulunuyorum. make dtbsOluşturulan dosyaları doğru sürüm numarasıyla oluşturmak için bunu düzeltmem ve en azından DTB'leri ( ) oluşturmam gerekiyor.


çıkıyor, bu bile yeterli değildi. Ben scripts/setlocalversionsadece bir şeyle değiştirmek zorunda kaldım :

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

sonra otomatikleştirilmiş dosyaları yeniden oluşturun:

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

o zaman Derek Molloy'un örnek sürücüsünü kurabilirim ve insmodbaşarılı bir şekilde başarabilirdim . Görünüşe göre var Module.symversolmama hakkındaki uyarının önemi yoktu. tüm Linux, modülün işe yarayıp yaramadığını belirlemek için kullanıyordu, bu yerel sürüm dizesiydi.


0

scripts/mkcompile_h

V4.19'da, bu, aşağıdakileri üreten include/generated/compile.hve birkaç ilginç bölüm içeren dosyadır /proc/version: https://github.com/torvalds/linux/blob/v4.19/scripts/mkcompile_h

  • bu #<version>kısım .version, bağlantı gerçekleştiğinde (dosya / yapılandırma değişiklikleri gerektiriyorsa) artırılan derleme ağacındaki dosyadan gelir scripts/link-vmlinux.sh.

    KBUILD_BUILD_VERSIONOrtam değişkeni tarafından geçersiz kılınabilir :

    if [ -z "$KBUILD_BUILD_VERSION" ]; then
        VERSION=$(cat .version 2>/dev/null || echo 1)
    else
        VERSION=$KBUILD_BUILD_VERSION
    fi
    
  • tarih sadece ham bir dateçağrıdır:

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

    ve benzer şekilde kullanıcı adı gelir whoami( KBUILD_BUILD_USER) ve makine ismini hostname( KBUILD_BUILD_HOST)

  • Derleyici sürümü geliyor gcc -vve kontrol edilemez gibi görünüyor.

İşte sorunun bir şeyler nasıl değiştirileceği: https://stackoverflow.com/questions/23424174/how-to-customize-or-remove-extra-linux-kernel-version-details-shown-at-boot

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.