Uygulama ikili arabirimi (ABI) nedir?


493

Bir ABI'nın ne olduğunu net bir şekilde anlamadım. Lütfen beni Wikipedia makalesine yönlendirmeyin. Eğer anlayabilseydim, burada böyle uzun bir yazı yayınlamak olmazdım.

Bu, farklı arayüzler hakkındaki zihniyetim:

TV uzaktan kumandası, kullanıcı ve TV arasındaki bir arabirimdir. Mevcut bir varlıktır, ancak tek başına yararsızdır (herhangi bir işlevsellik sağlamaz). Uzaktan kumandadaki bu düğmelerin her biri için tüm işlevler televizyon setinde uygulanır.

Arayüz: Bu arasında bir "Mevcut varlık" tabakasıdır functionalityve consumerbu işlevselliği. Bir arayüz tek başına hiçbir şey yapmaz. Sadece geride yatan işlevselliği çağırıyor.

Şimdi kullanıcının kim olduğuna bağlı olarak farklı tipte arayüzler vardır.

Komut Satırı Arabirimi (CLI) komutları var olan varlıklardır, tüketici kullanıcıdır ve işlevsellik geride kalır.

functionality: bu arayüzü tanımladığımız bir amacı çözen yazılım fonksiyonum.

existing entities: komutlar

consumer: kullanıcı

Grafiksel Kullanıcı Arayüzü (GUI) penceresi, düğmeler, vb.

functionality: Bu arayüzü açıkladığımız bazı problemleri çözen yazılım fonksiyonum.

existing entities: pencere, düğmeler vb.

consumer: kullanıcı

Uygulama Programlama Arabirimi (API) işlevleri (veya daha doğru olması için) arabirimleri (arabirim tabanlı programlamada) varolan varlıklardır, burada tüketici bir kullanıcı değil, başka bir programdır ve yine işlevsellik bu katmanın arkasındadır.

functionality: Bu arayüzü açıkladığımız bazı problemleri çözen yazılım fonksiyonum.

existing entities: Fonksiyonlar, Arayüzler (fonksiyon dizisi).

consumer: başka bir program / uygulama.

Uygulama İkili Arabirimi (ABI) Sorunum burada başlıyor.

functionality: ???

existing entities: ???

consumer: ???

  • Farklı dillerde yazılım yazdım ve farklı arayüzler (CLI, GUI ve API) sağladım, ancak herhangi bir ABI sağlayıp sağlamadığımı bilmiyorum.

Wikipedia diyor ki:

ABI'ler,

  • veri türü, boyutu ve hizalaması;
  • işlevlerin bağımsız değişkenlerinin nasıl iletildiğini ve alınan değerleri döndürdüğünü kontrol eden çağrı kuralı;
  • sistem çağrı numaraları ve uygulamanın işletim sistemine nasıl sistem çağrısı yapması gerektiği;

Diğer ABI'ler,

  • C ++ ad yönetimi,
  • istisna yayılımı ve
  • aynı platformdaki derleyiciler arasında çağrı kuralı, ancak platformlar arası uyumluluk gerektirmez.
  • Bu detaylara kimin ihtiyacı var? Lütfen işletim sistemini söylemeyin. Montaj programlamasını biliyorum. Bağlamanın ve yüklemenin nasıl çalıştığını biliyorum. İçinde ne olduğunu tam olarak biliyorum.

  • C ++ ad yönetimi neden geldi? İkili seviyede konuştuğumuzu sanıyordum. Diller neden giriyor?

Her neyse, tam olarak ne içerdiğini görmek için [PDF] Sistem V Uygulaması İkili Arabirim Sürümü 4.1'i (1997-03-18) indirdim . Çoğu mantıklı gelmedi.

  • ELF dosya biçimini tanımlamak için neden iki bölüm (4. ve 5.) içeriyor ? Aslında, bu şartnamenin sadece iki önemli bölümü bunlar. Diğer bölümler "işlemciye özeldir". Her neyse, tamamen farklı bir konu olmasına rağmen. ELF dosya biçimi spesifikasyonları öyle söyleme lütfen vardır ABI. Tanıma göre bir arayüz olmaya hak kazanmaz .

  • Biliyorum, bu kadar düşük bir seviyede konuştuğumuz için çok spesifik olmalı. Ama "komut kümesi mimarisine (ISA)" nasıl özel olduğundan emin değilim?

  • Microsoft Windows ABI'yi nerede bulabilirim?

Yani, bunlar beni rahatsız eden başlıca sorgular.


7
"Lütfen söyleme, İşletim Sistemi" Derleyicilerin ABI'yi bilmesi gerekir. Bağlayıcıların ABI'yi bilmesi gerekir. Çekirdek, programı düzgün çalışması için RAM'de ayarlamak için ABI'yi bilmelidir. C ++ ile ilgili olarak aşağıya bakın, aşırı yükleme ve özel yöntemler nedeniyle etiketleri kasıtlı olarak anlamsız hale getirir ve bağlayıcı ve diğer herhangi bir derleyicinin onunla çalışmak için uyumlu bir ad yönetimi, yani aynı ABI olması gerekir.
Justin Smith

8
Bence soru çok açık; tam olarak beklenen cevap formatının ne olduğunu açıklamakla birlikte kabul edilebilir tek bir tatmin edici cevap değildir.
legends2k

3
@ legends2k Bu konudaki benim düşüncem OP'nin bir ABI'nin ne olduğunu gerçekten bilmesi, ama bunun farkında olmaması. Programcıların büyük çoğunluğu asla bir ABI tasarlamayacak veya vermeyecektir, çünkü bu OS / platform tasarımcılarının işi.
Şubat'ta JesperE

4
@JesperE: Demek istediğini kabul ediyorum. Ama muhtemelen OP, ABI sağlamaya gerek duymasa da, uygun gördüğü formatta açıkça bilmek istiyor.
legends2k

2
Ben cahildim. Son zamanlarda tüm bunlarla çalışırken. ABI'nin gerçekte ne olduğunu anladım. Evet, şablonumun hatalı olduğunu kabul ediyorum. ABI'yi şablonuma sığdırmak uygun değil. Teşekkürler JasperE. Cevabınızı gerçekleştirmek sadece iş tecrübesi aldı.
pençeleri

Yanıtlar:


534

"ABI" yi anlamanın kolay bir yolu onu "API" ile karşılaştırmaktır.

Bir API kavramını zaten biliyorsunuz. Örneğin, bazı kitaplıkların veya işletim sisteminizin özelliklerini kullanmak istiyorsanız, bir API'ye karşı programlayabilirsiniz. API, harici bileşenin işlevselliğine erişmek için kodunuzda kullanabileceğiniz veri türleri / yapıları, sabitler, işlevler vb.

Bir ABI çok benzer. Bunu bir API'nın derlenmiş versiyonu (veya makine dili düzeyinde bir API olarak) düşünün. Kaynak kodu yazdığınızda, kitaplığa bir API aracılığıyla erişirsiniz. Kod derlendikten sonra, uygulamanız kütüphanedeki ikili verilere ABI üzerinden erişir. ABI, derlenmiş uygulamanızın (yalnızca API'nın yaptığı gibi) harici kitaplığa erişmek için kullanacağı yapıları ve yöntemleri yalnızca daha düşük bir düzeyde tanımlar. API'niz, bir işleve bağımsız değişken aktardığınız sırayı tanımlar. Kişisel ABI mekaniği tanımlar nasılbu argümanlar iletilir (yazmaçlar, yığın, vb.). API'niz hangi işlevlerin kitaplığınızın bir parçası olduğunu tanımlar. ABI'niz kodunuzun kütüphane dosyasının içinde nasıl saklanacağını tanımlar, böylece kütüphanenizi kullanan herhangi bir program istenen işlevi bulabilir ve yürütebilir.

Harici kütüphaneler kullanan uygulamalar söz konusu olduğunda ABI'ler önemlidir. Kütüphaneler kod ve diğer kaynaklarla doludur, ancak programınızın kütüphane dosyası içinde neye ihtiyacı olduğunu nasıl bilmesi gerekir. ABI'niz bir kütüphane içeriğinin dosyanın içinde nasıl saklandığını tanımlar ve programınız dosyada arama yapmak ve neye ihtiyaç duyduğunu bulmak için ABI'yi kullanır. Sisteminizdeki her şey aynı ABI ile uyumluysa, herhangi bir program, onları kimin oluşturduğuna bakılmaksızın herhangi bir kütüphane dosyasıyla çalışabilir. Linux ve Windows farklı ABI'ler kullanır, bu nedenle bir Windows programı Linux için derlenmiş bir kitaplığa nasıl erişileceğini bilemez.

Bazen ABI değişiklikleri kaçınılmazdır. Bu durumda, kitaplığın yeni sürümünü kullanmak üzere yeniden derlenmedikçe bu kitaplığı kullanan programlar çalışmaz. ABI değişir ancak API değişmezse, eski ve yeni kütüphane sürümlerine bazen "kaynak uyumlu" denir. Bu, bir kütüphane sürümü için derlenen bir program diğeriyle çalışmazken, biri için yazılan kaynak kodun yeniden derlendiğinde diğeri için çalışacağı anlamına gelir.

Bu nedenle, geliştiriciler ABI'larını sabit tutma eğilimindedir (bozulmayı en aza indirmek için). Bir ABI'yi sabit tutmak, işlev arabirimlerini (dönüş türü ve sayısı, türleri ve bağımsız değişkenlerin sırası), veri türlerinin veya veri yapılarının tanımlarını, tanımlanmış sabitleri vb. Değiştirmemek anlamına gelir. Yeni işlevler ve veri türleri eklenebilir, ancak mevcut olanların kalması gerekir aynısı. Örneğin, kitaplığınız bir işlevin ofsetini belirtmek için 32 bit tamsayılar kullanıyor ve 64 bit tamsayılara geçiyorsanız, o kitaplığı kullanan önceden derlenmiş kod bu alana (veya onu izleyen herhangi birine) doğru erişmeyecektir . Veri yapısı üyelerine erişim derleme sırasında ve veri yapısı değişirse bellek adreslerine ve ofsetlerine dönüştürülür,

Bir ABI, çok düşük seviyeli sistem tasarım işi yapmadıkça açıkça sağlayacağınız bir şey değildir. Dile özgü değildir, çünkü (örneğin) bir C uygulaması ve Pascal uygulaması derlendikten sonra aynı ABI'yi kullanabilir.

Düzenle:SysV ABI belgelerinde ELF dosya biçimi ile ilgili bölümler hakkındaki sorunuzla ilgili olarak: Bu bilgilerin dahil edilmesinin nedeni, ELF biçiminin işletim sistemi ve uygulama arasındaki arabirimi tanımlamasıdır. İşletim sistemine bir program çalıştırmasını söylediğinizde, programın belirli bir şekilde biçimlendirilmesini bekler ve (örneğin) ikili dosyanın ilk bölümünün belirli bellek ofsetlerinde belirli bilgileri içeren bir ELF üstbilgisi olmasını bekler. Uygulamanın kendisi hakkında önemli bilgileri işletim sistemine nasıl ilettiği budur. ELF olmayan bir ikili biçimde (a.out veya PE gibi) bir program oluşturursanız, ELF biçimli uygulamaların beklendiği bir işletim sistemi ikili dosyayı yorumlayamaz veya uygulamayı çalıştıramaz.

IIRC, Windows şu anda Taşınabilir Yürütülebilir (veya, PE) biçimini kullanmaktadır. Bu Wikipedia sayfasının "harici bağlantılar" bölümünde PE biçimi hakkında daha fazla bilgi içeren bağlantılar vardır.

Ayrıca, C ++ ad yönetimi ile ilgili notunuzla ilgili: Bir kütüphane dosyasında bir işlev bulunurken, işlev genellikle ada göre aranır. C ++ işlev adlarını aşırı yüklemenize izin verir, bu nedenle yalnızca bir işlevi tanımlamak için yeterli değildir. C ++ derleyicileri, ad mangling adı verilen bu dahili olarak kendi başlarına çalışma yöntemlerine sahiptir . Bir ABI, farklı bir dil veya derleyici ile oluşturulan programların ihtiyaç duyduklarını bulabilmeleri için bir işlevin adını kodlamanın standart bir yolunu tanımlayabilir. Bir extern "c"C ++ programında kullandığınızda, derleyiciye diğer yazılımlar tarafından anlaşılabilir olan standart bir kayıt adı kullanma talimatı vermiş olursunuz.


2
@bta, Harika cevap için teşekkürler. Çağrı kuralı bir çeşit ABI mı? Teşekkürler
camino

37
Güzel cevap. Bir ABI bu değil. Bir ABI, çağrı kuralını belirleyen bir kurallar dizisi ve yapıları düzenleme kurallarıdır. Pascal, yığın üzerinde argümanları C uygulamalarından tersine sırayla iletir, bu nedenle pascal ve C derleyicileri aynı ABI'ye derlemez. C ve Pascal derleyicileri için ilgili standartlar bunun doğru olacağını garanti eder. C ++ derleyicileri, standart bir yol olmadığından adları işlemek için "standart" bir yol tanımlayamaz. Windows üzerinde rakip C ++ derleyicileri olduğunda C ++ ad düzenleme kuralları C ++ derleyicileri arasında uyumlu değildi.
Robin Davies


1
@RobinDavies: Pascal derleyicilerinin, arayanları tarafından verilen işlevler pop argümanları olarak adlandırdığı platformlarda, C derleyicileri genellikle bir programcının belirli işlevlerin Pascal derleyicileri, C derleyicileri genellikle varsayılan olarak çağrılan işlevlerin arayanlar tarafından yerleştirilen herhangi bir şeyi yığına bıraktığı bir kural kullanır.
Supercat

C derleyicisi tarafından oluşturulan obj dosyalarının ABI içerdiğini söyleyebilir miyim?
Mitu Raj

144

Montajı ve işlerin işletim sistemi düzeyinde nasıl çalıştığını biliyorsanız, belirli bir ABI'ya uyuyorsunuz. ABI, parametrelerin nasıl iletildiği, dönüş değerlerinin yerleştirildiği gibi şeyleri yönetir. Birçok platform için seçilebilecek tek bir ABI vardır ve bu durumlarda ABI sadece "işler nasıl çalışır" dır.

Ancak, ABI ayrıca sınıfların / nesnelerin C ++ 'da nasıl düzenlendiğini yönetir. Nesne referanslarını modül sınırları ötesine geçirebilmek veya farklı derleyicilerle derlenen kodu karıştırmak istiyorsanız bu gereklidir.

Ayrıca, 32 bit ikili dosyaları çalıştırabilen 64 bit bir işletim sisteminiz varsa, 32 ve 64 bit kod için farklı ABI'leriniz olacaktır.

Genel olarak, aynı yürütülebilir dosyaya bağladığınız kodların aynı ABI ile uyumlu olması gerekir. Farklı ABI'ler kullanarak kod arasında iletişim kurmak istiyorsanız, bir çeşit RPC veya serileştirme protokolü kullanmanız gerekir.

Farklı tür arayüzlerde sabit bir özellik setine sıkıştırmak için çok uğraştığınızı düşünüyorum. Örneğin, bir arayüz mutlaka tüketicilere ve üreticilere bölünmek zorunda değildir. Bir arayüz sadece iki varlığın etkileşim kurduğu bir kuraldır.

ABI'lar (kısmen) ISA agnostik olabilir. Bazı yönler (çağırma kuralları gibi) ISA'ya bağlıyken, diğer yönler (C ++ sınıf düzeni gibi) buna bağlı değildir.

Derleyici yazanlar için iyi tanımlanmış bir ABI çok önemlidir. İyi tanımlanmış bir ABI olmasaydı, birlikte çalışabilir kod oluşturmak imkansız olurdu.

EDIT: Açıklamak için bazı notlar:

  • ABI'deki "Binary", dize veya metin kullanımını dışlamaz. C ++ sınıfını dışa aktaran bir DLL'i bağlamak istiyorsanız, içinde bir yerde yöntemler ve tür imzaları kodlanmalıdır. C ++ ad yönetimi burada devreye giriyor.
  • Hiçbir zaman bir ABI sunmamanızın nedeni, programcıların büyük çoğunluğunun asla yapamayacağıdır. ABI'ler, platformu tasarlayan aynı kişiler tarafından sağlanır (yani işletim sistemi) ve çok az programcı, yaygın olarak kullanılan bir ABI tasarlama ayrıcalığına sahip olacaktır.

Şablonumun hatalı olduğuna hiç ikna olmadım. Çünkü arayüz için bu şablon her yerde doğrudur. Yani, evet ABI'nın da bu şablona uymasını bekliyorum ama bu değil. ÖNEMLİ şey hala anlamıyorum. Çok aptal mıyım yoksa başka bir şey mi bilmiyorum ama sadece kafama girmiyor. Cevapları ve wiki makalesini anlayamıyorum.
pençeleri

2
@jesperE, "ABI, parametrelerin nasıl aktarıldığı, dönüş değerlerinin nereye yerleştirildiği gibi şeyleri yönetiyor."
camino

3
Evet. Uygun isim ABI'nin bir parçası olan "çağrı kuralı" dır. en.wikipedia.org/wiki/X86_calling_conventions
JesperE

4
bu doğru ve kesin ayrıntı vermeden cevap (daha doğrusu gürültü )!
Nawaz

Biraz montaj yazmanızı tavsiye ederim. Bu, insanların ABI'yi daha somut bir şekilde anlamalarına yardımcı olacaktır.
KunYu Tsai

40

Aslında bir ABI'ye ihtiyacınız yok.

  • Programınızın işlevleri yok ve--
  • Programınız, tek başına çalışan tek bir yürütülebilir dosyadır (yani gömülü bir sistem), tam anlamıyla çalışan tek şeydir ve başka bir şeyle konuşmaya gerek yoktur.

Çok basitleştirilmiş bir özet:

API: "İşte çağırabileceğiniz tüm işlevler."

ABI: " Bir işlevi böyle çağırırız."

ABI, derleyicilerin ve bağlayıcıların programınızı derlemek için uygun şekilde çalışması için uyduğu kurallar dizisidir. ABI'ler birden fazla konuyu kapsar:

  • Bir ABI'nın tartışmasız en büyük ve en önemli kısmı, bazen "çağrı kuralı" olarak bilinen prosedür çağrı standardıdır . Çağıran kurallar, "işlevlerin" montaj koduna nasıl çevrildiğini standartlaştırır.
  • ABI'ler ayrıca kütüphanelerde açıkta kalan işlevlerin adlarının nasıl temsil edilmesi gerektiğini de belirler, böylece diğer kodlar bu kütüphaneleri çağırabilir ve hangi argümanların iletilmesi gerektiğini bilir. Buna "ad yönetimi" denir.
  • ABI'ler ayrıca ne tür veri türlerinin kullanılabileceğini, nasıl hizalanmaları gerektiğini ve diğer düşük düzeyli ayrıntıları da belirler.

Bir ABI'nin çekirdeği olarak gördüğüm çağrı kuralına daha derin bir bakış:

Makinenin kendisinde "işlev" kavramı yoktur. C gibi üst düzey bir dilde bir işlev yazdığınızda, derleyici gibi bir montaj kodu satırı oluşturur _MyFunction1:. Bu, sonunda montajcı tarafından bir adrese çözülecek olan bir etikettir . Bu etiket, montaj kodundaki "fonksiyon" unuzun "başlangıcını" belirtir. Eğer "Çağrı" bu fonksiyon, ne gerçekten yapıyoruz için CPU neden olan zaman üst düzey kodunda, atlamak o etiketin adrese ve devam orada infaz.

Atlamaya hazırlanırken, derleyici bir sürü önemli şey yapmalıdır. Çağrı kuralı, derleyicinin tüm bunları yapmak için takip ettiği bir kontrol listesi gibidir:

  • İlk olarak, derleyici geçerli adresi kaydetmek için biraz montaj kodu ekler, böylece "fonksiyonunuz" tamamlandığında, CPU doğru yere atlayabilir ve çalışmaya devam edebilir.
  • Sonra, derleyici argümanları iletmek için montaj kodu üretir.
    • Bazı çağırma kuralları, argümanların yığına konulmasını gerektirir ( belirli bir sırada ).
    • Diğer sözleşmeler, argümanların belirli kayıtlara konulmasını gerektirir (elbette veri türlerine bağlı olarak ).
    • Yine de diğer sözleşmeler, yığın ve kayıtların belirli bir kombinasyonunun kullanılması gerektiğini belirtir.
  • Tabii ki, daha önce bu kayıtlarda önemli bir şey varsa, bu değerlerin üzerine yazılır ve sonsuza dek kaybolur, bu nedenle bazı çağrı kuralları, derleyicinin argümanları içine koymadan önce bu kayıtlardan bazılarını kaydetmesi gerektiğini söyleyebilir.
  • Şimdi derleyici, CPU'ya daha önce yaptığı etikete gitmesini söyleyen bir atlama talimatı ekler ( _MyFunction1:). Bu noktada, CPU'nun "sizin" fonksiyonunuzda "olduğunu düşünebilirsiniz.
  • İşlevin sonunda, derleyici CPU'nun dönüş değerini doğru yere yazmasını sağlayacak bazı montaj kodları koyar. Çağıran kural, dönüş değerinin (türüne bağlı olarak) belirli bir kayıt defterine mi yoksa yığına mı yerleştirileceğini belirler.
  • Şimdi temizlik zamanı. Çağıran kural derleyicinin temizleme montaj kodunu nereye koyacağını belirler.
    • Bazı kurallar arayanın yığını temizlemesi gerektiğini söylüyor. Bu, "işlev" yapıldıktan ve CPU'nun önceki konumuna geri döndükten sonra, yürütülecek bir sonraki kodun çok özel bir temizleme kodu olması gerektiği anlamına gelir.
    • Diğer kurallar, temizleme kodunun bazı belirli bölümlerinin geri atlamadan önce "işlev" in sonunda olması gerektiğini söylüyor .

Birçok farklı ABI / çağrı kuralı vardır. Bazı ana olanlar:

  • X86 veya x86-64 CPU (32 bit ortam) için:
    • CDECL
    • STDCALL
    • fastcall
    • VECTORCALL
    • thiscall
  • X86-64 CPU (64 bit ortam) için:
    • SystemV
    • MSNATIVE
    • VECTORCALL
  • ARM CPU için (32 bit)
    • AAPCS
  • ARM CPU (64 bit) için
    • AAPCS64

İşte farklı Abis düzenleme yapılırken aslında montaj oluşturulan farklılıkları gösteren büyük bir sayfası.

Söz etmek başka şey, bir ABI değil sadece ilgili olmasıdır programınızın yürütülebilir modülü. Aynı oluyor da program kütüphane fonksiyonları çağrıları doğru emin olmak için bağlayıcı ile kullandı. Bilgisayarınızda çalışan birden fazla paylaşılan kitaplığınız vardır ve derleyiciniz her biri hangi ABI'yi kullandıklarını bildiği sürece, yığını havaya uçurmadan onlardan işlevleri doğru şekilde çağırabilir.

Derleyicinizin kütüphane işlevlerini nasıl arayacağını anlaması son derece önemlidir. Barındırılan bir platformda (yani bir işletim sisteminin programları yüklediği bir platformda), programınız çekirdek çağrısı yapmadan bile yanıp sönemez.


19

Bir uygulama ikili arayüzü (ABI) bir API'ye benzer, ancak işleve kaynak kodu düzeyinde arayan tarafından erişilemez. Yalnızca ikili gösterime erişilebilir / kullanılabilir.

ABI'ler işlemci-mimari düzeyinde veya işletim sistemi düzeyinde tanımlanabilir. ABI'ler, derleyicinin kod üreteci aşaması tarafından izlenecek standartlardır. Standart, işletim sistemi veya işlemci tarafından sabitlenir.

İşlevsellik: İşlev çağrılarını uygulama dilinden veya belirli bir derleyici / bağlayıcı / araç zincirinden bağımsız hale getirmek için mekanizmayı / standardı tanımlayın. JNI veya bir Python-C arabirimi vb. Sağlayan mekanizma sağlayın.

Mevcut varlıklar: Makine kodu biçimindeki işlevler.

Tüketici: Başka bir işlev (başka bir dilde biri dahil, başka bir derleyici tarafından derlenmiş veya başka bir bağlayıcı tarafından bağlanmış).


ABI neden mimarlık tarafından tanımlanmalıdır? Aynı mimarideki farklı işletim sistemleri neden farklı ABI'leri tanımlayamıyor?
Andreas Haferburg

10

İşlevsellik: Derleyiciyi, montaj yazarlarını, bağlayıcıyı ve işletim sistemini etkileyen bir dizi sözleşme. Sözleşmeler, işlevlerin nasıl düzenlendiğini, parametrelerin nerede iletildiğini, parametrelerin nasıl iletildiğini, işlevin nasıl çalıştığını belirtir. Bunlar genellikle (işlemci mimarisi, işletim sistemi) grubuna özgüdür.

Mevcut varlıklar: parametre düzeni, işlev semantiği, kayıt tahsisi. Örneğin, ARM mimarilerinin çok sayıda ABI'si vardır (APCS, EABI, GNU-EABI, bir sürü tarihi vakayı düşünmeyin) - karışık bir ABI kullanmak, kodunuzu sınırlar boyunca çağırırken çalışmayacaktır.

Tüketici: Derleyici, montaj yazarları, işletim sistemi, CPU'ya özgü mimari.

Bu detaylara kimin ihtiyacı var? Derleyici, montaj yazarları, kod üretimi yapan bağlayıcılar (veya hizalama gereksinimleri), işletim sistemi (kesme işleme, sistem çağrısı arayüzü). Montaj programlaması yaptıysanız, bir ABI'ye uyuyordunuz!

C ++ ad yönetimi özel bir durumdur - bir bağlayıcı ve dinamik bağlayıcı merkezli sorun - ad yönetimi standart değilse, dinamik bağlantı çalışmaz. Bundan böyle, C ++ ABI sadece C ++ ABI olarak adlandırılır. Bu, bağlayıcı düzeyinde bir sorun değil, kod oluşturma sorunudur. Bir C ++ ikili dosyaya sahip olduğunuzda, kaynaktan derlemeden başka bir C ++ ABI (ad yönetimi, istisna işleme) ile uyumlu hale getirmek mümkün değildir.

ELF, bir yükleyici ve dinamik bağlayıcı kullanımı için bir dosya formatıdır. ELF, ikili kod ve veriler için bir kapsayıcı biçimidir ve bu nedenle bir kod parçasının ABI'sini belirtir. PE yürütülebilirleri bir ABI olmadığı için ELF'yi kesinlikle ABI olarak kabul etmem.

Tüm ABI'ler talimat setine özeldir. ARM ABI, MSP430 veya x86_64 işlemcide bir anlam ifade etmez.

Windows'un birkaç ABI'si vardır - örneğin, hızlı arama ve stdcall iki yaygın kullanım ABI'sıdır. Sistem çağrısı ABI yine farklı.


9

Sorunuzun en azından bir kısmını cevaplayayım. Linux ABI'nın sistem çağrılarını nasıl etkilediğine ve bunun neden yararlı olduğuna bir örnek.

Sistem araması, kullanıcı alanı programının çekirdek alanından bir şey istemesinin bir yoludur. Belirli bir kayıt defterine çağrı ve argüman için sayısal kod koyarak ve bir kesmeyi tetikleyerek çalışır. Daha sonra, çekirdek alanına bir anahtar oluşur ve çekirdek sayısal kodu ve bağımsız değişkeni arar, isteği işler, sonucu tekrar kayıt defterine koyar ve kullanıcı alanına geri geçişi tetikler. Bu, örneğin uygulama bellek ayırmak veya bir dosya açmak istediğinde gereklidir (syscalls "brk" ve "open").

Artık sistem çağrılarının kısa adları "brk" vb. Ve bunlara karşılık gelen op kodları vardır, bunlar sisteme özel bir başlık dosyasında tanımlanmıştır. Bu işlem kodları aynı kaldığı sürece, yeniden derlemeye gerek kalmadan farklı derlenmiş çekirdeklerle aynı derlenmiş kullanıcı alanı programlarını çalıştırabilirsiniz. Yani önceden derlenmiş binarys, yani ABI tarafından kullanılan bir arayüz var.


4

Paylaşılan kitaplıklardaki kodu veya derleme birimleri arasındaki arama kodunu çağırmak için, nesne dosyasının aramalar için etiketler içermesi gerekir. C ++, veri gizlemeyi zorlamak ve aşırı yüklenmiş yöntemlere izin vermek için yöntem etiketlerinin adlarını yönetir. Bu nedenle, aynı ABI'yi açıkça desteklemedikleri sürece farklı C ++ derleyicilerinden dosyaları karıştıramazsınız.


4

ABI ve API'yi ayırt etmenin en iyi yolu, neden ve ne için kullanıldığını bilmektir:

X86-64 için genellikle bir ABI vardır (ve x86 32 bit için başka bir set vardır):

http://www.x86-64.org/documentation/abi.pdf

https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/LowLevelABI/140-x86-64_Function_Calling_Conventions/x86_64.html

http://people.freebsd.org/~obrien/amd64-elf-abi.pdf

Linux + FreeBSD + MacOSX bunu küçük değişikliklerle takip eder. Ve Windows x64'ün kendi ABI'si var:

http://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64/

ABI'yi bilmek ve diğer derleyiciyi de kabul etmek, bunu izler, ardından ikili teorik olarak birbirlerini nasıl arayacağınızı (özellikle kütüphaneler API'sını) ve parametreleri yığının veya kayıtların vb. Üzerinden geçirmesini ya da işlevleri vb. Aslında bu bilgi yazılımın birbiriyle bütünleşmesine yardımcı olacaktır. Kayıtların / yığın düzeninin sırasını bilerek, montajlarda yazılan farklı yazılımları kolaylıkla bir araya getirebilirim.

Ancak API farklıdır:

Bu API kullanılarak farklı yazılım parçaları oluşturulursa, birbirini arayabilirler. Ancak SAME ABI'nın ek bir gereksinimi dikkate alınmalıdır.

Örneğin, Windows daha önce POSIX API uyumlu idi:

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

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

Linux da POSIX uyumludur. Ancak ikili dosyalar hemen taşınamaz ve hemen çalıştırılamaz. Ancak POSIX uyumlu API'da aynı NAMES'i kullandıkları için, aynı yazılımı C'de alabilir, farklı işletim sistemlerinde yeniden derleyebilir ve hemen çalıştırabilirsiniz.

API, yazılım - derleme öncesi aşamasının entegrasyonunu kolaylaştırmak içindir. Yani derlemeden sonra yazılım tamamen farklı görünebilir - eğer ABI farklıysa.

ABI, yazılımın ikili / montaj düzeyinde tam entegrasyonunu tanımlamayı amaçlamaktadır.


Windows x86-64 çağrı kuralı, diğer tüm x86-64 işletim sistemlerinin kullandığı SysV çağrı kuralını kullanmaz. Linux / OS X / FreeBSD tüm pay aynı çağrı kuralı, ancak yok tam ABI paylaşır. Bir işletim sisteminin ABI'sinde sistem çağrı numaraları bulunur. Örneğin, freebsd.org/doc/en_US.ISO8859-1/books/developers-handbook/…SYS_execve 32bit linux'da 11, FreeBSD'de 59 olduğunu söylüyor .
Peter Cordes

Yorumunuz için teşekkürler, yorumumu ABI ve API arasındaki farkı daha iyi cevaplamak için değiştirdim.
Peter Teoh

Hala bir çağrı kuralı ile tam bir ABI (sistem çağrıları ve her şey) arasındaki farkı kaçırıyorsunuz. Linux (çekirdek) bir FreeBSD uyumluluk katmanı sağladığı için Linux'ta bazı FreeBSD ikili dosyaları çalıştırabilirsiniz. O zaman bile, bu, Linux'un sağlamadığı FreeBSD ABI'nin herhangi bir bölümünü kullanmaya çalışmayan ikili dosyalar ile sınırlıdır. (örneğin, yalnızca FreeBSD sistem çağrıları). ABI uyumlu, aynı derlemeyi her iki sistemde de çalıştırabileceğiniz anlamına gelir.
Peter Cordes

"FreeBSD uyumluluk katmanı", bunu hiç duymadım. İlgili linux çekirdeği kaynak kodunu gösterebilir misiniz? Ancak bunun tersi de geçerlidir: freebsd.org/doc/en_US.ISO8859-1/books/handbook/linuxemu.html .
Peter Teoh

Kullandığım bir şey değil. Ben düşünce var böyle bir şey, ama belki de artık yok. tldp.org/HOWTO/Linux+FreeBSD-6.html bunun bakımsız olduğunu ve bunun nasıl yapılacağını 2000'den söylüyor. xD. unix.stackexchange.com/questions/172038/… , terk edildiğini ve hiçbir zaman yeniden yapılmadığını doğrular (çünkü kimse bunu yapmak için yeterince kötü istemediğinden). personality(2)ayarlayabilirsiniz PER_BSD. Ben gördüğümü hatırlıyorum düşünüyorum personality(PER_LINUX)içinde straceçıkış her zaman, ama modern 64bit Linux ikili artık bunu yapmaz.
Peter Cordes

4

Linux paylaşımlı kütüphane minimal çalıştırılabilir ABI örneği

Paylaşılan kütüphaneler bağlamında, "kararlı bir ABI'ye sahip olmanın" en önemli anlamı, kütüphane değiştikten sonra programlarınızı yeniden derlemenize gerek olmamasıdır.

Yani mesela:

  • paylaşılan bir kitaplık satıyorsanız, kullanıcılarınıza her yeni sürüm için kitaplığınıza bağlı olan her şeyi yeniden derleme sıkıntısını kaydedersiniz

  • kullanıcının dağıtımında bulunan paylaşılan bir kütüphaneye bağlı kapalı kaynak programı satıyorsanız, ABI'nin hedef işletim sisteminin belirli sürümlerinde kararlı olduğundan eminseniz daha az önyükleme yayınlayabilir ve test edebilirsiniz.

    Bu, sisteminizdeki birçok programın bağlandığı C standart kitaplığı için özellikle önemlidir.

Şimdi bunun asgari somut çalıştırılabilir bir örneğini sunmak istiyorum.

main.c

#include <assert.h>
#include <stdlib.h>

#include "mylib.h"

int main(void) {
    mylib_mystruct *myobject = mylib_init(1);
    assert(myobject->old_field == 1);
    free(myobject);
    return EXIT_SUCCESS;
}

mylib.c

#include <stdlib.h>

#include "mylib.h"

mylib_mystruct* mylib_init(int old_field) {
    mylib_mystruct *myobject;
    myobject = malloc(sizeof(mylib_mystruct));
    myobject->old_field = old_field;
    return myobject;
}

mylib.h

#ifndef MYLIB_H
#define MYLIB_H

typedef struct {
    int old_field;
} mylib_mystruct;

mylib_mystruct* mylib_init(int old_field);

#endif

Derleme ve iyi çalışır:

cc='gcc -pedantic-errors -std=c89 -Wall -Wextra'
$cc -fPIC -c -o mylib.o mylib.c
$cc -L . -shared -o libmylib.so mylib.o
$cc -L . -o main.out main.c -lmylib
LD_LIBRARY_PATH=. ./main.out

Şimdi, kütüphanenin v2'si için mylib_mystructçağrılan yeni bir alan eklemek istediğimizi varsayalım new_field.

Alanı daha önce old_fieldolduğu gibi eklediysek :

typedef struct {
    int new_field;
    int old_field;
} mylib_mystruct;

ve kütüphaneyi yeniden inşa etti ama değil main.out, o zaman iddia başarısız olur!

Çünkü çizgi:

myobject->old_field == 1

intyapının ilkine erişmeye çalışan bir montaj oluşturmuştu , ki bu şimdi new_fieldbeklenen yerine old_field.

Bu nedenle bu değişiklik ABI'yi bozdu.

Ancak, biz eklemek new_fieldsonra old_field:

typedef struct {
    int old_field;
    int new_field;
} mylib_mystruct;

eski oluşturulan montaj hala intyapının ilkine erişir ve program hala çalışır, çünkü ABI'yi sabit tuttuk.

İşte olan GitHub'dan bu örnek tam otomatik versiyonu .

Bu ABI'yi sabit tutmanın başka bir yolu, opak bir yapımylib_mystruct olarak davranmak ve alanlarına sadece yöntem yardımcıları aracılığıyla erişmek olurdu . Bu, ABI'yi sabit tutmayı kolaylaştırır, ancak daha fazla işlev çağrısı yapacağımız için performans yüküne neden olur.

API ve ABI karşılaştırması

Bir önceki örnekte, ekleme olduğunu ilginçtir new_fieldönce old_field, sadece API ABI kırdı ama.

Bunun anlamı, eğer main.cprogramımızı kütüphaneye karşı derleseydik, ne olursa olsun işe yarardı.

Bununla birlikte, örneğin işlev imzasını değiştirmiş olsaydık, API'yı da kırmış olurduk:

mylib_mystruct* mylib_init(int old_field, int new_field);

çünkü bu durumda, main.cderlemeyi tamamen durduracaktır.

Anlamsal API ve Programlama API'sı

API değişikliklerini üçüncü bir türde de sınıflandırırız: anlamsal değişiklikler.

Anlamsal API, genellikle API belgelerinde yer alan ve API'nın ne yapması gerektiği konusunda doğal bir dil tanımıdır.

Bu nedenle, semantik API'yi program derlemesinin kendisini bozmadan kırmak mümkündür.

Örneğin,

myobject->old_field = old_field;

için:

myobject->old_field = old_field + 1;

bu ne programlama API'sini ne de ABI'yi bozar, ancak main.csemantik API bozulurdu.

Sözleşme API'sını programlı olarak kontrol etmenin iki yolu vardır:

  • bir grup köşe vakasını test edin. Yapması kolay, ancak her zaman birini özleyebilirsiniz.
  • resmi doğrulama . Yapması daha zor, ancak matematiksel doğruluk kanıtı üretir, temelde belgeleri ve testleri "insan" / makine doğrulanabilir bir şekilde birleştirir! Elbette resmi açıklamanızda bir hata olmadığı sürece ;-)

    Bu kavram Matematiğin kendisinin resmileştirilmesiyle yakından ilgilidir: /math/53969/what-does-formal-mean/3297537#3297537

C / C ++ paylaşılan kütüphane ABI'larını kıran her şeyin listesi

YAPILACAKLAR: nihai listeyi bul / oluştur:

Java minimal çalıştırılabilir örneği

Java'da ikili uyumluluk nedir?

Ubuntu 18.10, GCC 8.2.0'da test edilmiştir.


3

ABI, çağrının başarılı olduğundan emin olmak için arayan ile arayan arasında tutarlı olmalıdır. Yığın kullanımı, kayıt kullanımı, rutin sonu yığını pop. Bütün bunlar ABI'nin en önemli parçalarıdır.


3

özet

Bir ABI'yi (uygulama ikili arayüzü) tanımlayan tam katmanın çeşitli yorumları ve güçlü görüşleri vardır.

Bence bir ABI, belirli bir API için verilen / platform olarak kabul edilenin öznel bir sözleşmesidir . ABI, belirli bir API için "değişmeyecek" veya çalışma zamanı ortamı tarafından ele alınacak kuralların "geri kalanıdır": yürütücüler, araçlar, bağlayıcılar, derleyiciler, jvm ve işletim sistemi.

Arayüz Tanımlama : ABI, API

Eğer joda-time gibi bir kütüphane kullanmak istiyorsanız, bağımlılık beyan etmelisiniz joda-time-<major>.<minor>.<patch>.jar. Kütüphane en iyi uygulamaları takip eder ve Anlamsal Sürüm Oluşturmayı kullanır . Bu, API uyumluluğunu üç düzeyde tanımlar:

  1. Düzeltme eki - Tüm kodunuzu değiştirmeniz gerekmez. Kütüphane sadece bazı hataları düzeltir.
  2. Küçük - Eklemelerden bu yana kodunuzu değiştirmeniz gerekmez
  3. Major (Ana) - Arayüz (API) değiştirilir ve kodunuzu değiştirmeniz gerekebilir.

Aynı kütüphanenin yeni bir büyük sürümünü kullanmanız için hala birçok başka konvansiyona saygı duyulmaktadır:

  • Kütüphaneler için kullanılan ikili dil (Java'da Java bayt kodunu tanımlayan JVM hedef sürümü)
  • Çağrı kuralları
  • JVM sözleşmeleri
  • Bağlama kuralları
  • Çalışma zamanı kuralları Tüm bunlar, kullandığımız araçlar tarafından tanımlanır ve yönetilir.

Örnekler

Java örnek olay incelemesi

Örneğin, Java tüm bu kuralları bir araçta değil, resmi bir JVM spesifikasyonunda standardize etti. Spesifikasyon, diğer satıcıların uyumlu kütüphaneler çıkarabilen farklı bir araç seti sağlamasına izin verdi.

Java, ABI için iki ilginç durum çalışması daha sunar: Scala versiyonları ve Dalvik sanal makine.

Dalvik sanal makine ABI'yi kırdı

Dalvik VM, Java bayt kodundan farklı bir bayt koduna ihtiyaç duyar. Dalvik kütüphaneleri, Dalvik için Java bayt kodunu (aynı API ile) dönüştürerek elde edilir. Bu şekilde, aynı API'nın iki sürümü elde edebilirsiniz: orijinal tarafından tanımlanır joda-time-1.7.2.jar. Beni arayabiliriz joda-time-1.7.2.jarve joda-time-1.7.2-dalvik.jar. Yığın yönelimli standart Java vms için farklı bir ABI kullanırlar: Oracle'ın biri, IBM'in biri, açık Java veya diğer herhangi biri; ve ikinci ABI Dalvik çevresindeki.

Scala'nın ardışık sürümleri uyumsuz

Scala'nın küçük Scala versiyonları arasında ikili uyumluluğu yoktur: 2.X. Bu nedenle aynı API "io.reactivex" %% "rxscala"% "0.26.5" üç sürüme sahiptir (gelecekte daha fazla): Scala 2.10, 2.11 ve 2.12 için. Ne değişti? Şimdilik bilmiyorum , ancak ikili dosyalar uyumlu değil. Muhtemelen en son sürümler, kütüphaneleri eski sanal makinelerde kullanılamaz hale getiren şeyler, muhtemelen bağlama / adlandırma / parametre kuralları ile ilgili şeyler ekler.

Java ardışık sürümleri uyumsuz

Java'nın JVM'nin büyük sürümleriyle de sorunları var: 4,5,6,7,8,9. Yalnızca geriye dönük uyumluluk sunarlar. Jvm9 -target, diğer tüm sürümler için derlenmiş / hedeflenmiş kodu (javac'ın seçeneği) nasıl çalıştıracağını bilirken, JVM 4, JVM 5 için hedeflenen kodu nasıl çalıştıracağını bilmiyor. Bu uyumsuzluk, farklı çözümler sayesinde radarın altında uçar:

  1. Anlamsal sürüm oluşturma: kütüphaneler daha yüksek JVM'yi hedeflediğinde genellikle ana sürümü değiştirirler.
  2. ABI olarak JVM 4 kullanın ve güvendesiniz.
  3. Java 9, aynı kitaplığa belirli hedefli JVM için bayt kodunu nasıl ekleyebileceğinize ilişkin bir özellik ekler.

Neden API tanımıyla başladım?

API ve ABI, yalnızca uyumluluğu nasıl tanımladığınıza ilişkin sözleşmelerdir. Alt katmanlar, yüksek seviyeli semantik bolluğu bakımından jeneriktir. Bu yüzden bazı sözleşmeler yapmak kolaydır. İlk kurallar, bellek hizalama, bayt kodlama, arama kuralları, büyük ve küçük endian kodlamaları vb. İle ilgilidir. Bunların üstünde, Java tarafından kullanılanlar gibi konvansiyonları, ara bayt kodunu veya GCC tarafından kullanılan LLVM IR. Üçüncüsü, kitaplıkları nasıl bulacağınız, nasıl yükleyeceğinize dair sözleşmeler alırsınız (bkz. Java sınıf yükleyicileri). Kavramlarda gittikçe daha da yükseldikçe, verilen olarak kabul ettiğiniz yeni sözleşmelere sahipsiniz. Bu yüzden anlamsal versiyonlamaya geçmediler .sürümü. İle semantik versiyonlamayı değiştirebiliriz <major>-<minor>-<patch>-<platform/ABI>. Bu aslında zaten neler olduğunu: platform zaten bir rpm, dll, jar(JVM baytkodu), war(jvm + web sunucusu), apk, 2.11(özgül Scala versiyonu) ve benzerleri. APK dediğinizde zaten API'nizin belirli bir ABI bölümü hakkında konuşuyorsunuz.

API, farklı ABI'ye taşınabilir

Bir soyutlamanın en üst seviyesi (en yüksek API'ya karşı yazılan kaynaklar başka herhangi bir alt seviye soyutlamaya yeniden derlenebilir / taşınabilir.

Diyelim ki rxscala için bazı kaynaklara sahibim. Scala araçları değiştirilirse bunları yeniden derleyebilirim. JVM değişirse, üst düzey kavramlarla uğraşmadan eski makineden yenisine otomatik dönüşümler yapabilirim. Taşıma zor olsa da diğer herhangi bir müşteri yardımcı olacaktır. Tamamen farklı bir montajcı kodu kullanılarak yeni bir işletim sistemi oluşturulursa, bir çevirmen oluşturulabilir.

Diller arasında taşınan API'lar

Reaktif akışlar gibi birden çok dilde taşınan API'ler vardır . Genel olarak belirli dillere / platformlara eşlemeler tanımlarlar. API'nin resmi olarak insan dilinde veya hatta belirli bir programlama dilinde tanımlanan ana şartname olduğunu iddia ediyorum. Diğer tüm "eşlemeler" bir anlamda ABI'dir, normal ABI'den daha fazla API'dir. Aynı şey REST arayüzlerinde de oluyor.


1

Kısacası ve felsefede, sadece bir tür şeyler iyi geçinebilir ve ABI, birlikte çalıştığı yazılımların bir türü olarak görülebilir .


1

Ayrıca ABI'yı anlamaya çalışıyordum ve JesperE'nin cevabı çok yardımcı oldu.

Çok basit bir bakış açısıyla, ikili uyumluluğu dikkate alarak ABI'yı anlamaya çalışabiliriz.

KDE wiki, bir kütüphaneyi ikili uyumlu olarak tanımlar: “kütüphanenin eski bir sürümüne dinamik olarak bağlı bir program, yeniden derlemeye gerek kalmadan kütüphanenin daha yeni sürümleriyle çalışmaya devam ederse”. Dinamik bağlantı hakkında daha fazla bilgi için bkz. Statik bağlantı ile dinamik bağlantı

Şimdi, bir kütüphanenin ikili uyumluluk olması için gereken en temel yönlere bakmaya çalışalım (kütüphanede kaynak kodu değişikliği olmadığı varsayılarak):

  1. Aynı / geriye dönük uyumlu komut kümesi mimarisi (işlemci talimatları, kayıt dosyası yapısı, yığın organizasyonu, bellek erişim türleri, boyutlar, düzen ve işlemcinin doğrudan erişebileceği temel veri türlerinin hizalanması)
  2. Aynı çağrı kuralları
  3. Aynı isim mangling kuralı (bir Fortran programının bazı C ++ kütüphane işlevini çağırması gerekiyorsa bu gerekli olabilir).

Elbette, başka birçok detay var ama bu çoğunlukla ABI'nın da kapsadığı şey.

Daha özel olarak sorunuzu cevaplamak için yukarıdakilerden şunu çıkarabiliriz:

ABI işlevselliği: ikili uyumluluk

mevcut varlıklar: mevcut program / kütüphaneler / işletim sistemi

tüketici: kütüphaneler, işletim sistemi

Bu yardımcı olur umarım!


1

Uygulama ikili arayüzü (ABI)

Fonksiyonellik:

  • Programlayıcının modelinden temel sistemin etki alanı veri türü, boyutu, hizalaması, işlevlerin bağımsız değişkenlerinin nasıl iletildiğini ve alınan değerleri döndürdüğünü denetleyen çağrı kuralı ile çeviri; sistem çağrı numaraları ve uygulamanın işletim sistemine nasıl sistem çağrısı yapması gerektiği; üst düzey dil derleyicilerinin ad yönetim şeması, istisna yayılması ve derleyiciler arasında aynı platformda arama kuralı, ancak platformlar arası uyumluluk gerektirmez ...

Mevcut varlıklar:

  • Programın yürütülmesine doğrudan katılan mantıksal bloklar: ALU, genel amaçlı kayıtlar, I / O'nun bellek / I / O eşlemesi için kayıtlar, vb ...

tüketici:

  • Dil işlemcileri birleştirici, birleştirici ...

Bunlar, takım zincirlerinin bir bütün olarak çalışmasını sağlamak zorunda olan herkes tarafından gereklidir. Bir modülü montaj dilinde, diğerini Python'da yazarsanız ve kendi önyükleyiciniz yerine bir işletim sistemi kullanmak istiyorsanız, "uygulama" modülleriniz "ikili" sınırlar üzerinde çalışır ve bu tür "arayüz" üzerinde anlaşmaya varılmasını gerektirir.

Farklı üst düzey dillerdeki nesne dosyalarının uygulamanıza bağlanması gerekebileceğinden C ++ ad yönetimi. Visual C ++ ile oluşturulan Windows sistem çağrıları GCC standart kitaplığı kullanmayı düşünün.

ELF, bağlayıcıyı yorumlama için bir nesne dosyasından olası bir beklentidir, ancak JVM'nin başka bir fikri olabilir.

Bir Windows RT Mağazası uygulaması için, gerçekten bir takım oluşturma zincirinin birlikte çalışmasını istiyorsanız ARM ABI'yi aramayı deneyin.


1

ABI terimi, iki farklı fakat ilgili kavram için kullanılır.

Derleyiciler hakkında konuşurken, kaynak düzeyindeki yapılardan ikili yapılara çevirmek için kullanılan kurallara atıfta bulunur. Veri türleri ne kadar büyük? yığın nasıl çalışır? parametreleri fonksiyonlara nasıl iletirim? hangi kayıtlar arayan tarafından arayan tarafından kaydedilmelidir?

Kütüphaneler hakkında konuşurken derlenmiş bir kütüphane tarafından sunulan ikili arayüzü ifade eder. Bu arayüz, kütüphanenin kaynak kodu, derleyici tarafından kullanılan kurallar ve bazı durumlarda diğer kütüphanelerden alınan tanımlar gibi bir dizi faktörün sonucudur.

Bir kitaplıkta yapılan değişiklikler, API'yı bozmadan ABI'yi kırabilir. Örneğin, gibi bir arayüze sahip bir kütüphane düşünün.

void initfoo(FOO * foo)
int usefoo(FOO * foo, int bar)
void cleanupfoo(FOO * foo)

ve uygulama programcısı aşağıdaki gibi kod yazar

int dostuffwithfoo(int bar) {
  FOO foo;
  initfoo(&foo);
  int result = usefoo(&foo,bar)
  cleanupfoo(&foo);
  return result;
}

Uygulama programcısı FOO'nun boyutunu veya düzenini umursamaz, ancak uygulama ikili dosyası sabit kodlu bir foo boyutuyla sonuçlanır. Kütüphane programcısı foo'ya fazladan bir alan eklerse ve birisi yeni uygulama ikili dosyasını eski uygulama ikili dosyasıyla kullanırsa, kütüphane sınırsız bellek erişimi yapabilir.

Kütüphane yazarı API'lerini benzer şekilde tasarlamışsa OTOH.

FOO * newfoo(void)
int usefoo(FOO * foo, int bar)
void deletefoo((FOO * foo, int bar))

ve uygulama programcısı aşağıdaki gibi kod yazar

int dostuffwithfoo(int bar) {
  FOO * foo;
  foo = newfoo();
  int result = usefoo(foo,bar)
  deletefoo(foo);
  return result;
}

Daha sonra uygulama ikili, kütüphanenin içinde gizlenebilecek olan FOO'nun yapısı hakkında bir şey bilmeye gerek yoktur. Bunun için ödediğiniz fiyat, yığın işlemlerinin dahil olmasıdır.


0

ABI- uygulama, kütüphane, OS gibi iki ikili program parçasıApplication Binary Interface arasındaki çalışma zamanında bir makine kodu iletişimi ile ilgilidir ... nesnelerin belleğe nasıl kaydedildiğini ve işlevlerin nasıl çağrıldığını açıklar ( )ABIcalling convention

API ve ABI'nin iyi bir örneği Swift diline sahip iOS ekosistemidir .

  • Application- Farklı diller kullanarak bir uygulama oluşturduğunuzda. Örneğin Swiftve [Mixing Swift ile Objective-C] tuşlarını kullanarak uygulama oluşturabilirsiniz.Objective-C

  • Application - OS- çalışma zamanı - Swift runtimeve standard librariesişletim sisteminin parçalarıdır ve her bir pakete dahil edilmemelidir (örn. uygulama, çerçeve). Objective-C'nin kullandığı gibi

  • Library- Module Stabilitycase - compile time - Swift derleyicisinin başka bir sürümü ile oluşturulmuş bir çerçeveyi içe aktarabileceksiniz . Bu, derleyicinin farklı bir sürümü ( .swiftinterfacetarafından kullanılır .swiftmodule) tarafından tüketilecek kapalı kaynak (ön-yapım) bir ikili oluşturmanın güvenli olduğu anlamına gelir ve

    Module compiled with _ cannot be imported by the _ compiler
    
  • Library- Library Evolutiondava

    1. Derleme zamanı - bir bağımlılık değiştirildiyse, istemcinin yeniden derlenmesi gerekmez.
    2. Çalışma zamanı - bir sistem kitaplığı veya dinamik bir çerçeve, yenisiyle değiştirilebilir.

[API ve ABI karşılaştırması]

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.