İkili dosyalar farklı CPU mimarileri arasında taşınabilir mi?


16

Amacım gömülü Linux için geliştirme yapabilmek. ARM kullanan çıplak metal gömülü sistemlerde deneyimim var.

Farklı işlemci hedefleri geliştirmek için bazı genel sorularım var. Sorularım aşağıdaki gibidir:

  1. Bir ' x86 hedefi, linux işletim sistemi sürümü xyz ' üzerinde çalışmak üzere derlenmiş bir uygulamam varsa , aynı derlenmiş ikili dosyayı başka bir sistemin ' ARM hedefi, linux işletim sistemi sürümü xyz ' üzerinde çalıştırabilir miyim?

  2. Yukarıdaki doğru değilse, tek yol uygulama kaynak kodunu 'örneğin, arm-linux-gnueabi' ilgili araç zincirini kullanarak yeniden derlemek / yeniden derlemektir.

  3. Benzer şekilde, bir ' x86 hedefi, linux işletim sistemi sürümü xyz ' üzerinde çalışan yüklenebilir bir çekirdek modülüm (aygıt sürücüsü) varsa , aynı derlenmiş .ko'yu başka bir sistemin ' ARM hedefi, linux işletim sistemi sürümü xyz ' üzerine yükleyebilir / kullanabilir miyim ?

  4. Yukarıdaki doğru değilse, tek yol sürücü kaynak kodunu 'örneğin, arm-linux-gnueabi' ilgili araç zincirini kullanarak yeniden derlemek / yeniden derlemek.


27
hayır, evet, hayır, evet.
ocaklar

7
Bir AMD hedefimiz ve bir Intel hedefimiz olmadığını, her ikisi için de tek bir x86 hedefimizin olmadığını anlamaya yardımcı olur. Çünkü Intel ve AMD yeterince uyumludur. Daha sonra, ARM hedefinin belirli bir nedenden dolayı var olduğu açıktır, çünkü ARM CPU'lar Intel / AMD / x86 ile uyumlu değildir.
MSalters

1
Java Runtime gibi taşınabilir bir çalışma zamanı ortamında çalışmak üzere tasarlanmış bayt kodu yoksa, hayır. Gömülü kullanım için kod yazıyorsanız, kodunuzun muhtemelen düşük seviyeli işlemciye özgü optimizasyonlara veya özelliklere bağlı olacağı ve taşınması çok zor olacak ve hedef platform için derlemeden daha fazlasını gerektirecektir (örn. Montaj kodu değişiklikleri, muhtemelen yeniden yazma) birkaç modül veya programın tamamı).
bwDraco

1
@ MSalters: Aslında, bir AMD hedefimiz var: amd64, genellikle x86-64 olarak etiketlenir (x86 genellikle i386'nın yeniden etiketlenmesidir). Neyse ki Intel, AMD mimarisini kopyaladı (ve daha sonra genişletti), böylece 64 bit x 86, amd64 ikili dosyalarını çalıştırabilir.
slebetman

Yanıtlar:


42

Hayır. İkili dosyalar hedef mimari için (yeniden) derlenmelidir ve Linux kutudan yağ ikili dosyaları gibi bir şey sunmaz . Bunun nedeni, kodun belirli bir mimari için makine koduna derlenmesi ve makine kodunun çoğu işlemci ailesi arasında çok farklı olmasıdır (örneğin ARM ve x86 çok farklıdır).

DÜZENLEME: bazı mimarilerin geriye dönük uyumluluk (ve daha nadiren, diğer mimarilerle uyumluluk) düzeyleri sunduğunu belirtmek gerekir; 64 bit CPU'larda, 32 bit sürümlerle geriye dönük uyumluluğa sahip olmak yaygındır (ancak unutmayın: statik olarak bağlanmadığınız sürece C standart kitaplığınız da dahil olmak üzere bağımlı kitaplıklarınız da 32 bit olmalıdır ). Ayrıca , x86 kodunu (sadece 32 bit) çalıştırmanın mümkün olduğu Itanium da çok yavaş olsa da; x86 kodunun düşük yürütme hızı, piyasada çok başarılı olmamasının en azından bir parçasıydı.

Uyumluluk modlarında bile eski CPU'larda daha yeni talimatlarla derlenmiş ikili dosyaları kullanamayacağınızı unutmayın (örneğin, AVX'i Nehalem x86 işlemcilerde 32 bit ikili dosyada kullanamazsınız ; CPU desteklemez.

Çekirdek modüllerin ilgili mimari için derlenmesi gerektiğini unutmayın; Ayrıca, 32 bit çekirdek modülleri 64 bit çekirdeklerde çalışmaz veya bunun tersi de geçerlidir.

Çapraz derleme ikili dosyaları hakkında bilgi için (böylece hedef ARM cihazında bir alet zincirine sahip olmanız gerekmez), aşağıdaki grochmal'ın kapsamlı cevabına bakın.


1
Bazı x86 ikili dosyalarının x64 platformlarında çalışabileceği göz önüne alındığında, x86 ve x64 arasındaki herhangi bir uyumluluk (veya eksikliği) konusunda açıklığa kavuşmak faydalı olabilir. (Bunun Linux'ta durumdan emin değilim, ancak örneğin Windows'ta.)
jpmc26

4
@ jpmc26 Linux'ta mümkündür; ancak önce uyumluluk kitaplıklarını yüklemeniz gerekebilir. x86 desteği, Win64 yüklemelerinin isteğe bağlı olmayan bir parçasıdır. Linux'ta isteğe bağlıdır; Linux dünyasının her şeyin 64bit sürümlerini kullanıma sunmada çok daha uzak olması nedeniyle bazı dağıtımların varsayılan olarak (tümü?) 32bit kitaplıkları yüklü değildir. (Ne kadar yaygın olduğundan emin değilim; ancak daha önce ana akım dağıtımları yürüten insanlardan birkaç sorgu gördüm.)
Dan Firelight tarafından

@ jpmc26 Cevabımı notlarınızla güncelledim; Bundan bahsetmeyi düşündüm ama cevabı karmaşıklaştırmak istemedim.
Elizafox

16

Elizabeth Myers doğrudur, her mimari söz konusu mimari için derlenmiş bir ikili dosya gerektirir. Sisteminizin üzerinde çalıştığından farklı bir mimari için ikili dosyalar oluşturmak için bir cross-compiler.


Çoğu durumda bir çapraz derleyici derlemeniz gerekir. Sadece deneyimim var gcc(ama llvmdiğer derleyicilerin benzer parametrelere sahip olduğuna inanıyorum ). Yapılandırmaya gcceklenerek bir çapraz derleyici elde edilir --target:

./configure --build=i686-arch-linux-gnu --target=arm-none-linux-gnueabi

Sen derlemek gerekir gcc, glibcve binutilsbu parametrelerle (ve hedef makinede çekirdeğin çekirdeği başlıklarını sağlayın).

Uygulamada bu çok daha karmaşıktır ve farklı sistemlerde farklı yapı hataları ortaya çıkar.

GNU araç zincirinin nasıl derleneceğine dair birkaç kılavuz var, ancak sürekli olarak sağlanan ve sunulan komutların ne yaptığını açıklamak için çok iyi bir iş yapan Linux From Scratch'ı tavsiye edeceğim .

Başka bir seçenek, bir çapraz derleyicinin bootstrap derlemesidir. Farklı mimarilere çapraz derleyiciler derleme mücadelesi sayesinde farklı mimarilerde crosstool-ngyaratıldı. Çapraz bir derleyici oluşturmak için gereken araç zinciri üzerinde bir önyükleme verir.

crosstool-ngfarklı mimarilerde birkaç hedef üçlüyü destekler , temelde insanların çapraz derleyici araç zincirinin derlenmesi sırasında ortaya çıkan sorunları çözmek için zaman ayırdıkları bir önyüklemedir.


Birkaç dağıtım paket olarak çapraz derleyiciler sağlar:

Başka bir deyişle, çapraz derleyiciler açısından dağıtımınızın nelere sahip olduğunu kontrol edin. Dağıtımınızda ihtiyaçlarınız için bir çapraz derleyici yoksa, her zaman kendiniz derleyebilirsiniz.

Referanslar:


Çekirdek modülleri notu

Çapraz derleyicinizi elle derliyorsanız, çekirdek modüllerini derlemek için ihtiyacınız olan her şeye sahipsiniz. Bunun nedeni, derlemek için çekirdek başlıklarına ihtiyacınız olmasıdır glibc.

Ancak, dağıtımınız tarafından sağlanan bir çapraz derleyici kullanıyorsanız, hedef makinede çalışan çekirdeğin çekirdek başlıklarına ihtiyacınız olacaktır.


FWIW Fedora, çapraz derleyiciler de içerir.
mattdm

@mattdm - teşekkürler, cevap tweaked, bağlı fedora wiki doğru kısmını aldım inanıyorum.
grochmal

2
Linux Scratch'tan daha kolay bir yol, başka bir mimari için bir Linux ve araç zinciri almaktır crosstool-ng. Bunu listeye eklemek isteyebilirsiniz. Ayrıca, bir GNU çapraz takım zincirini herhangi bir mimari için elle yapılandırmak ve derlemek inanılmaz derecede ilgili ve sadece --targetbayraklardan çok daha sıkıcı . LLVM'nin neden popülerlik kazandığının bir parçası olduğundan şüpheleniyorum; Başka bir mimariyi hedeflemek için yeniden oluşturmaya gerek kalmayacak şekilde tasarlanmıştır - bunun yerine aynı ön uç ve optimize edici kitaplıklarını kullanarak birden fazla arka ucu hedefleyebilirsiniz.
Iwillnotexist Idonotexist

@IwillnotexistIdonotexist - teşekkürler, cevabı daha da değiştirdim. Daha önce çapraz takım çalışmasını hiç duymadım ve çok kullanışlı görünüyor. Yorumunuz benim için oldukça faydalı oldu.
grochmal

9

Son çare olarak (yani kaynak koduna sahip olmadığınızda) qemu, dosboxveya gibi emülatörleri kullanarak farklı bir mimaride ikili dosyalar çalıştırabileceğinizi unutmayın exagear. Bazı emülatörler Linux dışındaki sistemleri taklit etmek için tasarlanmıştır (örn. dosboxMS-DOS programlarını çalıştırmak için tasarlanmıştır ve popüler oyun konsolları için çok sayıda emülatör vardır). Öykünmenin önemli bir ek yükü vardır: öykünülen programlar yerel benzerlerinden 2-10 kat daha yavaş çalışır.

Çekirdek modüllerini yerel olmayan bir CPU'da çalıştırmanız gerekiyorsa, aynı mimari için çekirdek de dahil olmak üzere tüm işletim sistemini taklit etmeniz gerekir. AFAIK Linux çekirdeğinde yabancı kod çalıştırmak imkansızdır.


3
Öykünme için hız cezası genellikle 10x'ten daha yüksektir, ancak bir 4GHz makinede 16Mhz makine için yazılmış bir kod çalıştırmaya çalışıyorsa (250: 1 hız farkı) 50: 1 hız cezasına sahip bir emülatör yine de olabilir kodu orijinal platformda çalıştığından çok daha hızlı çalıştırır.
supercat

7

İkili dosyalar sadece x86 ve ARM arasında taşınabilir değil , farklı ARM lezzetleri de vardır .

Uygulamada karşılaşmanız muhtemel olan ARMv6 vs ARMv7. Raspberry Pi 1 ARMv6, sonraki sürümler ARMv7. Bu yüzden Pi 1 üzerinde çalışmayan daha sonraki kodları derlemek mümkündür.

Neyse ki, açık kaynak ve Özgür yazılımın bir faydası, kaynağa sahip olmaktır, böylece herhangi bir mimaride yeniden oluşturabilirsiniz. Her ne kadar bu biraz çalışma gerektirebilir.

(ARM versiyonlaması kafa karıştırıcıdır, ancak sayıdan önce bir V varsa komut seti mimarisi (ISA) hakkında konuşur. Eğer yoksa, "Cortex M0" veya "ARM926EJS" gibi bir model numarasıdır. ISA numaraları ile yapın.)


2
... ve daha sonra aynı ARM lezzeti için farklı alt katlar ve hatta aynı donanım için farklı ABI'ler var (tüm ARM soft / softfp / hard kayan nokta karışıklığı hakkında düşünüyorum).
Matteo Italia

1
@MatteoItalia Ugh. Çoklu ABI'ler bir snafu, hastalıktan daha kötü bir şeyin tedavisi idi. Bazı ARM'lerin VFP veya NEON kayıtları yoktu, bazıları 16, bazıları 32 idi. Cortex-A8 ve öncesinde NEON motoru çekirdeğin geri kalanının arkasında bir düzine CC çalıştırdı, bu nedenle bir vektör çıkışını GPR maliyetine aktarmak çok. ARM, doğru olanı yapmaya başladı - geniş bir ortak özellik alt kümesini zorunlu kıldı.
Iwillnotexist Idonotexist

7

Her zaman bir platformu hedeflemeniz gerekir . En basit durumda, hedef CPU doğrudan ikili dosyada derlenen kodu çalıştırır (bu kabaca MS DOS'un COM yürütülebilir dosyalarına karşılık gelir). Yeni icat ettiğim iki farklı platformu ele alalım - Ateşkes ve Intellio. Her iki durumda da, ekranda 42 çıktı veren basit bir merhaba dünya programımız olacak. Ayrıca platformdan bağımsız bir şekilde çok platformlu bir dil kullandığınızı varsayacağım, böylece kaynak kodu her ikisi için de aynıdır:

Print(42)

Armistice'te, sayıları yazdırmak için basit bir aygıt sürücünüz vardır, bu yüzden tek yapmanız gereken bir bağlantı noktasına çıkış yapmaktır. Portatif montaj dilimizde, bu şuna benzer:

out 1234h, 42

Ancak, veya Intellio sisteminin böyle bir şeyi yoktur, bu nedenle diğer katmanlardan geçmesi gerekir:

mov a, 10h
mov c, 42
int 13h

Hata! Makine kodunu bile almadan önce ikisi arasında zaten önemli bir fark var! Bu, kabaca Linux ve MS DOS veya bir IBM PC ve bir X-Box arasındaki farkınıza karşılık gelecektir (her ikisi de aynı CPU'yu kullanıyor olsa da).

Ama işletim sistemleri bunun için. Diyelim ki tüm farklı donanım yapılandırmalarının uygulama katmanında aynı şekilde işlenmesini sağlayan bir HAL'miz var - temelde, Mütareke'de bile Intellio yaklaşımını kullanacağız ve "taşınabilir montaj" kodumuz aynı şekilde sonuçlanacak. Bu, hem yerleşik Unix benzeri sistemler hem de Windows tarafından, genellikle gömülü senaryolarda bile kullanılır. İyi - şimdi Armistice ve Intellio'da aynı gerçekten taşınabilir montaj koduna sahip olabiliriz. Peki ya ikili dosyalar?

Tahmin ettiğimiz gibi, CPU'nun ikili dosyayı doğrudan yürütmesi gerekir. mov a, 10hIntellio'da kodumuzun ilk satırına bakalım:

20 10

Ah. O mov a, constantkadar popüler olduğu ortaya çıkıyor, kendi opcode ile kendi talimatı var. Mütareke bunu nasıl ele alıyor?

36 01 00 10

Hmm. Bunun için opcode var mov.reg.imm, bu yüzden atadığımız kaydı seçmek için başka bir argümana ihtiyacımız var. Ve sabit, her zaman 2 baytlık bir kelime, büyük endian notasyonunda - Ateşkes mesajının böyle tasarlandığı, aslında Ateşkes'teki tüm talimatların 4 bayt uzunluğunda, istisna yok.

Şimdi, İkili'yi Armistice üzerinde Intellio'dan çalıştırdığınızı düşünün: CPU talimatı çözmeye başlar, opcode'u bulur 20h. Mütareke'de bu, örneğin and.imm.regtalimata karşılık gelir . 2 baytlık kelime sabitini ( 10XXzaten bir sorun okur ) ve sonra da kayıt numarasını (başka bir XX) okumaya çalışır . Yanlış argümanlarla yanlış talimatı uyguluyoruz. Ve daha da kötüsü, bir sonraki talimat tamamen sahte olacak, çünkü aslında veri olduğunu düşünerek başka bir talimat yedik.

Uygulama çalışma şansı yoktur ve büyük olasılıkla hemen kilitlenir veya kilitlenir.

Şimdi, bu bir yürütülebilir dosyanın her zaman Intellio veya Armistice üzerinde çalıştığını söylemesi gerektiği anlamına gelmez. Sadece CPU'dan ( bashUnix'te olduğu gibi ) veya hem CPU hem de OS'den (Java veya .NET gibi ve günümüzde JavaScript, hatta) bağımsız bir platform tanımlamanız yeterlidir . Bu durumda, uygulama tüm farklı CPU'lar ve işletim sistemleri için bir yürütülebilir dosya kullanabilirken, hedef sistemde platformdan bağımsız kodu CPU aslında çalışabilir. Bu, performans, maliyet veya yetenek isabeti ile gelebilir veya gelmeyebilir.

CPU'lar genellikle ailelerde gelir. Örneğin, x86 ailesinden gelen tüm CPU'ların tam olarak aynı şekilde kodlanmış ortak bir talimatları vardır, bu nedenle her x86 CPU, herhangi bir uzantı kullanmaya çalışmadığı sürece her x86 programını çalıştırabilir (örneğin, kayan nokta işlemleri veya vektör işlemleri). X86'da bugün en yaygın örnekler elbette Intel ve AMD'dir. Atmel, gömülü cihazlar için oldukça popüler olan ARM ailesinde CPU tasarlayan tanınmış bir şirkettir. Apple'ın kendi ARM ARM'leri de var.

Ancak ARM, x86 ile tamamen uyumsuzdur - çok farklı tasarım gereksinimlerine sahiptir ve çok az ortak noktaları vardır. Talimatların tamamen farklı opcodesleri vardır, farklı bir şekilde kodları çözülür, bellek adresleri farklı şekilde ele alınır ... Bazı güvenli işlemleri kullanarak hem x86 CPU hem de ARM CPU üzerinde çalışan bir ikili yapmak mümkün olabilir. ikisi arasında ayrım yapmak ve tamamen farklı iki talimat setine atlamak, ancak yine de her iki versiyon için ayrı talimatlara sahip olduğunuz anlamına gelir, sadece çalışma zamanında doğru seti seçen bir bootstrapper ile.


3

Bu soruyu daha tanıdık gelebilecek bir ortama aktarmak mümkündür. Kıyas yoluyla:

"Çalıştırmak istediğim bir Ruby programım var, ancak platformumda yalnızca bir Python yorumlayıcısı var. Ruby programımı çalıştırmak için Python yorumlayıcısını kullanabilir miyim yoksa programımı Python'da yeniden yazmak zorunda mıyım?"

Komut kümesi mimarisi ("hedef") bir dildir - bir "makine dili" - ve farklı CPU'lar farklı dilleri uygular. Bu yüzden bir ARM işlemcisinden Intel ikili çalıştırmasını istemek, bir Python yorumlayıcısı kullanarak bir Ruby programı çalıştırmaya çalışmak gibidir.


2

gcc, belirli bir CPU'nun '' komut seti '' anlamına gelen '' mimari '' terimlerini kullanır ve "hedef", ABI, libc, endian-ness ve diğer değişkenlerle birlikte CPU ve mimarinin kombinasyonunu kapsar (muhtemelen "çıplak metal" dahil). Tipik bir derleyici sınırlı sayıda hedef kombinasyonuna sahiptir (muhtemelen bir ABI, bir CPU ailesi, ancak muhtemelen hem 32 hem de 64 bit). Çapraz derleyici genellikle üzerinde çalıştığı sistemden başka bir hedefi olan bir derleyici veya birden çok hedefi veya ABI'si olan bir derleyici anlamına gelir (ayrıca buna bakın ).

İkili dosyalar farklı CPU mimarileri arasında taşınabilir mi?

Genel olarak, hayır. Geleneksel terimlerle ikili, belirli bir CPU veya CPU ailesi için yerel nesne kodudur . Ancak, orta derecede yüksek taşınabilirliğe sahip olabilecekleri birkaç durum vardır:

  • bir mimari diğerinin bir üst kümesidir (genellikle en yeni ve en büyük x86 yerine x86 ikili dosyaları i386 veya i686'yı hedefler -march=core2)
  • mimarilerden biri doğal öykünme veya diğerinin çevirisini sağlar ( Crusoe'yu duymuş olabilirsiniz ) veya uyumlu ortak işlemciler sağlar (örneğin PS2 )
  • İşletim sistemi ve çalışma zamanı çoklu diziyi destekler (örn. x86_64'te 32 bit x86 ikili dosyalarını çalıştırma yeteneği) veya VM / JIT'i sorunsuz hale getirme ( Dalvik veya ART kullanan Android )
  • her desteklenen mimari için esasen yinelenen kod içeren "şişman" ikili dosyalar için destek vardır

Bir şekilde bu sorunu çözmeyi başarırsanız, sayısız kütüphane sürümlerinin (glibc sana bakıyorum) diğer taşınabilir ikili sorunu o zaman kendini gösterecektir. (Çoğu yerleşik sistem sizi en azından bu sorundan kurtarır.)

Henüz yapmadıysanız, koşmak gcc -dumpspecsve gcc --target-helpneyle karşı karşıya olduğunuzu görmek için şimdi iyi bir zaman .

Yağ ikili dosyalarının çeşitli dezavantajları vardır , ancak yine de potansiyel kullanımları vardır ( EFI ).

Bununla birlikte, diğer cevaplarda eksik olan iki husus daha vardır: ELF ve ELF yorumlayıcısı ve rasgele ikili formatlar için Linux çekirdeği desteği . Burada gerçek olmayan işlemciler için ikili dosyalar veya baytlar hakkında ayrıntılı bilgi vermeyeceğim, ancak bunları "yerel" olarak ele almak ve Java veya derlenmiş Python bayt kodu ikili dosyalarını çalıştırmak mümkündür, ancak bu ikili dosyalar donanım mimarisinden bağımsızdır (ancak bunun yerine sonuçta yerel bir ikili dosya çalıştıran ilgili VM sürümünde).

Herhangi bir çağdaş Linux sistemi ELF ikili dosyalarını kullanacaktır ( bu PDF'deki teknik detaylar ), dinamik ELF ikili dosyaları söz konusu olduğunda, çekirdek görüntüyü belleğe yüklemekle sorumludur, ancak ELF'de ayarlanan '' tercüman '' ın görevidir. ağır kaldırma yapmak için üstbilgileri. Normalde bu, tüm bağımlı dinamik kitaplıkların kullanılabilir olmasını sağlar (kitaplıkları ve gerekli sembolleri listeleyen diğer bazı yapıları listeleyen '' Dinamik '' bölümün yardımıyla) - ancak bu neredeyse genel amaçlı bir dolaylama katmanıdır.

$ file /bin/ls
/bin/ls: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses \
shared libs), stripped
$ readelf -p .interp /bin/ls
    String dump of section '.interp':
      [     0]  /lib/ld-linux.so.2

( /lib/ld-linux.so.2aynı zamanda bir ELF ikili dosyasıdır, bir tercümanı yoktur ve yerel ikili koddur.)

ELF ile ilgili sorun, binary ( readelf -h /bin/ls) içindeki başlığın belirli bir mimari, sınıf (32- veya 64-bit), endianess ve ABI (Apple'ın "evrensel" yağ ikili dosyaları Mach-O alternatif bir ikili format kullanmasıdır. bunun yerine bu sorunu çözer, bu NextSTEP'den kaynaklanır). Bu, bir ELF yürütülebilir dosyasının çalıştırılacağı sistemle eşleşmesi gerektiği anlamına gelir. Bir kaçış kapağı yorumlayıcıdır, bu herhangi bir yürütülebilir olabilir (başlangıçta ikili olan mimariye özgü alt bölümleri ayıklayan veya haritalayan ve bunları çağıran dahil), ancak yine de sisteminizin çalışmasına izin vereceği ELF türleriyle sınırlandırılırsınız . (FreeBSD ilginç bir yol var Linux ELF dosyalarını işleme , onun brandelfdeğiştirir ELF ABI alanı.)

Linux'ta Mach-O desteği (kullanma binfmt_misc) var, orada bir yağ (32- ve 64-bit) ikili oluşturmayı ve çalıştırmayı gösteren bir örnek var. Kaynak çatalları / ADS , başlangıçta Mac'te yapıldığı gibi, bir geçici çözüm olabilir, ancak yerel Linux dosya sistemi bunu desteklemez.

Aynı şey çekirdek modülleri .koiçin de geçerlidir, dosyalar da ELF'dir (tercüman kümeleri olmamasına rağmen). Bu durumda uname -r, arama yolunda çekirdek sürümünü ( ) kullanan fazladan bir katman vardır, bunun yerine teorik olarak sürüm oluşturma ile ELF'de yapılabilir, ancak bazı karmaşıklık ve az kazançla şüphelenirim.

Başka bir yerde belirtildiği gibi, Linux doğal olarak yağ ikili dosyalarını desteklemez, ancak aktif bir yağ ikili projesi vardır: FatELF . Bu oldu senedir , bu (şimdi doldu) patent endişeleri kısmen standart Çekirdeğe entegre değildi. Şu anda hem çekirdek hem de araç zinciri desteği gerekiyor. Bu binfmt_miscyaklaşımı kullanmaz , bu yan basamaklar ELF başlığı sorunudur ve yağ çekirdeği modüllerine de izin verir.

  1. Bir 'x86 hedefi, linux işletim sistemi sürümü xyz' üzerinde çalıştırmak için derlenmiş bir uygulama varsa, ben sadece aynı derlenmiş ikili başka bir sistemin 'ARM hedef, linux işletim sistemi sürümü xyz' çalıştırabilir miyim?

ELF ile değil, bunu yapmanıza izin vermez.

  1. Yukarıdaki doğru değilse, tek yol uygulama kaynak kodunu 'örneğin, arm-linux-gnueabi' ilgili araç zincirini kullanarak yeniden derlemek / yeniden derlemektir.

Basit cevap evet. (Karmaşık cevaplar öykünmeyi, ara gösterimleri, çevirmenleri ve JIT'i içerir; bir i686 ikilisinin yalnızca burada ilginç olmadıkları i386 opcodlarını kullanmak için "düşürülmesi" ve ABI düzeltmeleri potansiyel olarak yerel kodu çevirmek kadar zordur. )

  1. Benzer şekilde, bir 'x86 hedefi, linux işletim sistemi sürümü xyz' üzerinde çalışan yüklenebilir bir çekirdek modülü (aygıt sürücüsü) varsa, aynı derlenmiş .ko'yu başka bir sistemin 'ARM hedefi, linux işletim sistemi sürümü xyz' üzerine yükleyebilir / kullanabilir miyim ?

Hayır, ELF bunu yapmanıza izin vermeyecek.

  1. Yukarıdaki doğru değilse, tek yol sürücü kaynak kodunu 'örneğin, arm-linux-gnueabi' ilgili araç zincirini kullanarak yeniden derlemek / yeniden derlemek.

Basit cevap evet. FatELF'in .koçok mimarili bir yapı oluşturmanıza izin verdiğine inanıyorum , ancak bir noktada desteklenen her mimari için ikili bir sürüm oluşturulmalıdır. Çekirdek modülleri gerektiren şeyler genellikle kaynakla birlikte gelir ve gerektiği gibi oluşturulur, örneğin VirtualBox bunu yapar.

Bu zaten uzun bir saçma cevap, sadece bir yol daha var. Çekirdeğin zaten özel bir makine olsa da yerleşik bir sanal makinesi var: paketleri eşleştirmek için kullanılan BPF VM . İnsan tarafından okunabilir filtre "port 22 değil ana bilgisayar foo") bir bayt koduna derlenir ve çekirdek paket filtresi bunu yürütür . Yeni eBPF sadece paketler için değil, teorik olarak VM kodunun herhangi bir çağdaş linux arasında taşınabilir olduğunu ve llvm tarafından desteklendiğini, ancak güvenlik nedenleriyle büyük olasılıkla idari kurallar dışında herhangi bir şey için uygun olmayacağını belirtti.


Şimdi, bir ikili yürütülebilir dosya tanımı ile ne kadar cömert olduğunuza bağlı olarak, (ab) binfmt_misckabuk betiği ve ZIP dosyalarını bir kapsayıcı formatı ile yağ ikili desteği uygulamak için kullanabilirsiniz :

#!/bin/bash

name=$1
prog=${1/*\//}      # basename
prog=${prog/.woz/}  # remove extension
root=/mnt/tmpfs
root=$(TMPDIR= mktemp -d -p ${root} woz.XXXXXX)
shift               # drop argv[0], keep other args

arch=$(uname -m)                  # i686
uname_s=$(uname -s)               # Linux
glibc=$(getconf GNU_LIBC_VERSION) # glibc 2.17
glibc=${glibc// /-}               # s/ /-/g

# test that "foo.woz" can unzip, and test "foo" is executable
unzip -tqq "$1" && {
  unzip -q -o -j -d ${root} "$1"  "${arch}/${uname_s}/${glibc}/*" 
  test -x ${root}/$prog && ( 
    export LD_LIBRARY_PATH="${root}:${LD_LIBRARY_PATH}"
    #readlink -f "${root}/${prog}"   # for the curious
    exec -a "${name}" "${root}/${prog}" "$@" 
  )
  rc=$?
  #rm -rf -- "${root}/${prog}"       # for the brave
  exit $rc
}

Buna "wozbin" deyin ve aşağıdaki gibi bir şeyle ayarlayın:

mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
printf ":%s:%s:%s:%s:%s:%s:%s" \
  "woz" "E" "" "woz" "" "/path/to/wozbin" ""  > /proc/sys/fs/binfmt_misc/register

Bu, .wozdosyaları çekirdeğe kaydeder ; wozbinbunun yerine komut dosyası, ilk bağımsız değişkeni, çağrılan .wozdosyanın yoluna ayarlandığında çağrılır .

Taşınabilir (yağ) bir .woz dosya almak için, test.wozbir dizin hiyerarşisine sahip bir ZIP dosyası oluşturmanız yeterlidir :

i686/ 
    \- Linux/
            \- glibc-2.12/
armv6l/
    \- Linux/
            \- glibc-2.17/

Her kemer / OS / libc dizininin içine (rasgele bir seçim) mimariye özgü testikili .sodosyaları ve dosyalar gibi bileşenleri yerleştirin . Çağırdığınızda, gerekli alt dizin bir tmpfs bellek içi dosya sistemine ( /mnt/tmpfsburada) çıkarılır ve çağrılır.


0

berry önyükleme, bazı sorunları çözmek .. ama sorun kol hf, normall / regullAr xux-32 / 64bit için linux distro çalıştırmak için sorun çözmez.

Ben izolinux (usb üzerinde boatloader linux) inşa gerektiğini düşünüyorum ne regullar distro tanıyabilir bazı canlı dönüştürücü ve binmek / canlı hf dönüştürmek.

Neden? Çünkü her linux berry önyükleme ile arm-hf üzerinde çalışmaya dönüştürülebilirse, exaple herer için kullandığımız veya ubuntu creat başlatma diski için kullandığımız izolinux'a bery boot mekanizması oluşturabilir.

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.