इसकी जानकारी कहां से मिलती है?


40

वास्तव में इसकी जानकारी कहां से मिलती है?

मुझे लगता है कि यह कुछ ऐसा है जो सीधा होना चाहिए। दुर्भाग्य से, मुझे कोई हेडर नहीं मिल रहा है जिसमें सिर्फ जानकारी हो।

कहते हैं कि कोई व्यक्ति मूल उत्पादन को uname/ uname -s से Linuxकुछ और (अनिवार्य रूप से, कर्नेल का नाम बदलकर) बदलना चाहता था ।

वह उचित तरीके से (यानी स्रोत को बदलकर) ऐसा करने के बारे में कैसे / वह जाएगा?

जवाबों:


26

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 फ़ील्ड कैन - यह लिनक्स कर्नेल है और इसके लिए और कुछ भी उपयोग करने के लिए कोई बोधगम्य कारण नहीं है।

हालाँकि, चूंकि यह खुला स्रोत है, आप स्रोत कोड को बदल सकते हैं और जो कुछ भी आप चाहते हैं उसका उपयोग करने के लिए कर्नेल को फिर से जोड़ सकते हैं।


2
domainnameक्षेत्र द्वारा निर्धारित है domainnameआदेश, का उपयोग कर setdomainnameसिस्टम कॉल। इसी तरह, सिस्टम कॉल का उपयोग करके nodenameफ़ील्ड को hostnameकमांड द्वारा सेट किया जाता है sethostname। ( nodename/ hostnameमान को संग्रहीत किया जा सकता है /etc/nodename।)
स्कॉट

2
यह अप्रासंगिक है - सवाल पूछा गया कि इसे कहां बदलना है। तो हां, unameकमांड को इसकी जानकारी सिस्टम कॉल से मिलती है। और सिस्टम कॉल को इसकी जानकारी कहाँ से मिलती है? (उत्तर, यहां अन्य पोस्टरों द्वारा प्रदान किया गया है: यह संकलन के समय कर्नेल में कठिन-कोडित है।)
गाइल्स का SO- बुराई को रोकना '

@ गिल्स: बेमतलब क्या है? यदि उत्तर "अन्य पोस्टरों द्वारा यहां प्रदान किया गया है: यह कर्नेल में हार्ड-कोडेड है ..." मैंने ठीक उसी बात को नोट किया है: "यह सीधे चलने वाले कर्नेल से आता है। मुझे लगता है कि सभी जानकारी कठिन है। इसमें कोडित ... चूंकि यह खुला स्रोत है, आप स्रोत कोड को बदल सकते हैं और जो कुछ भी आप चाहते हैं sysname का उपयोग करने के लिए कर्नेल को फिर से जोड़ सकते हैं । यह एक विन्यास विकल्प नहीं है।
Goldilocks

2
@goldilocks machineकभी क्यों बदलेगा? इसे कर्नेल में हार्डकोड नहीं किया जा सकता है क्योंकि यह हार्डवेयर के लिए अनुकूल हो सकता है, लेकिन निश्चित रूप से तब इसे बूट समय पर सेट किया जाएगा और उसके बाद नहीं बदलेगा। लेकिन नहीं: यह प्रति प्रक्रिया (उदाहरण के i686लिए 32-बिट x86_64 पर संसाधित) रिपोर्ट करने के लिए सेट किया जा सकता है । वैसे, releaseकुछ हद तक (प्रक्रिया) प्रति प्रक्रिया के अनुसार अनुकूलित भी किया जा सकता है setarch i686 --uname-2.6 uname -a
गिल्स एसओ- बुराई को रोकें '

1
@Gilles मैंने संपादित किया है machine, nodenameऔर releaseटिप्पणियों के संदर्भ में प्रश्न में है। फिर, सवाल वास्तव में उन सभी क्षेत्रों के बारे में नहीं था।
गोल्डीलॉक्स

26

डेटा 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);

तार स्वयं शामिल / उत्पन्न / संकलित हैं:

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

और इसमें शामिल / उत्पन्न / utsrelease.h:

#define UTS_RELEASE "3.14.0-v2-v"

UTS_SYSNAME को शामिल / linux / uts.h में परिभाषित किया जा सकता है

#ifndef UTS_SYSNAME
#define UTS_SYSNAME "Linux"
#endif

या मेकफाइल्स में एक #define के रूप में

अंत में, hostname और domainname को / proc / sys / कर्नेल / {hostname, domainname} द्वारा नियंत्रित किया जा सकता है। ये प्रति UTS नामस्थान हैं:

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

यह आम तौर पर एक अच्छा और पूर्ण उत्तर है, लेकिन पोस्टर के प्रश्न निर्देश का उत्तर देते समय यह मूल्य हो सकता है। मेरा मानना ​​है कि यह प्रासंगिक फ़ाइल और recompile में प्रासंगिक प्रविष्टि को बदल देगा। आपने लिखा है "या मेकफ़ाइल्स में एक # दोस्त के रूप में"। क्या आप विस्तार से समझा सकते हैं?
फहीम मीठा

के लिए +1 unshare। किसी तरह मैं इस आदेश को आज तक याद करने में कामयाब रहा। धन्यवाद!
तिनो

और include/generated/compile.hइसके द्वारा जनरेट किया गया है scripts/mkcompile_h: unix.stackexchange.com/a/485962/32558
Ciro Santilli 中心 un un un '

8

एक की मदद से लिनक्स क्रॉस संदर्भ और के अपने उल्लेख /proc/sys/kernel/ostypeहै, मैं पता लगाया ostypeको शामिल / linux / sysctl.h , जहां एक टिप्पणी का कहना है कि नाम को फोन करके जोड़ रहे हैं register_sysctl_table

तो वह कहाँ से कहा जाता है ? एक जगह कर्नेल / utsname_sysctl.c है , जिसमें शामिल हैं / linux / uts.h , जहां हम शामिल हैं:

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

तो, कर्नेल प्रलेखन के रूप में बताता है:

इन मानों को ट्यून करने का एकमात्र तरीका कर्नेल का पुनर्निर्माण करना है

:-)


6

जैसा कि कहीं और टिप्पणी की गई है, जानकारी unamesyscall के साथ आती है , कौन सी जानकारी हार्ड कर्नेल में चल रही है।

संस्करण हिस्सा सामान्य रूप से सेट किया गया है जब से एक नया कर्नेल संकलन Makefile :

VERSION = 3
PATCHLEVEL = 15
SUBLEVEL = 0
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सिसकल को ओवरराइड करने के लिए कर्नेल मॉड्यूल लिख रहा है ; मैंने ऐसा कभी नहीं किया, लेकिन आप इस पेज की जानकारी धारा 4.2 (क्षमा करें, कोई सीधा लिंक नहीं) में पा सकते हैं। ध्यान दें कि वह कोड काफी पुराने कर्नेल का उल्लेख कर रहा है (अब लिनक्स कर्नेल में utsनेमस्पेस है, जो भी उनका मतलब है) इसलिए आपको इसे बहुत बदलना होगा।


सभी को धन्यवाद। मैं पहले से ही जानता था कि इसका कुछ नाम नहीं है। हालाँकि, मैं क्या नहीं कर सकता है कि कैसे और कहाँ स्रोत के अंदर स्ट्रिंग "लिनक्स" को परिभाषित किया गया है। मुझे पता है कि मैं कहां से रनटाइम के दौरान यह जानकारी पा सकता हूं (यह अंदर है / proc / sys / kernel / ostype)। यह पता लगाना कि वास्तव में कर्नेल अपने आप को जानता है कि यह उचित नाम है और अधिक दिलचस्प चीजों में से एक होगा, मैं कहूंगा।
user237251

@ user237251 स्ट्रिंग संदर्भों में कर्नेल स्रोत में "लिनक्स" शब्द के कितने उदाहरण हैं? यदि यह ऐसा नहीं है, तो आप केवल एक पाठ्य खोज के परिणामों की जांच कर सकते हैं और देख सकते हैं कि यह आपको किस दिशा में ले जाता है।
जेएबी

@ जेएबी वे बहुत सारे। सौभाग्य से, kernnewbies.org पर किसी ने मुझे "रहस्य" को सुलझाने में मदद की। Linux को इसका sys नाम /include/Linux/uts.h से मिलता है। यहां देखें: lxr.free-electrons.com/source/include/linux/uts.h?v=3.10
user237251

2

हालांकि मुझे यह इंगित करने के लिए स्रोत में कुछ भी नहीं मिला, मेरा मानना ​​है कि यह बिना नाम के syscall का उपयोग करता है।

man 2 uname

आपको इसके बारे में और बताना चाहिए। यदि ऐसा है तो इसकी जानकारी सीधे कर्नेल से मिल रही है और इसे बदलने से संभवतः पुनर्मूल्यांकन की आवश्यकता होगी।

आप अपने लिए जो कुछ भी चाहते हैं, उसे करने के लिए आप बाइनरी को बदल सकते हैं, बस कृपया w / e प्रोग्राम के साथ इस पर लिखें। कुछ स्क्रिप्ट्स का नकारात्मक पहलू उस आउटपुट पर निर्भर करता है।


3
यदि आप करते हैं strace uname, तो यह पुष्टि करेगा कि unameसिस्टम कॉल का उपयोग किया जाता है।
ग्रीम

1

नाम बदलने का उचित तरीका संकलन हेडर बदलना और दूसरों के सुझाव के अनुसार पुन: संकलन करना होगा। लेकिन मुझे यकीन नहीं है कि जब आप कुछ ऐसा कर सकते हैं तो आप उस परेशानी से क्यों गुजरना चाहेंगे,

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

या और भी

alias uname 'echo whatever'

0

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सही संस्करण संख्या के साथ उत्पन्न फ़ाइलों को बनाने के लिए , उसे ठीक करने और कम से कम DTBs ( ) बनाने की आवश्यकता है।


यह भी पर्याप्त नहीं था। मैं बदलने के लिए था scripts/setlocalversionएक है कि बस करता रहे हैं:

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

तब ऑटोजेनरेटेड फ़ाइलों का पुनर्निर्माण करें:

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

तब मैं डेरेक मोलॉय के सैंपल ड्राइवर का निर्माण कर सकता था और insmodइसे सफलतापूर्वक करने में सक्षम था । स्पष्ट रूप से Module.symversमौजूद नहीं होने के बारे में चेतावनी कोई मायने नहीं रखती थी। सभी लिनक्स यह निर्धारित करने के लिए उपयोग कर रहा था कि मॉड्यूल काम करेगा या नहीं, जो लोकलवर्जन स्ट्रिंग है।


0

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://stackoverflow.com/questions/23424174/how-to-customize-or-remove-extra-linux-kernel-version-details-shown-at-boot

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.