क्या एक लिनक्स निष्पादन योग्य लिनक्स के एक "स्वाद" पर संकलित किया जाएगा जो एक अलग पर चलता है?


59

विल एक छोटे, अत्यंत सरल कार्यक्रम का निष्पादन, जैसे कि नीचे दिखाया गया है, कि लिनक्स के एक स्वाद पर संकलित किया जाता है एक अलग स्वाद? या इसे फिर से शुरू करने की आवश्यकता होगी?

क्या मशीन आर्किटेक्चर इस तरह के मामले में मायने रखता है?

int main()
{
  return (99);
}

2
बकाया जवाब के लिए सभी को धन्यवाद! मैंने प्रत्याशित होने की तुलना में बहुत अधिक सीखा। मैंने उद्देश्य पर कृत्रिम रूप से कोड को सरल बनाया ताकि यह यथासंभव कुछ पुस्तकालयों पर निर्भर हो; लेकिन मुझे वास्तव में कहना चाहिए कि सामने वाला। मेरे C ++ में अधिकांश प्लेटफ़ॉर्म पर Microsoft टूल जैसे Visual Studio के साथ विकसित करना और फिर कोड को * nix सिस्टम और recompiling पर कोडिंग करना शामिल है।
JCDeen

4
यहाँ व्यक्त कई पहलुओं और विचारों ने मुझे आश्चर्यचकित कर दिया है! मैं ईमानदारी से चाहता हूं कि मैं उत्तर के रूप में कई चुन सकता हूं। सभी को फिर से धन्यवाद! निष्ठा से।
JCDeen

2
एंड्रॉइड भी एक लिनक्स-आधारित ऑपरेटिंग सिस्टम है। हालांकि, बेस्ट ऑफ लक, किसी भी कोड को glibcवहां या उसके विपरीत संकलित करता है । दी, यह पूरी तरह से असंभव नहीं है
undercat

2
कमांड-लाइन टूल की अधिकतम अनुकूलता के लिए, आप ग्लिबक के बजाय uClibc, musl या dietlibc का उपयोग करना चाह सकते हैं, और अपने 32-बिट निष्पादन योग्य ( gcc -m32 -static) को स्टेटिकली लिंक कर सकते हैं । ऐसा करने से, कोई भी i386 या amd64 लिनक्स निष्पादन योग्य चलाने में सक्षम होगा।
पीटी

10
आपको 42 लौटाने चाहिए ! :)
होम्युनकुलस रेटिकुल्ली

जवाबों:


49

निर्भर करता है। IA-32 (Intel 32-bit) के लिए संकलित कुछ amd64 पर चल सकता है क्योंकि Intel पर लिनक्स 32-बिट अनुप्रयोगों (उपयुक्त सॉफ़्टवेयर इंस्टॉल के साथ) के साथ पीछे की संगतता बनाए रखता है। यहां codeरेडहैट 7.3 32-बिट सिस्टम (लगभग 2002, gcc संस्करण 2.96) पर संकलित किया गया है और फिर बाइनरी को सेंटोस 7.4 64-बिट सिस्टम (लगभग 2017) पर कॉपी और रन किया गया है:

-bash-4.2$ file code
code: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.2.5, not stripped
-bash-4.2$ ./code
-bash: ./code: /lib/ld-linux.so.2: bad ELF interpreter: No such file or directory
-bash-4.2$ sudo yum -y install glibc.i686
...
-bash-4.2$ ./code ; echo $?
99

प्राचीन रेडहैट 7.3 से सेंटोस 7.4 (अनिवार्य रूप से रेडहैट एंटरप्राइज लिनक्स 7.4) एक ही "वितरण" परिवार में रह रहा है, इसलिए संभवतः 2002 से 2018 में कुछ अन्य यादृच्छिक लिनक्स वितरण के लिए कुछ यादृच्छिक "खरोंच से लिनक्स" स्थापित करने से बेहतर पोर्टेबिलिटी होगी। ।

Amd64 के लिए संकलित कुछ केवल लिनक्स के 32-बिट रिलीज पर नहीं चलेगा (पुराने हार्डवेयर नए हार्डवेयर के बारे में नहीं जानता है)। यह प्राचीन पुरानी चीजों पर चलने के लिए बनाए गए आधुनिक सिस्टम पर संकलित नए सॉफ्टवेयर के लिए भी सही है, क्योंकि लाइब्रेरी और यहां तक ​​कि सिस्टम कॉल बैकवर्ड पोर्टेबल नहीं हो सकते हैं, इसलिए संकलन ट्रिक्स की आवश्यकता हो सकती है, या एक पुराने संकलक और इसके आगे, या संभवतः प्राप्त कर सकते हैं। पुराने सिस्टम पर संकलन। (यह पुरानी पुरानी चीजों की आभासी मशीनों को आसपास रखने का एक अच्छा कारण है।)

आर्किटेक्चर मायने रखता है; amd64 (या IA-32) ARM या MIPS से काफी अलग है, इसलिए उनमें से एक से बाइनरी को दूसरे पर चलने की उम्मीद नहीं होगी। विधानसभा स्तर mainपर IA-32 पर आपके कोड का अनुभाग इसके माध्यम gcc -S code.cसे संकलित करता है

main:
    pushl %ebp
    movl %esp,%ebp
    movl $99,%eax
    popl %ebp
    ret

जो एक amd64 प्रणाली (Linux सिस्टम पर - OpenBSD पर विपरीत amd64 पर 32-बिट बायनेरिज़ का समर्थन नहीं करता है, के साथ सौदा कर सकता है ; पुराने आर्क के साथ पश्चगामी संगतता हमलावरों को wiggle कमरा देती है, जैसे CVE-2014-8866 और मित्र)। इस बीच एक बड़े-एंडियन MIPS सिस्टम पर main इसके बजाय संकलन करता है:

main:
        .frame  $fp,8,$31
        .mask   0x40000000,-4
        .fmask  0x00000000,0
        .set    noreorder
        .set    nomacro
        addiu   $sp,$sp,-8
        sw      $fp,4($sp)
        move    $fp,$sp
        li      $2,99
        move    $sp,$fp
        lw      $fp,4($sp)
        addiu   $sp,$sp,8
        j       $31
        nop

एक इंटेल प्रोसेसर को पता नहीं होगा कि क्या करना है, और इसी तरह MIPS पर इंटेल असेंबली के लिए।

आप संभवतः विदेशी कोड चलाने के लिए QEMU या कुछ अन्य एमुलेटर का उपयोग कर सकते हैं (शायद बहुत धीरे-धीरे)।

हालाँकि! आपका कोड बहुत सरल कोड है, इसलिए किसी भी चीज़ की तुलना में कम पोर्टेबिलिटी समस्या होगी; कार्यक्रम आमतौर पर पुस्तकालयों का उपयोग करते हैं जो समय के साथ बदल गए हैं (ग्लिस्क, ओपनसेल, ...); उन लोगों के लिए भी विभिन्न पुस्तकालयों के पुराने संस्करणों को स्थापित करने की आवश्यकता हो सकती है (उदाहरण के लिए RedHat आमतौर पर "कंपास" को पैकेज के लिए कहीं और रखता है)

compat-glibc.x86_64                     1:2.12-4.el7.centos

या संभवतः पुरानी चीजों के लिए एबीआई परिवर्तन (एप्लिकेशन बाइनरी इंटरफ़ेस) के बारे में चिंता करें जो कि ग्लिबक का उपयोग करते हैं, या अधिक हाल ही में सी ++ 11 या अन्य सी ++ रिलीज के कारण परिवर्तन। पुस्तकालय के मुद्दों से बचने की कोशिश करने के लिए व्यक्ति स्थैतिक (डिस्क पर द्विआधारी आकार में वृद्धि) को भी संकलित कर सकता है, हालांकि कुछ पुराने बाइनरी ने ऐसा किया था या नहीं यह इस बात पर निर्भर करता है कि क्या पुराने लिनक्स वितरण गतिशील (रेडहैट: हाँ) सबसे अधिक सब कुछ संकलित कर रहा था या नहीं। दूसरी ओर, patchelfगतिशील लाइजर (एलएएफ, लेकिन शायद a.outप्रारूप नहीं ) की तरह चीजें अन्य पुस्तकालयों का उपयोग कर सकती हैं।

हालाँकि! एक कार्यक्रम चलाने में सक्षम होना एक बात है, और वास्तव में इसके साथ कुछ उपयोगी करना। पुराने 32-बिट इंटेल बायनेरिज़ में सुरक्षा संबंधी समस्याएँ हो सकती हैं, यदि वे ओपनएसएसएल के एक संस्करण पर निर्भर करते हैं, जिसमें कुछ भयानक और गैर-बैकपोर्टेड सुरक्षा समस्या है, या प्रोग्राम आधुनिक वेब सर्वर (आधुनिक के रूप में) के साथ बातचीत करने में सक्षम नहीं हो सकता है सर्वर पुराने प्रोटोकॉल और पुराने प्रोग्राम के सिफर को अस्वीकार करते हैं), या एसएसएच प्रोटोकॉल संस्करण 1 अब समर्थित नहीं है, या ...


14
पहला पैराग्राफ: नहीं, इंटेल इसे "इंटेल 64" कहता है (इन दिनों, पहले कुछ अन्य नामों से गुजरने के बाद)। IA-64 इटेनियम को संदर्भित करता है, कुछ x86- संगत को नहीं।
हॉब्स

1
@ होब्स शुक्रिया, मैंने उन संदर्भों को amd64 से बदल दिया है; मैं इंटेल विपणन विभाग को चीजों के नामकरण को छोड़ दूंगा।
thrig

3
स्थैतिक लिंकिंग का उल्लेख क्यों नहीं किया गया?
dcorking

2
यह सिर्फ पुस्तकालय ABI नहीं है जो बदल जाता है - कर्नेल का syscall इंटरफ़ेस समय के साथ-साथ विस्तारित होता जाता है। for GNU/Linux 2.6.32के आउटपुट में (या ऐसे) नोट करें file /usr/bin/ls
चार्ल्स डफी

1
@Wilbert आप शायद याद कर रहे हैं कि Thrig Red Hat Linux की चर्चा कर रहा था जो Red Hat Enterprise Linux से अलग है ।
बॉब

68

संक्षेप में: यदि आप उसी (या संगत) आर्किटेक्चर का उपयोग करके एक होस्ट से दूसरे में एक संकलित बाइनरी ले रहे हैं , तो आप इसे दूसरे वितरण में ले जाना बिल्कुल ठीक हो सकता है । हालाँकि जैसे-जैसे कोड की जटिलता बढ़ती जाती है, वैसे पुस्तकालय से जुड़े होने की संभावना जो स्थापित नहीं होती है; दूसरे स्थान पर स्थापित; या एक अलग संस्करण में स्थापित, बढ़ जाती है। उदाहरण के लिए अपने कोड को लेना, जिसके लिए एक (डेबियन-व्युत्पन्न) उबंटू लिनक्स होस्ट पर lddसंकलित होने gcc -o exit-test exit-test.cपर निम्नलिखित निर्भरता की रिपोर्ट करता है:

$ ldd exit-test
    linux-gate.so.1 =>  (0xb7748000)
    libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb757b000)
    /lib/ld-linux.so.2 (0x8005a000)

जाहिर है कि यह बाइनरी नहीं चलेगी, अगर मैं इसे एक मैक ( ./exit-test: cannot execute binary file: Exec format error) के लिए कहूं । आइए इसे RHEL बॉक्स में ले जाने का प्रयास करें:

$ ./exit-test
-bash: ./exit-test: /lib/ld-linux.so.2: bad ELF interpreter: No such file or directory

ओह प्रिय। ऐसा क्यों हो सकता है?

$ ls /lib/ld-l* # reference the `ldd` output above
ls: cannot access /lib/ld-l*: No such file or directory

यहां तक ​​कि इस उपयोग-मामले के लिए, यह साझाकरण पुस्तकालयों के लापता होने के कारण फोर्कलिफ्टिंग विफल रहा।

हालाँकि, अगर मैं इसे संकलित करता हूं, तो gcc -static exit-test-static exit-test.cइसे बिना पुस्तकालयों के सिस्टम में पोर्ट करना ठीक रहता है। निश्चित रूप से, डिस्क स्थान की कीमत पर:

$ ls -l ./exit-test{,-static}
-rwxr-xr-x  1 username  groupname    7312 Jan 29 14:18 ./exit-test
-rwxr-xr-x  1 username  groupname  728228 Jan 29 14:27 ./exit-test-static

एक और व्यवहार्य समाधान नए मेजबान पर अपेक्षित पुस्तकालयों को स्थापित करना होगा।

यू एंड एल ब्रह्मांड में कई चीजों के साथ, यह कई खाल के साथ एक बिल्ली है, जिनमें से दो ऊपर उल्लिखित हैं।


4
वास्तव में, मैं स्थिर बायनेरिज़ के बारे में भूल गया। कुछ विक्रेता स्थिर बायनेरिज़ को अपनाते हैं, और कुछ मैलवेयर लेखक भी उसी आर्किटेक्चर के
रुई एफ रिबेरो

8
Forklifting ...?
user253751

2
@ मुझे लगता है कि इसका मतलब है कि डेटा (निष्पादन योग्य) को एक वातावरण (डिस्ट्रो) से दूसरे में कॉपी करना, जहां डेटा गंतव्य वातावरण के लिए डिज़ाइन नहीं किया गया है।
वेजेंड्रिया

13
आपका लिनक्स उदाहरण दुर्भाग्य से कृत्रिम है, और वितरण के बजाय आर्किटेक्चर के बारे में आपकी बात को दिखाता है: आपने डेबियन पर 32-बिट बाइनरी का निर्माण किया और इसे 64-बिट आरएचईएल पर चलाने की कोशिश की; उन विभिन्न आर्किटेक्चर हैं ... इतने कम पुस्तकालय निर्भरता वाले समान-आर्किटेक्चर बायनेरिज़ को ठीक-ठीक कॉपी किया जा सकता है।
स्टीफन किट

7
@ मैं यह नहीं कह रहा हूं कि यह अनुचित है, मैं कह रहा हूं कि यह एक खराब उदाहरण है, जिसे देखते हुए डोपघोटी बनाने की कोशिश कर रहे हैं (आप एक वितरण से दूसरे में बायनेरिज़ की नकल नहीं कर सकते - जो गलत है)। बेशक इंटेल पर 64-बिट लिनक्स उचित बुनियादी ढांचे के साथ, 32-बिट निष्पादनयोग्य को भी चलाने का समर्थन करता है। इस मामले में एक वैध उदाहरण IMO एक amd64बाइनरी का निर्माण और इसे किसी अन्य amd64वितरण पर चलाने , या एक i386बाइनरी का निर्माण करने और इसे अन्य i386वितरण पर चलाने का होगा ।
स्टीफन किट

25

उत्कृष्ट @thrig और @DopeGhoti उत्तरों को जोड़ना: लिनक्स सहित यूनिक्स या यूनिक्स-जैसे OS, हमेशा पारंपरिक रूप से डिज़ाइन किए गए थे और बायनेरिज़ की तुलना में स्रोत कोड की पोर्टेबिलिटी के लिए अधिक संरेखित थे।

यदि आपके उदाहरण में हार्डवेयर विशिष्ट या सरल स्रोत के रूप में कुछ भी नहीं है, तो आप इसे किसी भी समस्या के बिना लिनक्स या आर्किटेक्चर के किसी भी संस्करण के बीच स्रोत कोड के रूप में तब तक आगे बढ़ा सकते हैं, जब तक कि गंतव्य सर्वरों में C विकास पैकेज स्थापित न हो जाएं , आवश्यक पुस्तकालयों, और इसी विकास पुस्तकालयों को स्थापित किया।

जहां तक ​​समय में लिनक्स दूर के पुराने संस्करणों से अधिक उन्नत कोड को पोर्ट करने या विभिन्न कर्नेल संस्करणों के लिए कर्नेल मॉड्यूल जैसे अधिक विशिष्ट कार्यक्रमों के लिए, आपको अपग्रेड किए गए पुस्तकालयों / एपीआई / एबीआई के लिए स्रोत कोड को अनुकूलित और संशोधित करना पड़ सकता है।


19

द्वारा डिफ़ॉल्ट , तो आप लगभग निश्चित रूप से बाहरी पुस्तकालयों के साथ समस्याएं आ जाएगा। कुछ अन्य उत्तर उन समस्याओं के बारे में अधिक जानकारी में जाते हैं, इसलिए मैं उनके काम की नकल नहीं करूंगा।

आप कर सकते हैं यहां तक कि गैर तुच्छ लोगों - -, हालांकि, कई कार्यक्रमों संकलन लिनक्स सिस्टम के बीच पोर्टेबल होने के लिए। कुंजी टूलकिट है जिसे लिनक्स मानक बेस कहा जाता है । LSB सिर्फ पोर्टेबल अनुप्रयोगों के इन प्रकार बनाने के लिए बनाया गया है। LSB v5.0 के लिए एक आवेदन संकलित करें और यह किसी भी अन्य लिनक्स पर्यावरण (उसी वास्तुकला का) पर चलेगा जो LSB v5.0 को लागू करता है। कुछ लिनक्स डिस्ट्रोस एलएसबी कंप्लेंट हैं, और अन्य में एलएसबी टूलकिट / लाइब्रेरी शामिल हैं जो एक इंस्टाल करने योग्य पैकेज के रूप में हैं। यदि आप एलएसबी टूल्स ( lsbccलाइक फॉर रैपर gcc) और लाइबर्स के एलएसबी संस्करण का उपयोग करके अपना एप्लिकेशन बनाते हैं, तो आप एक पोर्टेबल एप्लिकेशन बनाएंगे।


और qemuआप विभिन्न आर्कटक्चर के लिए संकलित कार्यक्रम भी चला सकते हैं, (उच्च प्रदर्शन नहीं, लेकिन आप उन्हें चला सकते हैं)
जैसन

1
मैं लिनक्स स्टैंडर्ड बेस टूलकिट के बारे में भी नहीं जानता था, इसलिए धन्यवाद! मैंने बहुत समय पहले C / C ++ के साथ काम करना शुरू किया था, इसलिए इन उत्तरों में बहुत सारी जानकारी मेरे लिए नई है। और बहुत मददगार है।
JCDeen

1
विकिपीडिया के लेख में कहा गया है कि डेबियन और उबंटू एलएसबी को लागू नहीं करते हैं (और ऐसा करने का कोई इरादा नहीं है।)
ब्लैकजैक

2
@ ब्लैकजैक- डिस्ट्रो खुद को कोर ओएस के हिस्से के रूप में 100% लागू नहीं करता है, लेकिन आप एलएसबी-संगतता लाइब्रेरी और टूलकिट को वैकल्पिक पैकेज के रूप में स्थापित कर सकते हैं। मैंने एलएसबी-संगत कार्यक्रमों के निर्माण के लिए उबंटू (उदाहरण के लिए) का उपयोग किया है जो तब सुज़ और सेंटोस पर चले गए थे, आपको बस apt-get installकुछ पैकेजों की आवश्यकता है।
बटा

10

शायद।

जो चीजें इसे तोड़ती हैं उनमें शामिल हैं।

  1. विभिन्न आर्किटेक्चर। स्पष्ट रूप से पूरी तरह से अलग-अलग आर्किटेक्चर काम नहीं करेंगे (जब तक कि आपके पास Binfmt_misc के साथ उपयोगकर्ता मोड qemu जैसा कुछ नहीं है लेकिन यह शायद ही एक सामान्य कॉन्फ़िगरेशन है)। x86 बायनेरिज़ am64 पर काम कर सकते हैं लेकिन केवल तभी जब आवश्यक 32-बिट लाइब्रेरी उपलब्ध हो।
  2. लाइब्रेरी संस्करण। यदि यह गलत है, तो यह पुस्तकालय को बिल्कुल नहीं मिलेगा। यदि विचलन समान है, लेकिन बाइनरी लाइब्रेरी के नए संस्करण के खिलाफ बनाया गया है, तो इसके खिलाफ चल रहा है तो नए प्रतीकों या प्रतीकों के नए संस्करणों के कारण लोड करने में विफल हो सकता है। विशेष रूप से ग्लिबक प्रतीक संस्करण का एक भारी उपयोगकर्ता है, इसलिए एक नए ग्लिबक के खिलाफ निर्मित बायनेरिज़ एक पुराने ग्लिब के साथ असफल होने की बहुत संभावना है।

यदि आप किसी भी तेजी से बदलते पुस्तकालयों का उपयोग करने से बचते हैं, तो वास्तुकला के परिवर्तनों से बचें और सबसे पुराने डिस्ट्रो पर निर्माण करें जो आप लक्षित करना चाहते हैं, आपके पास कई विकृतियों पर एक बाइनरी काम करने का एक अच्छा मौका है।


4

पहले उल्लिखित कुछ चीजों के अलावा, निष्पादन योग्य फ़ाइल प्रारूप में कुछ बदलाव हुए हैं। अधिकांश भाग के लिए, linux ELF का उपयोग करता है, लेकिन पुराने संस्करण a.out या COFF का उपयोग करते हैं।

विकीहोल की शुरुआत:

https://en.wikipedia.org/wiki/Comparison_of_executable_file_formats

नए स्वरूपों को चलाने के लिए पुराने संस्करण प्राप्त करने का एक तरीका हो सकता है, लेकिन मैंने व्यक्तिगत रूप से कभी इस पर ध्यान नहीं दिया है।


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