Yazılım işletim sistemi neden özel?


77

Bazı işletim sistemlerinde programlama dilleri kullanılarak üretilen yazılımların neden yalnızca onlarla çalıştığının teknik ayrıntılarını belirlemeye çalışıyorum.

Anladığım kadarıyla, ikililerin, anladıkları işlemciye özel makine dili ve farklı işlemciler arasındaki farklı komut setleri nedeniyle belirli işlemcilere özgü oldukları anlaşılıyor. Peki işletim sisteminin özgüllüğü nereden geliyor? İşletim sistemi tarafından sağlanan API'ler olduğunu varsayıyordum ama sonra bu diyagramı bir kitapta gördüm: Diyagram

İşletim Sistemleri - İç Tasarım ve Tasarım İlkeleri 7. Baskı - W. Stallings (Pearson, 2012)

Gördüğünüz gibi, API'ler işletim sisteminin bir parçası olarak gösterilmez.

Örneğin, aşağıdaki kodu kullanarak C'de basit bir program hazırlarsam:

#include<stdio.h>

main()
{
    printf("Hello World");

}

Derleyici bunu derlerken işletim sistemine özgü bir şey yapıyor mu?


15
Bir pencereye yazdırıyor musunuz? ya da bir konsol? veya grafik belleğine? Verileri oraya nasıl koyuyorsunuz? Printf Apple'a bakmak] [+ bir Mac OS 7'den farklı, Mac OS X'ten de oldukça farklı (sadece bir bilgisayar hattına bağlı kalacaktır).

3
Çünkü bu kodu Mac OS 7 için yazdıysanız, metin yeni bir pencerede görünecektir. Apple'da yaptıysanız] [+, doğrudan bir bellek bölümüne yazıyordu. Mac OS X'te, bir konsola yazar. Böylece, bu kütüphane katmanı tarafından işlenen yürütme donanımına bağlı olarak kodu işleyen üç farklı yazma yöntemidir.

2
@StevenBurnap evet - en.wikipedia.org/wiki/Aztec_C

10
FFT işleviniz Windows veya Linux altında (aynı CPU'da) yeniden derleme yapmadan mutlu bir şekilde çalışacaktır. Ama sonucu nasıl göstereceksin? Tabii ki bir işletim sistemi API'si kullanmak. ( printffrom msvcr90.dll, printflibc.so.6 ile aynı değildir )
user253751

9
API'ler "işletim sisteminin bir parçası olmasa bile", bir işletim sisteminden diğerine geçerseniz farklılar. (Ki, elbette, şemaya göre, ifade "işletim sisteminin bir parçası olmayan" gerçekten ne anlama geldiğini sorusunu gündeme getirmektedir.)
Theodoros Chatzigiannakis

Yanıtlar:


78

Kodun bir CPU'ya özgü olup olmadığı, neden bir işletim sistemine özgü olması gerektiğinden bahsettiniz. Bu aslında burada cevapların çoğunun varsaydığı ilginç bir soru.

CPU Güvenlik Modeli

Çoğu CPU mimarisinde çalışan ilk program , iç halka veya halka 0 olarak adlandırılanın içinde çalışır . Belirli bir CPU kemerinin halkaları nasıl uyguladığı değişebilir, ancak neredeyse her modern işlemcinin en az 2 işlem modu vardır, bunlardan biri ayrıcalıklı ve işlemcinin yapabileceği herhangi bir yasal işlemi gerçekleştirebilen 'çıplak metal' kodunu çalıştıran en az 2 işlem moduna sahiptir. güvenilmez ve yalnızca tanımlanmış güvenli bir yetenek kümesi gerçekleştirebilen korumalı kod çalıştırır. Ancak bazı CPU'lar çok daha yüksek ayrıntı derecesine sahiptir ve VM'lerin güvenli bir şekilde kullanılması için en az 1 veya 2 ekstra halka gerekir (genellikle negatif sayılarla etiketlenir), ancak bu cevabın kapsamı dışındadır.

İşletim sisteminin geldiği yer

Erken dönem tekli görevli işletim sistemleri

Çok erken DOS ve diğer ilk görev tabanlı sistemlerde tüm kodlar iç halkada çalıştırıldı, koştuğunuz her program tüm bilgisayar üzerinde tam güce sahipti ve tüm verilerinizi silmeyi veya hatta donanımın zarar görmesini de içeren bir haksızlığa uğradıysa tam anlamıyla bir şey yapabilirdi. çok eski ekranlarda geçersiz ekran modlarının ayarlanması gibi bazı aşırı durumlarda, daha da kötüsü, herhangi bir kötülük olmadan basitçe buggy kodundan kaynaklanıyor olabilir.

Aslında bu kod, büyük ölçüde işletim sistemi agnostiği idi, programı belleğe yükleyebilecek bir yükleyiciye sahip olduğunuzda (erken ikili biçimler için oldukça basit) ve kod, herhangi bir sürücüye güvenmiyordu, kod altında çalışması gereken tüm donanım erişimini uyguladı. halka 0'da çalıştığı sürece herhangi bir işletim sistemi. Not, bunun gibi çok basit bir işletim sistemine, diğer programları çalıştırmak için kullanılırsa ve ek işlevsellik sağlamazsa genellikle monitör denir .

Modern çoklu görev işletim sistemleri

Daha modern işletim sistemleri UNIX dahil , sürümleri NT ile başlayan Windows'un ve diğer çeşitli şimdi belirsiz işletim sistemleri bu durumla ilgili, kullanıcılar ek özellikler istediğini geliştirmek için karar böyle çoklu görev olarak tek seferde birden fazla uygulamayı çalıştırmak böylece ve koruma, böylece bir hata ( veya kötü amaçlı kod) bir uygulamada artık makine ve verilere sınırsız zarar veremez.

Bu, yukarıda belirtilen halkalar kullanılarak yapıldı, işletim sistemi, halka 0'da çalışan tek yeri alacak ve uygulamalar, güvenilmeyen dış halkalarda çalışacak, ancak işletim sisteminin izin verdiği sınırlı bir işlem setini gerçekleştirebilecektir.

Bununla birlikte, bu artan fayda ve koruma bir maliyet getirdi, programlar artık işletim sistemi ile kendileri yapmasına izin verilmeyen işleri yapmak için çalışmak zorunda kaldılar, örneğin artık belleğine erişerek ve isteğe bağlı olarak değiştirerek sabit disk üzerinde doğrudan kontrol sahibi olamıyorlardı. veri yerine, işletim sisteminden kendilerine bu işleri yapmalarını istemek zorunda kaldılar, böylece kendilerine ait olmayan dosyaları değiştirmeden işlemi gerçekleştirmelerine izin verilip verilmediğini kontrol edebilsinlerdi, ayrıca işlemin gerçekten geçerli olduğunu ve donanımı tanımsız bir durumda bırakmaz.

Her bir işletim sistemi, kısmen bu işletim sisteminin tasarlandığı mimariye dayanan ve kısmen de söz konusu işletim sisteminin tasarımına ve ilkelerine dayanan bu korumalar için farklı bir uygulamaya karar verdi, örneğin, UNIX çok kullanıcılı kullanım için iyi ve odaklanmış makinelere odaklandı. Windows için daha basit olacak şekilde tasarlanırken, tek bir kullanıcıyla daha yavaş donanımlarda çalışacak şekilde kullanılabilir. Kullanıcı alanı programlarının işletim sistemi ile konuşma şekli de X86'da tamamen farklıdır, örneğin ARM veya MIPS'de olduğu gibi, çoklu platform işletim sistemini hedef aldığı donanım üzerinde çalışma gereksinimi temelinde kararlar almaya zorlar.

Bu işletim sistemine özgü etkileşimler genellikle "sistem çağrıları" olarak adlandırılır ve bir kullanıcı alanı programının işletim sistemi aracılığıyla donanımla tamamen nasıl etkileşime girdiğini kapsar, işletim sisteminin işlevine bağlı olarak temelde farklılık gösterir ve bu nedenle sistem çağrıları aracılığıyla işini yapan bir program, işletim sistemine özgü olun.

Program Yükleyici

Sistem çağrılarına ek olarak, her bir işletim sistemi bir programı ikincil depolama ortamından ve belleğe yüklemek için farklı bir yöntem sunar , belirli bir işletim sistemi tarafından yüklenebilmesi için, programın işletim sistemine nasıl olabileceğini açıklayan özel bir başlık içermesi gerekir. yüklü ve çalıştırın.

Bu başlık , farklı bir format için bir yükleyici yazmanın neredeyse önemsiz olduğu kadar basitti , ancak dinamik bağlantı ve zayıf bildirimler gibi gelişmiş özellikleri destekleyen elf gibi modern biçimlerde, bir işletim sisteminin ikili yüklemeyi denemesi neredeyse imkansız bunun için tasarlanmadı, bunun anlamı, sistem çağrısı uyumsuzlukları olmasa bile, bir programın çalıştırılabileceği bir biçimde koç olarak yerleştirilmesi bile çok zor.

Kütüphaneler

Programlar nadiren doğrudan sistem çağrılarını kullanırlar, ancak neredeyse tamamen işlevselliklerini kazanırlar; ancak, sistem çağrılarını programlama dili için biraz daha dostça bir formatta saran kütüphaneler; Windows NT ve üzeri, diğer programlama dillerinin çoğunda, sistem işlevselliğini uygun bir şekilde saran benzer kütüphaneler bulunur.

Bir dereceye kadar, hatta çapraz platform sorunları üstesinden gelebilir Bu kütüphaneler içten işletim sistemleri geniş bir yelpazede çağrı yönetirken uygulamalara tek tip platform sunarak etrafında tasarlanmış kütüphanelerin bir dizi vardır, yukarıda açıklandığı gibi bu tür SDL olarak , bu durum olsa gelir programlar ikili uyumlu olamaz, bu kütüphaneleri kullanan programlar platformlar arasında ortak bir kaynağa sahip olabilir, bu da portlamayı yeniden derlemek kadar basit hale getirir.

Yukarıdaki istisnalar

Burada söylediğim her şeye rağmen, birden fazla işletim sisteminde programlar yürütememenin sınırlarını aşma girişimleri olmuştur. Bazı iyi örnekler, hem win32 program yükleyicisini, ikili formatı hem de Windows programlarının çeşitli UNIX'lerde çalışmasına izin veren sistem kitaplıklarını başarıyla taklit eden Wine projesidir . Ayrıca birçok BSD UNIX işletim sisteminin Linux yazılımı kullanmasına ve tabii ki Apple'ın MacOS X altında eski MacOS yazılımının çalıştırılmasına izin vermesine olanak tanıyan bir uyumluluk katmanı var.

Bununla birlikte, bu projeler muazzam düzeyde el geliştirme çabasıyla çalışır. İki işletim sisteminin zorluk derecesinin ne kadar farklı olduğuna bağlı olarak, genellikle işletim sisteminin tamamını kendi başına yazmaktan daha karmaşık olan diğer işletim sisteminin neredeyse tam bir emülasyonuna kadar oldukça küçük bir çerçeveden, kurallara göre istisna değildir.


6
+1 "Yazılım işletim sistemi neden özel?" Çünkü tarih.
Paul Draper,

2
CPU güvenlik modeli x86 kaynaklı mı? Model neden ve ne zaman icat edildi?
n611x007

8
@naxa Hayır, uzun zamandır x86'dan önce, kısmen GE-645 bilgisayarında bu modeli gerektiren kullanışlı çok kullanıcılı zaman paylaşım özelliklerine sahip ilk işletim sistemi olan 1969'da Multics için kısmen uygulandı , ancak bu uygulama eksik ve güvenildi. Yazılım desteği, donanımdaki ilk eksiksiz ve güvenli uygulama halefi olan Honeywell 6180'de yapıldı . Bu tamamen donanım temelliydi ve Multics'in birden fazla kullanıcıdan kodları karışmasına izin vermeden kod çalıştırmasına izin veriyordu.
Vality

@Vality Ayrıca, IBM LPAR ~ 1972'dir .
Elliott Frisch

@ElliottFrisch vay, bu etkileyici. Oldukça erken olduğunu farketmemiştim. Bu bilgi için teşekkürler.
Vality

48

Gördüğünüz gibi, API'ler işletim sisteminin bir parçası olarak gösterilmez.

Bence diyagramda çok fazla okuyorsun. Evet, bir işletim sistemi işletim sistemi işlevlerinin nasıl çağrılacağı için bir ikili arayüz belirleyecektir ve ayrıca çalıştırılabilir dosyalar için bir dosya formatı da tanımlayacaktır, fakat aynı zamanda tarafından çağrılabilecek bir fonksiyonlar kataloğu sağlama anlamında bir API sağlayacaktır. İşletim sistemi servislerini çağırmak için bir uygulama.

Diyagramın, işletim sistemi işlevlerinin genellikle basit bir kütüphane çağrısından farklı bir mekanizma aracılığıyla başlatıldığını vurgulamaya çalıştığını düşünüyorum. Yaygın olarak kullanılan işletim sistemi kullanımının çoğu, işletim sistemi işlevlerine erişmek için işlemci kesintilerini engeller. Tipik modern işletim sistemleri, bir kullanıcı programının herhangi bir donanıma doğrudan erişmesine izin vermeyecektir . Konsola bir karakter yazmak istiyorsanız, işletim sisteminden sizin için yapmasını istemeniz gerekecektir. Konsola yazmak için kullanılan sistem çağrısı işletim sisteminden işletim sistemine göre değişecektir, bu nedenle yazılımın işletim sistemine neden özel olduğuna dair bir örnek vardır.

printf C çalışma zamanı kütüphanesinden bir fonksiyondur ve tipik bir uygulamada oldukça karmaşık bir fonksiyondur. Google’ı kullanıyorsanız, çevrimiçi olarak birkaç sürümün kaynağını bulabilirsiniz. Rehberli tur için bu sayfaya bakınız . Çimenlerde bir veya daha fazla sistem çağrısı yapsa da sona erer ve bu sistem çağrıları her biri ana bilgisayar işletim sistemine özgüdür.


4
Tüm program ne yaptıysa, giriş veya çıkış olmadan iki sayı eklemek olsaydı. Bu program hala işletim sistemine özel midir?
Paul,

2
OS'lerin, donanıma özgü çoğu malzemeyi bir soyutlama katmanının arkasına / arkasına koyması amaçlanmıştır. Ancak, işletim sisteminin kendisi (soyutlama) uygulamadan uygulamaya kadar farklılık gösterebilir. Bazı OS'lerin (az ya da çok) POSIX ve belki bazılarına uyduğu, ancak genel OS'lerin soyutlamanın “görünür” kısmında çok fazla farklılık gösterdiği POSIX var. Daha önce de söylediğim gibi: / home / kullanıcı pencerelerini açamazsınız ve * N * X sisteminde HKEY_LOCAL_MACHINE \ ... erişemezsiniz. Sen olabilir bu birbirine yaklaştırır bu sistemleri getirmek için ancak bu her zaman (OS POV itibaren) "3. parti" olacaktır için sanal ( "öykünme") yazılım geliştiriyorum.
RobIII

16
@Paul Evet. Özellikle, bir çalıştırılabilir paket içinde paketlenme şekli işletim sistemine özgüdür.
OrangeDog

4
@TimSeguine XP vs 7 örneğinizle aynı fikirde değilim. Aynı API'nin XP'de olduğu gibi 7'de varlığını sağlamak için Microsoft tarafından çok iş yapıldı. Açıkçası burada olan şey, programın belirli bir API veya sözleşmeye karşı çalışmak üzere tasarlandığı. Yeni işletim sistemi sadece aynı API / sözleşmeye bağlı kaldı. Ancak, pencereler söz konusu olduğunda, bu API çok özel bir şirkettir, bu nedenle başka hiçbir OS satıcısının desteklememesinin nedeni budur. O zaman bile 7 üzerinde çalışmayan birçok program örneği var.
ArTs

3
@Paul: Giriş / Çıkış yapmayan bir program, çalışmama için derlenmesi gereken boş programdır .
Bergi

14

Derleyici bunu derlerken işletim sistemine özgü bir şey yapıyor mu?

Muhtemelen. Derleme ve bağlama işlemi sırasında bir noktada, kodunuz işletim sistemine özgü bir ikiliye dönüştürülür ve gerekli tüm kitaplıklar ile ilişkilendirilir. Programınızın işletim sisteminin beklediği biçimde kaydedilmesi gerekir, böylece işletim sistemi programı yükleyebilir ve uygulamayı başlatabilir. Ayrıca, standart kütüphane işlevini çağırıyorsunuzprintf() işletim sisteminin sağladığı hizmetler açısından bir düzeyde uygulanan .

Kütüphaneler bir işletim sistemi - işletim sistemi ve donanımdan bir soyutlama katmanı - ve farklı bir işletim sistemi veya farklı bir donanım için programınızı yeniden derlemenizi mümkün kılar. Ancak bu soyutlama kaynak düzeyde mevcuttur - program derlenip bağlandıktan sonra, belirli bir işletim sistemine özgü bu arayüzün belirli bir uygulaması ile bağlantılıdır.


12

Çok sayıda neden var, ancak çok önemli nedenlerden biri, İşletim Sisteminin, programınızı belleğe dönüştüren bayt dizilerini nasıl okuyacağını, programla birlikte giden kitaplıkları bulup bunları belleğe yüklemesini bilmesi gerektiği ve daha sonra program kodunuzu çalıştırmaya başlayın. Bunu yapmak için, işletim sisteminin yaratıcıları o bayt serisi için özel bir format oluştururlar, böylece işletim sistemi kodu programınızın yapısının çeşitli kısımlarını nerede arayacağını bilir. Ana İşletim Sistemlerinin farklı yazarları olduğundan, bu formatların birbirleriyle çok az ilgisi vardır. Özellikle, Windows çalıştırılabilir formatı , çoğu Unix varyantının kullandığı ELF formatıyla çok . Bu yüzden tüm bu yükleme, dinamik bağlantı ve kod çalıştırma işletim sistemine özgü olmalıdır.

Daha sonra, her bir işletim sistemi donanım katmanıyla konuşmak için farklı bir dizi kitaplık sağlar. Bunlar bahsettiğiniz API'lerdir ve genellikle geliştiriciye daha basit bir arayüz sunan ve işletim sisteminin kendisinin derinliklerine daha karmaşık, daha spesifik çağrılara dönüştürürken, bu çağrılar genellikle belgelenmemiş veya güvence altına alınmış olan kütüphanelerdir. Bu katman genellikle oldukça gri, daha yeni "İşletim Sistemi" API'leri kısmen veya tamamen eski API'ler üzerine kuruludur. Örneğin, Windows'ta, Microsoft'un yıllar içinde yarattığı yeni API'lerin çoğu, esasen orijinal Win32 API'lerinin üzerinde katmanlardır.

Örnekte ortaya çıkmayan, ancak geliştiricilerin karşılaştığı en büyük sorunlardan biri, bir GUI sunmak için pencere yöneticisi ile olan arayüzdür. Pencere yöneticisinin "İşletim Sistemi" nin bir parçası olup olmadığı, bazen sizin bakış açınıza ve işletim sisteminin kendisine bağlıdır; Windows'taki GUI, Linux'ta işletim sistemi ile daha derin bir düzeyde bütünleşirken, Linux ve OS X'deki GUI'ler daha derin bir düzeydedir. daha doğrudan ayrılmış. Bu çok önemlidir, çünkü bugün insanların tipik olarak "İşletim Sistemi" dedikleri şey, pek çok uygulama düzeyinde bileşen içerdiğinden, ders kitaplarının tarif etme eğiliminden çok daha büyük bir canavardır.

Son olarak, kesinlikle bir işletim sistemi sorunu değil, çalıştırılabilir dosya üretiminde önemli bir konu, farklı makinelerin farklı montaj dili hedeflerine sahip olmasıdır ve bu nedenle gerçek oluşturulan nesne kodunun farklı olması gerekir. Bu, kesinlikle bir "İşletim Sistemi" sorunu değil, bir donanım sorunu olmaktan öte, ancak farklı donanım platformları için farklı yapılara ihtiyaç duyacağınız anlamına geliyor.


2
Daha basit çalıştırılabilir formatların, yüklü kodu tutmak için gerekenden daha az miktarda RAM (varsa) kullanarak yüklenebileceğini, daha karmaşık formatlar ise bazı durumlarda daha büyük bir RAM ayak izi gerektirebilir. sonra bile, yükleme. MS-DOS, rasgele bir kesimin 0x100 ofsetinden başlayarak RAM'e sıralı baytları okuyarak, rasgele baytları okuyarak, 63.75K'a kadar COM dosyalarını yükler, bitiş adresini içeren CX'i yükler ve buna atlar. Tek geçişli derleme, arka yama (
flopies

1
... derleyiciye, her bir rutinde, her biri önceki listenin adresini içerecek olan tüm yama noktalarının bir listesini içeren ve son listenin adresini kodun sonuna koyarak. İşletim sistemi kodu yalnızca ham bayt olarak yükler, ancak kodun küçük bir yordamı, kodun ana bölümünü çalıştırmadan önce tüm gerekli adres düzeltme eklerini uygulayabilir.
supercat,

9

Gönderen başka bir yanıt madeninin:

Erken DOS makinelerini ve Microsoft'un dünyaya gerçek katkısının ne olduğunu düşünün:

Autocad, yazdırabilecekleri her yazıcı için sürücüler yazmak zorunda kaldı. Lotus da 1-2-3 yaptı. Aslında, yazılımınızın yazdırılmasını istiyorsanız, kendi sürücülerinizi yazmak zorunda kaldınız. 10 yazıcı ve 10 program olsaydı, esasen aynı kodun 100 ayrı parçası ayrı ayrı ve bağımsız olarak yazılmalıydı.

Windows 3.1'in başarmaya çalıştığı şey (GEM ve diğer birçok soyutlama katmanıyla birlikte), yazıcı üreticisinin yazıcısı için bir sürücü yazması ve programcının Windows yazıcı sınıfı için bir sürücü yazmasıdır.

Şimdi 10 program ve 10 yazıcı ile sadece 20 parça kodun yazılması gerekiyor ve kodun microsoft tarafı herkes için aynı olduğundan, o zaman MS'ten örnekler yapmak için çok az çalışmanız gerektiği anlamına geliyordu.

Şimdi, bir program desteklemeyi seçtiği sadece 10 yazıcı ile sınırlı kalmadı, fakat üreticileri Windows için sürücü sağlayan tüm yazıcılarla sınırlıydı.

Böylece işletim sistemi uygulamalara hizmet verir, böylece uygulamaların gereksiz olan işleri yapmasına gerek kalmaz.

Örnek C programınız karakterleri stdout'a gönderen printf'yi kullanır - karakterleri kullanıcı arayüzünde gösterecek olan işletim sistemine özgü bir kaynak. Programın kullanıcı arayüzünün nerede olduğunu bilmesi gerekmez - DOS'ta olabilir, grafiksel bir pencerede olabilir, başka bir programa aktarılabilir ve başka bir işleme girdi olarak kullanılabilir.

İşletim sistemi bu kaynakları sağladığı için programcılar çok az işle daha fazlasını başarabilirler.

Bununla birlikte, bir program başlatmak bile karmaşıktır. İşletim sistemi yürütülebilir bir dosya bekliyor başlangıçta işletim sistemine nasıl başlatılması gerektiğini ve bazı durumlarda (android veya iOS gibi daha gelişmiş ortamlar) dış kaynaklara dokundukları için onaylanması gereken hangi kaynaklara ihtiyaç duyulacağını söyleyen belirli bilgilere sahip . "sandbox" - kullanıcıları ve diğer uygulamaları yaramazlık programlarından korumaya yardımcı olan bir güvenlik önlemidir.

Bu nedenle, çalıştırılabilir makine kodu aynı olsa ve hiçbir işletim sistemi kaynağı gerekli olmasa bile, Windows için derlenen bir program, aynı donanımda bile ek bir öykünme veya çeviri katmanı olmadan OS X işletim sisteminde çalışmaz.

Eski DOS tarzı işletim sistemleri sık sık programları paylaşabilirdi, çünkü aynı API'yi donanımda (BIOS) uyguladılar ve işletim sistemi donanım sağlamak için donanıma takıldılar. Bu nedenle , bir dizi işlemci talimatının yalnızca bir bellek görüntüsü olan bir COM programı yazıp derlediyseniz , onu CP / M, MS-DOS ve diğer işletim sistemlerinde çalıştırabilirsiniz. Aslında hala modern Windows makinelerinde COM programları çalıştırabilirsiniz. Diğer işletim sistemleri aynı BIOS API kancalarını kullanmaz, bu nedenle COM programları bir öykünme veya çeviri katmanı olmadan bunlar üzerinde çalışmaz. EXE programları sadece işlemci talimatlarından çok daha fazlasını içeren bir yapı izler ve böylece API sorunları ile birlikte belleğe nasıl yükleneceğini ve çalıştırılacağını anlamayan bir makinede çalışmaz.


7

Aslında, asıl cevap, eğer her işletim sistemi aynı çalıştırılabilir ikili dosya düzenini anladıysa ve kendinizi yalnızca işletim sisteminizin sağladığı (hangi işletim sistemlerinin sağladığı) standartlaştırılmış işlevlerle (C standart kütüphanesinde olduğu gibi) sınırlandırırsanız , , aslında, herhangi bir işletim sistemi üzerinde çalıştırın.

Tabii ki, gerçek bu böyle değil. Her ikisi de aynı CPU için ikili kod içermesine rağmen, EXEbir ELFdosya bir dosyayla aynı biçime sahip değildir . * Bu nedenle, her işletim sisteminin tüm dosya biçimlerini yorumlayabilmesi gerekir ve bunu basitçe yapmazlardı. içinde ve daha sonra başlaması için bir neden yoktu (teknik olarak değil, kesinlikle ticari nedenlerle).

Ayrıca, programınızın muhtemelen C kütüphanesinin nasıl yapılacağını tanımlamaması gereken şeyleri yapması gerekir (bir dizinin içeriğini listeleme gibi basit şeyler için bile) ve bu durumlarda, her işletim sistemi kendi başarınızı sağlamak için kendi işlevlerini sağlar. Görev, doğal olarak, kullanmanız için en düşük ortak paydaya sahip olmayacağınız anlamına gelir ( bu paydayı kendiniz yapmazsanız ).

Yani prensipte, bu tamamen mümkün. Aslında, WINE, Windows çalıştırılabilir dosyalarını doğrudan Linux üzerinde çalıştırır .
Fakat bu bir ton iş ve (genellikle) ticari olarak haksız.

* Not: Yürütülebilir bir dosyada sadece ikili koddan çok daha fazlası var. İşletim sistemine, dosyanın hangi kitaplıklara bağlı olduğunu, ne kadar yığın bellek gerektirdiğini, ona bağlı olabilecek diğer kitaplıklara hangi işlevleri dışa aktardığını, işletim sisteminin ilgili hata ayıklama bilgilerini nerede bulabileceğini gösteren bir ton bilgi vardır . " Gerekirse, bellekteki dosyayı yeniden konumlandırın, istisna işlemenin nasıl doğru bir şekilde yapılmasını sağlayın, vb. vb. Yine, bunun için herkesin kabul edeceği tek bir format olabilir , ancak yok.


Eğlenceli gerçek: OS'lerde çalıştırılabilecek standart bir posiz ikili formatı var. Sadece yaygın olarak kullanılmıyor.
Marcin

@Marcin: Windows'un bir işletim sistemi olduğunu düşünmüyor gibisiniz. (Ya da Windows POSIX ikili dosyalarını çalıştırabilir mi diyorsunuz ?!) Cevabımın amacı için POSIX atıfta bulunduğum standart tür değil. POSIX’deki X, Unix’in kısaltmasıdır. Windows bir POSIX alt sistemine sahip olsa bile, örneğin Windows tarafından kullanılma amacı gütmedi.
Mehrdad,

1. Bir şey tüm işletim sistemlerinde çalışmadan birden fazla işletim sisteminde çalışabilir; 2. NT'den beri Windows posix ikili dosyalarını çalıştırmayı başardı.
Marcin

1
@Marcin: (1) Dediğim gibi, POSIX’deki X, UNIX’in kısaltmasıdır . Diğer işletim sistemleri tarafından takip edilmesi amaçlanan bir standart değildir, sadece Unix'ler arasında ortak bir paydaya ulaşma çabasıydı, bu harika ama şaşırtıcı değil. Unix işletim sistemlerinde çok fazla lezzet olduğu gerçeği, Unix'ten başka işletim sistemlerinde uyumluluk konusunda yapmaya çalıştığım nokta ile tamamen alakasız . (2) # 2 için bir referans verebilir misiniz?
Mehrdad,

1
@Mehrdad: Marcin haklı; Windows SUA (Unix Uygulamaları için Alt Sistem) POSIX uyumludur
MSalters

5

Şemada, "işletim sistemi" katmanından "kitaplıklar" ile ayrılmış "uygulama" katmanı (çoğunlukla) bulunmaktadır ve bu "uygulama" ve "işletim sistemi" nin birbirini bilmesi gerekmediği anlamına gelir. Bu, şemadaki bir sadeleştirmedir, ancak tam olarak doğru değildir.

Sorun şu ki, "kütüphane" aslında üç bölümden oluşuyor: uygulama, uygulama arayüzü ve işletim sistemi arayüzü. Prensip olarak, ilk ikisi işletim sistemi ile ilgili olarak "evrensel" yapılabilir (bu, nerede dilimlediğinize bağlıdır), ancak üçüncü kısım - işletim sisteminin arayüzü - genellikle yapamaz. İşletim sisteminin arayüzü mutlaka işletim sistemine, sağladığı API'lere, paketleme mekanizmasına (örneğin, Windows DLL tarafından kullanılan dosya formatı) vb. Bağlı olacaktır.

"Kütüphane" genellikle tek bir paket olarak kullanıma sunulduğundan, program bir kez kullanmak için bir "kütüphane" seçtiğinde, belirli bir işletim sistemine taahhüt anlamına gelir. Bu iki yoldan biri olur: a) programlayıcı tamamen önceden alır ve daha sonra kütüphane ile uygulama arasındaki bağ evrensel olabilir, ancak kütüphanenin kendisi işletim sistemine bağlıdır; veya b) programcı işleri kurar, böylece programı çalıştırdığınızda kütüphane seçilir, ancak daha sonra ciltleme mekanizması program ile kitaplık arasındaki kendisi işletim sistemine bağımlıdır (örn. Windows'taki DLL mekanizması). Her birinin kendine göre avantajları ve dezavantajları vardır, ancak her iki şekilde de önceden bir seçim yapmanız gerekir.

Şimdi, bu yapmanın imkansız olduğu anlamına gelmez, ama çok zeki olmalısın. Sorunun üstesinden gelmek için, çalışma zamanında kütüphaneyi seçme yoluna gitmeniz ve işletim sistemine bağlı olmayan evrensel bir bağlayıcı mekanizma geliştirmeniz gerekecekti (bu nedenle bunu sürdürmek konusunda sorumlusunuz, çok daha fazla iş). Bazı zamanlar buna değer.

Zorunda değilsiniz, ancak bunu yapmak için çaba sarfedecekseniz, belirli bir işlemciye bağlı kalmak istemediğiniz için iyi bir ihtimal var, yani bir Sanal Makine yazacak ve derleyeceksiniz. Programınızı bir işlemci nötr kod biçiminde.

Şimdi nereye gittiğimi farketmeliydin. Java gibi dil platformları tam olarak bunu yapıyor. Java çalışma zamanı (kütüphane), Java programınızla kütüphane (OS çalışma zamanının nasıl açılıp programınızı çalıştıracağı) arasındaki OS-nötr bağlamayı tanımlar ve mevcut işletim sistemine özgü bir uygulama sağlar. .NET, aynı şeyi bir ölçüde yapar; ancak Microsoft, Windows dışında hiçbir şey için bir "kitaplık" (çalışma zamanı) sağlamaz (ancak diğerleri Mono'yu görür). Ve aslında, Flash, Tarayıcı için daha sınırlı olmasına rağmen aynı şeyi yapar.

Son olarak, özel bir ciltleme mekanizması olmadan aynı şeyi yapmanın yolları vardır. Geleneksel araçlar kullanabilirsiniz, ancak kullanıcı işletim sistemi seçilinceye kadar bağlama adımını kütüphaneye erteleyin. Kaynak kodu dağıttığınızda tam olarak ne olur. Kullanıcı programınızı alır ve kullanıcı çalışmaya hazır olduğunda işlemciye (derleme) ve işletim sistemine (bağlantı) bağlar.

Her şey katmanları nasıl dilimlediğinize bağlı. Günün sonunda, her zaman belirli bir makine kodunu çalıştıran belirli bir donanıma sahip bir bilgi işlem cihazınız vardır. Katmanlar büyük ölçüde kavramsal bir çerçeve olarak var.


3

Yazılım her zaman işletim sistemine özgü değildir. Hem Java hem de önceki p kod sistemi (ve hatta ScummVM), İşletim Sistemleri arasında taşınabilir bir yazılıma izin verir. Infocom ( Zork ve Z-makinesi üreticileri ), başka bir sanal makineye dayanan ilişkisel bir veri tabanına sahipti . Bununla birlikte, bir seviyede, bu soyutlamaları bile bilgisayarda yürütülecek gerçek talimatlara çevirmek zorundadır.


3
Java, çapraz-işletim sistemi olmayan sanal bir makinede çalışıyor. Her bir işletim sistemi için farklı bir JVM
binaryosu

3
@ Izkata Doğru, ancak yazılımı tekrar derlemiyorsunuz (sadece JVM). Ayrıca, son cümlemi gör. Ancak Sun'ın doğrudan byte kodunu çalıştırabilecek bir mikro işlemciye sahip olduğunu belirteceğim.
Elliott Frisch

3
Java bir işletim sistemidir, ancak genelde bir tane olarak düşünülmemektedir. Java yazılımı Java işletim sistemine özgüdür ve çoğu "gerçek" işletim sistemi için Java işletim sistemi emülatörleri vardır. Ancak aynı şeyi herhangi bir ana bilgisayarla ve hedef işletim sistemi ile de yapabilirsiniz - Windows yazılımını WINE kullanarak Linux'ta çalıştırmak gibi.
user253751

@ immibis Daha spesifik olurdum. Java Temel Sınıfları (JFC, Java'nın standart kütüphanesi) bir çerçevedir. Java'nın kendisi bir dildir. JVM bir işletim sistemine benzer: Adında "Sanal Makine" vardır ve içinde çalışan kod perspektifinden bir işletim sistemine benzer işlevleri gerçekleştirir.

1

Diyorsun

belirli işletim sistemleri için programlama dilleri kullanılarak üretilen yazılımlar yalnızca bunlarla çalışır

Ancak örnek olarak verdiğiniz program birçok işletim sistemi ve hatta bazı çıplak metal ortamlarda çalışacaktır.

Burada önemli olan, kaynak kod ile derlenmiş ikili arasındaki farktır. C programlama dili özellikle kaynak biçimde işletim sisteminden bağımsız olacak şekilde tasarlanmıştır. Bunu, "konsola yazdır" gibi şeylerin yorumunu uygulayıcıya bırakarak yapar. Ancak C, işletim sistemine özgü bir şeye uyulabilir (nedenlerden dolayı diğer cevaplara bakınız). Örneğin, PE veya ELF çalıştırılabilir formatları.


6
OP'nin kaynak kodundan değil, ikili dosyalar hakkında soru sorduğu açıkça görülüyor.
Caleb,

0

Diğer insanlar teknik detayları iyi ele aldılar, daha az teknik bir nedenden bahsettim, UX / UI tarafı:

Bir Kez Yaz, Her Yerde Garip Hisset

Her işletim sisteminin kendi kullanıcı arayüzü API'leri ve tasarım standartları vardır. Bir program için bir kullanıcı arayüzü yazmak ve çoklu işletim sistemlerinde çalışmasını sağlamak mümkündür, ancak hepsini yapar ancak programın her yerde kendini yerinde hissetmediğini garanti eder. İyi bir kullanıcı arayüzü oluşturmak, desteklenen her platform için ayrıntıların ince ayarını gerektirir.

Bunların birçoğu küçük ayrıntılardır, ancak bunları yanlış anlayın ve kullanıcılarınızı hayal kırıklığına uğratın:

  • Windows ve OSX'te iletişim kutularının düğmelerini farklı sırada bulunduğunu doğrulayın; bu yanlış olsun ve kullanıcılar kas hafızası tarafından yanlış düğmeye basacaktır. Windows bu sırada "Tamam", "İptal" seçeneğine sahiptir. OSX emri değiştirdi ve do-it düğmesinin metni gerçekleştirilecek eylemin kısa bir açıklaması: "İptal", "Çöp Kutusuna Taşı".
  • "Geri dön" davranışı iOS ve Android için farklıdır. iOS uygulamaları, genellikle sol üstte gerektiği gibi kendi geri düğmelerini çizer. Android ekranın dönmesine bağlı olarak sol alt veya sağ alt kısımda özel bir düğmeye sahiptir. OS geri düğmesi göz ardı edilirse Android hızlı bağlantı noktaları yanlış davranır.
  • Momentum kaydırma iOS, OSX ve Android arasında farklıdır. Ne yazık ki, yerel kullanıcı arayüzü kodu yazmıyorsanız, muhtemelen kendi kaydırma davranışınızı yazmanız gerekir.

Her yerde çalışan bir UI kod tabanı yazmak teknik olarak mümkün olsa bile, desteklenen her işletim sistemi için ayarlamalar yapmak en iyisidir.


-2

Bu noktada önemli bir ayrım, derleyiciyi linkerden ayırmaktır. Derleyici büyük olasılıkla aynı çıktının az çok üretilmesine neden olur (farklar çoğunlukla çeşitli nedenlerden kaynaklanmaktadır #if WINDOWS). Öte yandan, linker, platforma özgü tüm malzemeleri ele almalıdır - kütüphaneleri birbirine bağlar, yürütülebilir dosyayı oluşturur.

Başka bir deyişle, derleyici daha çok CPU mimarisini önemser, çünkü gerçek çalıştırılabilir kodu üretir ve CPU'nun talimatlarını ve kaynaklarını kullanmak zorundadır (.NET’in IL veya JVM’nin bytecode’u sanal bir CPU’nun komut kümesi olarak kabul edilir. Bu görünümde). Bu nedenle x86ve için ayrı ayrı kod derlemelisiniz.ARM örneğin.

Öte yandan linker, tüm bu ham veri ve talimatları almak zorundadır ve yükleyicinin (bugünlerde bu hemen hemen her zaman işletim sistemi olacaktı) ve statik olarak bağlantılı tüm kütüphaneleri bağlayabileceği bir formatta koymak zorundadır. (ayrıca dinamik bağlantı, hafıza ayırma vb. için gereken kodu da içerir).

Başka bir deyişle, sadece bir kez kodunu derlemek ve Linux hem de Windows üzerinde çalışan olması mümkün olabilir - ama buna mecbur bağlantı iki farklı oluşturarak iki kez gerekir. Şimdi, pratikte, sıklıkla kodda da tahsisat yapmak zorundasınız ((derleyici yönergelerin bulunduğu yer) bu yüzden bir kere-link derlemek bile iki kez kullanılmıyor. İnsanların derlemeyi ele aldıklarından ve derleme sırasında tek bir adım olarak bağlandıklarından bahsetmiyorum bile (tıpkı derleyicinin parçalarını artık umursamamanız gibi).

DOS çağındaki yazılımlar genellikle daha fazla ikili taşınabilirdi, ancak DOS veya Unix'e karşı değil, çoğu IBM tarzı PC için de ortak olan belirli bir sözleşmeye karşı derlendiğini anlamalısınız. yazılım kesintileri. Bunun için statik bağlamaya gerek yoktu, çünkü sadece gerekli kayıtları ayarlamanız, örneğin int 13hgrafik fonksiyonlarını çağırmanız ve CPU, kesme tablosunda belirtilen bir hafıza göstericisine atladı. Tabii ki, yine de pratik çok zordu, çünkü metaller arasında pedal performansı elde etmek için, tüm bu yöntemleri kendiniz yazmak zorunda kaldınız, ancak bu temel olarak tamamen işletim sistemi etrafında dolaşmak için yeterliydi. Ve elbette, OS API - program sonlandırması ile etkileşimi kaçınılmaz olarak gerektiren bir şey var. Fakat yine de, mevcut en basit biçimleri kullanıyorsanız (ör.COMDOS'ta, başlığı yok, sadece talimatlar var) ve çıkmak istemedi, iyi - şanslısın! Ve tabii ki, çalışma zamanında da uygun sonlandırmayı işleyebilir, böylece aynı çalıştırılabilir programda hem Unix sonlandırmasını hem de DOS sonlandırmasını kodlayabilir ve hangisini kullanacağınızı tespit edebilirsiniz :)


Bu sadece bu konuda açıklanan noktaları ve dün yayınlanan bu önceki cevapları tekrarlıyor gibi görünüyor
gnat
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.