Home Index Search Links About Us
  News   Archives   Companies   Tips  

Paylaşımlı Kitaplıkların Yapımı

Yazar: Luis Colorado

Çeviri: Emre Demiralp


Süreç

Tarihçe

Kitaplık

Türler

Bağlama İşlemleri

link

soname

ldconfig

Kitaplık Yapımı

Derleme

Bağlama

Kurulum (Devinimli)

Durağan

Kaynaklar

Kurulum (Durağan)

Devinimliye karşı Durağan Bağlantı

1.- Bir program üretme süreci. Giriş. 

Bugünlerde geliştirme çevrelerinde bir program üretme süreci, programcıların ve tasarımcıların, alışkanlık ve deneyimlerde yaşadıkları, evrimin meyvesidir.

Bu süreç aşağıdaki adımlardan oluşur:

  • Kaynakyazılımın bir metin dosyadüzenleyicisi yardımıyla yüksek düzeyli bir dilde yaratımı. Çok büyük programların işlenmeleri, tek bir dosya içinde tutulmak istenmeleri durumunda, oldukça zordur. Bu nedenle, kaynakyazılım, birkaç kaynakyazılımdan oluşturulmuş işlevsel modüllere bölünürler. Bu modüllerdeki kaynakyazılımın, bazı dillerin belirgin bir görevi diğerlerinden daha iyi yapabilmeleri nedeniyle, aynı dilde yazılma zorunluluğu yoktur.

  • Program için kaynakyazılım dosyalarının, yaratılımdan sonra, nesnel düzgü (object code) olarak adlandırılabilen ve makinenin yerine getirebileceği, düzgü kesimlerine (segment of code) dönüştürülmesi gerekir. Bu düzgü (kod), makinenin doğrudan yerine getirebileceği güdümlerde yazılmış olmakla birlikte kaynakyazılımla aynı işlemleri yerine getirir. Kaynakyazılımın nesnel düzgüye dönüştürülme süreci derleme (compilation) olarak bilinir. Derleme birimler tarafından gerçekleştirilir ve bir derleme oturumu, derleyiciye bağlı olarak, programın bir parçasını ve genelde yalnızca bir ya da birkaç dosyayı içerir. Derlenmiş nesnel düzgü, henüz dönüştürülmüş olan programın genel parçası içindeki program, altyordam, değişkenleri içerir ve bir sonraki aşamaya aktarır.

  • Program için makine dilindeki dosyaların tümünün üretilmesinden sonra bunların bağlayıcı adı verilen özel bir olanak aracılığıyla birleştirilmesine yönlenilir. Bu süreçte, bir modülde kullanülan güdümlerle bir başka modülden çağrılan (altyordam çağrıları ya da başka modüllere ait olan ya da başka modüllerde tanımlanan değişkenlere yapılan göndermeler gibi) tüm işlevler "bütünselleştirilir. Böylece oluşan yapı normal olarak doğrudan yüklenebilen ve koşulabilen bir programdır.

  • Bir programın çalıştırılması işletim sisteminin önemli bir parçası olan bir yazılım parçası tarafından gerçekleştirilir. Bu yazılım parçası, Linux durumunda exec() sistem çağrı fonksiyonudur. Bu fonksiyon dosyayı bulur, süreçlere bellek ataması yapar, dosya içeriğinin ( güdümleri ve değişkenlerin baçlangıç değerlerini içeren ) özel parçalarını yükler ve programda 'metin' (text) olarak genellikle çalıştırılabilen dosyanın kendisinde gösterilen noktada denetimi MİB (Merkezi İşlem Birimi)'ne aktarır.

2.- Program üretim süreçlerinin kısa tarihçesi. 

Program üretim süreçleri, daima en etkin çalıştırılabilen programa erişmek ya da sistem kaynaklarını en iyi biçimde kullanmak için sürekli bir evrim geçirmektedir.

Başlangıçta, programlar doğrudan makine dilinde yazılırdı. Sonraları, daha yüksek düzeyli bir dilde program yazma ve yazılan programın makine diline çevrilmesinin, çevirme'nin sistematik doğası nedeniyle, özdevimlileştirilebileceği (otomatikleştirilebileceği) anlaşılmıştır. Bu durum, yazılım üretkenliğini arttırmıştır.

Programların derlenebilmesinin gündeme gelmesiyle ( Burada derlemenin evrimini çok basitleştirmiş bulunmaktayım, gerçekte bugünlere gelinebilmesi, derleme olayının çok karmaşık bir süreç olmasından dolayı, atılması çok güç gerçekleştirilebilmiş bir adımdı ), program üretim süreci program güdümlerinin içerildiği bir kaynak dosyasının yaratılması, onun derlenmesi ve son adım olarak da çalıştırılması aşamalarından oluşur duruma gelmiştir.

FORTRAN kullanımıyla görüldüğü üzere, kısa bir süre sonra, derleme sürecinin ederi çok yüksek olduğu ve çok fazla kaynak kullanımı ve MİB (Merkezi İşlem Birimi) gerektirdiği ve bu programlarda içerilen birçok fonksiyonun çeşitli programlarda yinelenerek defalarca kullanıldığı ortaya çıkarılmıştır. Üstelik, birilerinin programlarında değişiklik yapmaları durumunda, derleme, değişiklik yapılan kesimi derlemek için tüm kaynak yazılımın yeniden makine diline çevrilmek üzere derleyiciye verileceği anlamına gelmekteydi.

Bu durum, modüllerle derlemenin gündeme getirilmesinin nedeni olmuştur. Bu süreç, anaprogramın bir yana, sık sık defalarca kullanılan ve önceden derlenip ( bir kitaplık öncüsü gibi nitelendirebileceğimiz ) özel bir yerde belgeliklenmiş (arşivlenmiş) fonsiyonları bir yana ayrılması temeline dayanır.

Fazladan çaba göstererek programlarını defalarca devreye sokmaksızın programlar da yazılabilirdi. O zaman bile, programın bağlanma sürecinde tüm parçaların birleştirilmesinin gerekliliği ve bu işlevin programcı tarafından yerine getirilme zorunluluğunun ortaya çıkması nedeniyle, süreç karmaşık olacaktı ( Parça birleştirmedeki sıkıntı, bilinen bir fonksiyonun kullanılması durumunda bilinmeyen bir fonksiyonun devreye sokulma gereksiniminin ortaya çıkabilmesidir )


3.- Kitaplık Nedir?

Yukarıda sözü edilen sorun Kitaplıkların yaratılmasına yolaçmıştır. Kitaplık, özel bir tür dosyadan başka birşey değildir. Daha açık konuşmak gerekirse, onun tar(1) ya da cpio(1) türü bir belgelik (arşiv) olduğunu söyleyebiliriz. Bu dosya, bağlayıcının dosya biçimini anlayabileceği özgün nitelikler içerir. Kitaplık belgeliği (arşivi) belirtildiğinde BAĞLAYICI YALNIZCA PROGRAMIN GEREKTİRDİĞİ MODÜLLERİ SEÇER, bunların dışında başka bir şeyi devreye sokmaz. Yeni gündeme gelen bir başka yarar, artık büyük fonksiyon kitaplıklarının kullanılabilmesi ve programlayıcının kitaplık içindeki tüm fonksiyonlararası ilişkileri bilmek zorunda kalmaktan kurtarılması olmuştur.

Sözünü etmekte olduğumuz kitaplık bundan daha fazla gelişmiş değildir. O, yalnızca, belgeliğin (arşivin) başlangıcında yeralan yeni özel bir dosyayla donatılmıştır. Bu dosya modüllerin ve kimliklendiricilerin betimlendiği bir yapı taşır. Bu dosya yardımıyla, bağlayıcı kitaplığın tümünü okumak zorunda kalmaksızın fonksiyon çözümlemesini gerçekleştirir. Böylece kitaplığın defalarca okunmasına gerek kalmamış olur. Bu, simge çizelgelerinin kitaplık belgeliğine (arşivine) eklenmesi süreci Linux'ta ranlib(1) güdümü tarafından gerçekleştirilir. Böylece tanımlanan kitaplıklar DURAĞAN KİTAPLIKLAR olarak bilinirler.

İlk çokgörevli sistemlerin devreye sokulmasıyla yeni bir gelişme, yazılım paylaşımı gündeme getirilmiştir. Aynı sistemde, aynı yazılımın iki kopyası birden devreye sokulduğunda iki sürecin aynı yazılımı paylaşması ilginç gözükmüştür. Çünkü, bunun gerçekleşmesi durumunda, bir programın kendi kendini değiştirmemesinden dolayı bellekte çok sayıda kopyanın tutulmasına gereksinim kalmayacağı düşünülmüştür. Bu düşünce çok kullanıcılı dev sistemlerde büyük tutarlarda bellek korunumuna olanak sağlamıştır.

Bu yeniliğin bir adım ötesi olarak birisi (kim olduğunu bilmiyorum ama düşünce gerçekten büyüktü ;-) birçok programın kendileri farklı olmakla birlikte aynı kitaplığı kullandıklarını düşünmüştür. Bu yapıda bir programın kullandığı kitaplık kesimiyle bir diğerinin kullandığı kitaplık kesimi aynı olmak zorunda değildi. Üstelik anayazılım da aynı değildi (farklı programlar), dolayısıyla, onların metinleri de paylaşılmamaktaydı. Bu durumda, sözü edilen birey, aynı kitaplığı kullanan farklı programlar böyle bir kitaplık paylaşımına girebilirse, bellek kullanımı azaltılabilecekti. Bugün, artık, farklı programlar, özdeş program metnine sahip olmaksızın kitaplık yazılımlarını paylaşabilmektedirler.

Bununla beraber, artık, süreç daha da karmaşıklaşmıştır. Çalıştırılabilir program artık bütünüyle bir bağlantı olmayıp kitaplık kimliklendiricilerine başvurma, program yükleme sürecine ertelenmektedir. Bağlayıcı (Linux durumunda ld(1)) paylaşımlı bir kitaplık kullanımının söz konusu olduğunu algılayıp programa kendi düzgüsünü (kodunu) yerleştirmez. Sistemin kendisi, yani çekirdek, exec() programını devreye sokarken paylaşımlı kitaplık kullanan bir yazılımın devreye sokulduğunu algılar (Bu işi, paylaşımlı kitaplığı kendi metnine atayarak, kitaplık değerleri için özel bellek ataması yaparak, vb.. gerçekleştirir.) Çalıştırılabilir bir dosyanın yüklenmesi durumunda bu süreç gerçekleştirilir ve tüm işlem artık daha karmaşık hale gelmiştir.

Bağlayıcı normal bir kitaplıkla karşılaştığında, kuşkusuz, eskiden olduğu gibi davranır.

Paylaşımlı kitaplık nesnel yazılım içeren dosyalardan oluşan bir belgelik (arşiv) olmaktan çok nesnel yazılımı içeren tek bir dosya gibidir. Bağlayıcı, paylaşımlı kitaplığı bir programı bağlarken, kitaplık içinde hangi modülün kitaplığa eklenip eklenmediğiyle ilgilenmez, yalnızca, çözümlenmemiş kaynakların çözümlenmesini sağlar ve bunlardan hangilerinin kitaplığın içerilmesi durumunda dizelgeye (listeye) eklenmesi gerektiğini saptar. Tüm paylaşımlı kitaplıkları içeren bir belgelik (arşiv) ar(1) kitaplığı ilke olarak oluşturulabilse de bu yola sık sık başvurulmaz. Çünkü, paylaşımlı bir kitaplık, genellikle, çeşitli modüllerin bağlanmasının bir sonucudur ve bu yüzden kitaplık, daha sonra, çalıştırma süresince gerekecektir. Paylaşımlı kitaplık deyimi bu yapı için, belki de, en iyi ad değildir ve de bu yapıyı paylaşımlı nesne olarak adlandırmak daha yerinde olacaktır. (Ancak, bu diğer adı kullanma eğiliminde değiliz.)


4.- Kitaplık Türleri.

Biraz önce sözünü ettiğimiz gibi Linux altında iki tür kitaplık vardır; durağan ve paylaşımlı. Durağan kitaplıklar ar(1) yazılımıyla bir belgelik (arşiv) içine alınmış ve ranlib yazılımıyla da indislenmiş olan modüller topluluğudur. Bu modüller, çoğunlukla, adının sonunda uylaşım olarak .a bulunan bir dosya içinde tutulurlar. (Linux altında dosya uzantısı kavramı söz konusu olmadığından uzantı terimini kullanmayacağım.) Bağlayıcı addaki .a kesimini ve sanki durağan bir kitaplık söz konusuymuş gibi, çözümlenmemiş kaynakları çözümleyen modülleri seçip programa ekleyerek modül arayışına başlar.

Paylaşımlı kitaplıklar ise, tersine, belgelik (arşiv) olmayıp Üzel bir düzgü (kod) (kendilerini paylaşımlı kitaplık olarak tanımlayan) tarafından imlenen (işaretlenebilen) yeniden düzenlenebilir nesnelerdir. Bağlayıcı ld(1), sözü edildiği gibi, program kaynak yapısına modülleri eklemez. Ama kitaplık tarafından sağlanan kimliklendiricileri çözümlemiş gibi onları seçer, kitaplık tarafından tanıtılanları ekler ve bu durumda izlenimi vermeye çalışan diğer kaynak yazılımları eklemeksizin işini sürdürür. Bağlayıcı ld(1) paylaşımlı bir kitaplığı ad sonundaki .so kesiminden algılayabilir (.so.xxx.yyy kesimine bakmaz, bu noktaya daha sonra değineceğiz).


5.- Linux Altında Bağlanma İşlemleri.

Nesnel modüller içeren her program çalıştırılabilen (executable) oluşturmak üzere bağlantıya sokulur. Bu işlem, Linux bağlayıcısı olan, ld(1) tarafından gerçekleştirilir.

ld(1), davranışını yeniden düzenleme olanağı veren türlü seçenekleri destekler. Ancak, burada yalnızca kitaplık kullanımıyla genelde ilgili olan seçenekleri gündeme alacağız. ld(1) doğrudan kullanıcı tarafından etkinleştirilmek yerine derleyicinin kendisi, gcc(1) tarafından, derleme sürecinin son aşamasında devreye sokulur. Onun kullanım yolu hakkında yüzeysel bir bilgi kitaplıkların Linux altında kullanımlarının anlaşılmasında bize yardımcı olacaktır.

ld(1), işlevini yerine getirebilmek için, programa bağlanacak olan nesnelerin dizelgesine (listesine) gereksinim duyar. Bu nesneler, daha önceden sözettiğimiz uylaşıma, yani paylaşımlı kitaplıkların ad sonlarında .so (.so.xxx.yyy değil) durağan kitaplıkların ad sonlarında .a (ve kuşkusuz, basit nesne dosyaların ad sonlarında .o) kesimlerinin bulunması uylaşımına, uymak koşuluyla, herhangi bir sırada(*) verilebilir ve çağrılabilirler.

(*) Bu bütünüyle doğru değildir. ld(1), yalnızca, kaynakları kitaplık içerimi anında çözümleyen modülleri kapsama alır. O anda, daha sonra kapsama alınacak bir modül tarafından gündeme getirilecek kaynaklar bulunabilir. Bu kitaplığın kapsama alınma anında bu kaynaklar henüz ortalıkta görünmediklerinden içerilmede kargaşaya neden olabilirler. Dolayısıyla kitaplıkların kapsama alınma sırası önem kazanabilir.

Öte yandan, ld(1)'nin -l ve -L seçenekleri ölçünlü (standart) kitaplıkların içerilmesine olanak sağlar.

Amaaa ... Acaba ölçünlü (standart) kitaplıktan ne anlamaktayız, fark nedir? Hiçbir şey! Tek önemli nokta, ld(1)'in ölçünlü (standart) kitaplıkları önceden belirlenmiş yerlerde araması, parametre dizelgelerinde (listelerinde) nesne olarak gözükenleri ise dosya adlarını kullanarak bulmaya çabalamasıdır.

Kitaplıklar benimsenmiş olarak /lib ve /usr/lib dizinlerinde (ld(1)'nin yapı ve sürümüne bağlı olarak bazı ek konumların da kullanıldığını duymakla beraber) aranır. -L olağan kitaplık aramasında kullanılanlara dizin ekleme olanağı sağlar. Kullanım, eklenecek her yeni dizin için -L dizin yazarak gerçekleştirilir. Ölçünlü (standart) kitaplıklar, Ad yüklenecek kitaplığı belirtmek üzere, -l Ad seçeneğiyle belirtilirler. ld(1) aramayı ilgili dizinlerde sırayla yapar. Her bir dizinde, önce libAd.so dosyaadı aranır. Bulunamazsa, libAd.a ve onun durağan karşılığı denenir.

ld(1)'in libAd.so dosyasını bulması durumunda, bağlantı paylaşımlı kitaplık gibi bağlamayla gerçekleştirilir. libAd.a adlı bir dosya bulunursa, çözümlenmemiş kaynakların herhangi birinin çözümlenmesi durumunda bu dosyadan elde edilecek modüller bağlanır.


6.- Devinimli Bağlama ve Paylaşımlı Kitaplıkların Yüklenmesi

Devinimli (dinamik) bağlama çalıştırılabilen kaynak yazılımın yüklenmesi anında /lib/ld-linux.so adlı (gerçekte, kendisinin de paylaşımlı bir kitaplık olduğu) özel bir modül tarafından gerçekleştirilir.

Daha doğrusu, devinimli kitaplıkların bağlanması için iki modül elde bulunmaktadır: eski a.out biçimini kullanan kitaplıklar için /lib/ld.so ve yeni ELF biçimini kullanan kitaplıklar için /lib/ld-linux.so.

Bu modüller özel olup her devinimli program bağlamasında yüklenmelidirler. /lib dizininden başka yere aktarmamak ve adlarını değiştirmemek amacıyla bunların adları ölçünlüdür (standarttır). Eğer /etc/ld-linux.so adlı dosyanın adı değiştirilecek olursa, koşma anında çözümlenmemiş olan kaynakların çözümlenmesi bu yazılım tarafından gerçekleştirildiğinden, paylaşımlı kitaplık kullanan programlar kullanım dışı kalırlar.

/etc/ld.so.cache adlı dosya tarafından desteklenen son modül her bir kitaplık için böyle bir kitaplığı içermeye en uygun çalıştırılabilen dosyayı gösterir. Bu konuya daha sonra yine döneceğiz.


7.- soname. Paylaşımlı Kitaplıkların Sürümleri. Uyumluluk.

Artık paylaşımlı kitaplıklarla ilişkili en yanıltabilici konuya girebiliriz: Sürümler

Sık sık 'library libX11.so.3 not found' biçiminde ilgili kitaplığın bulunamadığını vurgulayan ve bizi libX11.so.6 varolmasına rağmen birşey yapamaz durumda bırakan bir iletiyle (mesajla) karşılaşırız. Nasıl olur da, ld.so(8), libpepe.so.45.0.1 ve libpepe.so.45.22.3 kitaplıklarının yerdeğiştirebileceğini algılarken libpepe.so.46.22.3?'nin bunlar yerine kullanımına izin vermez.

Linux altında ve ELF biçimini devreye sokan tüm işletim sistemlerinde kitaplıklar, birbirlerinden ayırdedilmek amacıyla bir katarla (simge dizisiyle) kimliklendirilirler: soname.

soname kitaplığın kendisinde içerilir ve ilgili katar (simge dizisi) kitaplığı oluşturan nesneler bağlanırken belirlenir. Bu katara bir değer vermek için, paylaşımlı kitaplık yaratıldığında, ld(1)'e bir seçenek (-soname ) vermek gerekir.

Bu katar çalıştırılabilen dosyayı kimliklendirir ve yüklenmesi gereken paylaşımlı kitaplığı kimliklendirmek amacıyla devinimli yükleyici tarafından kullanılır. Süreç aşağıdakine benzer biçimdedir:
Ld-linux.so programın bir kitaplığa gereksinimi olduğunu saptar ve kitaplığın soname değerini belirler. Ardından /etc/ld.so.cache devreye girer ve bu değeri içeren dosyanın adını bulur. Daha sonraki aşamada, istenen soname ile kitaplıkta bulunan ad karşılaştırılır ve eğer aynı oldukları saptanırsa iş bitmiş demektir! Özdeşlik sözkonusu değilse arama süreci uygun değer bulunana dek sürdürülür ya da yakınma iletisiyle (mesajıyla) işlem durdurulur.

ld-linux.so'un istemde bulunulan soname ile dosyanın çakıştığını denetlemesinden dolayı, soname bir kitaplığın yükleme için uygun düşüp düşmediğinin sınanmasına olanak sağlar. Uyumsuzluk durumunda ünlü 'libXXX.so.Y' not found biçiminde aranan kitaplığın bulunmadığı doğrultusunda ileti (mesaj) yayınlanır. Aranan şey soname olup yapılan yakınma soname'e gönderide bulunur.

Bu durum, bir kitaplığın adı değiştirildiğinde karşılaşılan kavram kargaşasına neden olur ve sorun da ortadan kalkmaz. Fakat soname'e erişip değiştirmek hiç de iyi bir düşünce değildir. Çünkü, Linux topluluğunda soname'e atama yapmak için bir uylaşım bulunmaktadır:

Uylaşım gereği, bir kitaplığın soname'i (paylaşımlı nesnel adı) uygun bir kitaplığı ve onun ARAYÜZÜNÜ kimliklendirmelidir. Eğer bir kitaplıkta onun yalnızca iç işlevselliğini etkileyen tüm arayüzün etkisiz kaldığı (fonksiyonların sayısı, değişkenler, fonksiyon parametreleri) değişiklikler yapılacak olursa iki kitaplığın (değişiklik öncesi ve sonrası) yerdeğiştirebilir olduğu söylenir. Böylece, genellikle, değişikliklerin azınlıkta olduğunu söyleyebiliriz. (İki kitaplık da uyuşumlu olup birinin yerine diğeri kullanılabilir.) Bu durumda, soname'de gözükmeyen azınlık değeri sük sük değiştirilebilir ve büyük sorunlar yaşanmaksızın kitaplıklararası değişim sağlanabilir.

Bununla beraber, fonksiyon eklemelerinde, fonksiyon kaldırımında, ve genellikle kitaplığın ARAYÜZ DEĞİŞTİRİMİNDE kitaplığın bir öncekisiyle yerdeğiştirebilir biçimde tutulabilmesi mümkün değildir. (Sözgelimi, libX11.so.3 yerine libX11.so.6'in yerleştirimi X11R5'ten X11R6'a güncellemenin bir parçası olup yeni fonksiyon tanımlarını gündeme getirdiğinden arayüzü değiştirir). X11R6-v3.1.2'dan X11R6-v3.1.3'ye geçişin arayüzde değişiklikler içermemesi ve (her ne kadar yenisine, eskisini koruma altında tutabilmek amacıyla, ayrı bir ad verilse de) kitaplığın aynı soname'e sahip olması olasıdır. Bu nedenle, kitaplık adında sürüm numarası da verilirken soname'de yalnızca egemen sayı yeralır.


8.- ldconfig(8)

Önceden sözünü ettiğimiz gibi, /etc/ld.so.cache, tt>ld-linux.so'in kitaplıkta bulunan dosyanın soname'ini dönüştürmesine izin verir. Bu daha çok etkinlik için ikitabanlı (binary) birdosya biçiminde olup ldconfig(8) güdümüyle yaratılır.

ldconfig(8), /etc/ld.so.conf tarafından belirtilen dizinlerde bulunan her bir devinimli kitaplık için kitaplığın soname'i tarafından çağrılan bir simgesel bağlantı üretir. Bu eylem ld.so dosya adını elde ederken, gerçekte yapılan dizin dizelgesinde (listesinde) aranan soname'e sahip dosyanın seçilmesi olacak biçimde gerçekleştirilir. Böylece, her kitaplık ekleme sürecinde ldconfig(8)'nin çalıştırılmasına gereksinim kalmaz. ldconfig, yalnızca dizelgeye (listeye) bir dizin eklenirken koşulur.

 

9.- Devinimli Kitaplık Yapmak İstiyorum.

Devinimli (dinamik) bir kitaplık oluşturmadan önce onun gerçekten yararlı olup olmadığını düşünmek gerekir. Devinimli kitaplıklar sistemde aşağıdaki nedenlerle aşırı yüklemelere neden olurlar:

  • Bir programın yüklenmesi çeşitli aşamalarda gerçekleştirilir. Bunlardan biri anaprogramın yüklenmesi olup diğerleri de programın kullandığı her bir devinimli kitaplığın devreye sokulmasıdır. (Bu son aşamanın uygun devinimli kitaplıklar için, uygun olmama konumundan yarar konumuna geçtiğini göreceğiz).

  • Devinimnli kitaplıklar yeniden bellek düzenlemeli güdümler içermelidir. Bunun nedeni süreç için sanal bulunakların (adreslerin) bulunduğu yerlerde yükleme bulunağını (adresinin) yükleme anına kadar bilinmemesidir. Derleyici, yükleme anında, kitaplığın yüklenme konumunu tutmak için bir yazmaç alıkoymaya zorlanır. Bu ise, sonuçta, güdümler topluluğunun eniyilenmesi için yazmaç sayısını bir azaltır. Bu ise, bu durumda ortaya çıkan aşırı yüklemenin birçok durumda karşılaşılan aşırı yüklemeden %5 daha fazla olması nedeniyle, küçük bir saglıksızlıktır.

Devinimli kitaplığın uygun düşebilmesi için zamanın büyük bir çoğunluğunda bazı programlar tarafından kullanılır olması gerekmektedir. (Bu, başlatıcı sürecin ölümünden sonra kitaplık metninin yeniden yüklenmesi sorunundan kaçınmaya olanak sağlar. Diğer süreçler kitaplığın modüllerini kullanırken kitaplık da bellekte kalır).

Paylaşımlı kitaplık, yalnızca gereken modülleriyle değil, bütünüyle belleğe yüklenir. Dolayısıyla yararlı olabilmesi için, bütünsel olarak yararlı olmalıdır. Devinimli kitaplığa en kötü örnek yalnızca bir fonksiyonu kullanılıp %90'ı çok seyrek kullanılan bir kitaplıktır.

Devinimli kitaplığa bir örnek olarak C standart kitaplığı verilebilir. (Bu kitaplık C'de yazılan tüm programlar tarafından kullanılır;). Ortalamada, fonksiyonların tümü orada burada yani her yerde kullanılırlar.

Durağan kitaplıklarda kullanımları seyrek olan fonksiyonların içerilmesi genellikle gereksizdir. Bu fonksiyonlar kitaplığın kendi modülünde yer aldıkça, bunlar kendilerine gereksinimi olmayan fonksiyonlara bağlantılı olmayacaklardır.


9.1.- Kaynakların Derlenmesi

Kaynakların derlenmesi, sürecin sanal bulunaklar (adresler) uzayındaki farklı konumlara yüklenebilen güdümler topluluğu üretebilmek amacıyla '-f PIC' (Konumdan Bağımsız Güdümler Topluluğu) seçeneği kullanımı dışında, normal bir kaynak durumundakine benzer biçimde gerçekleştirilir.

Bu aşama, durağan olarak bağlanan bir programda kitaplık nesnelerinin konumları bağlanma anında yani sabit bir anda çözümlenir olmasından dolayı, önemlidir. Eski a.out çalıştırılabilenlerinde, bu aşamanın her bir paylaşımlı kitaplığın sanal bulunaklar (adresler) uzayının sabit bir konumunda yerleştirilmesiyle sonuçlanarak gerçekleştirilmesi olanaksızdı. Bunun bir sonucu olarak, bir programın sanal belleğin örtüşmeli bölgelerinde yüklenmek için hazırlanmış iki kitaplık kullanmak istemesi durumunda çatışmalar oluşuyordu. Bir dizelgenin (listenin) bakımı için zorlanmanız durumunda, herhangi bir kimsenin bir kitaplığı devinimli yapmak istediği bir yerde, başka birilerinin kullanmaması amacına yönelik olarak bulunak (adres) bölgeleri belirtımı gerekecekti.

Önceden sözünü ettiğimiz gibi, resmi bir dizelgeye (listeye) kayıt için devinimli kitaplığa gerek yoktur. Bunun nedeni, güdümler topluluğunun bellekteki konumu yeniden düzenlenebilir olması gerekmesine rağmen, kitaplığın, yüklenme anında, o anda belirlenen konumlara gitmesidir.


9.2.- Kitaplıktaki Nesnelerin Bağlanması

Nesnelerin tümünün derlenmesinden sonra onların, devinimli olarak yüklenebilen bir nesne yaratmak için, özel bir seçenekle bağlanması gerekir.

gcc -shared -o libName.so.xxx.yyy.zzz
-Wl,-soname,libName.so.xxx

Okuyucunun takdir edeceği gibi, paylaşımlı bir kitaplık yaratımına yolaçacak bir dizi seçeneğin devreye sokulması dışında, bu işlem olağan bir bağlama işlemine benzer. Şimdi bunları bir bir açıklayalım:

  • -shared.
    Bu sözcük bağlayıcıya, sonuçta, paylaşımlı bir kitaplık üreteceğini, dolayısıyla çıktı dosyasında kitaplığa karşılık gelen bir tür çalıştırılabilenin bulunacağını, söyler.

  • -o libName.so.xxx.yyy.zzz.
    sonuç dosyasının adıdır. Ad uylaşımına uymak zorunlu olmamakla birlikte, bu kitaplığın gelecekteki gelişmelerin bir ölçünü olması istenmiyorsa, uylaşıma uymak daha uygundur.

  • -Wl,-soname,libName.so.xxx.
    -Wl seçeneği gcc(1)'ye (virgülle ayrılmış) izleyen seçeneğin baglayıcı için olduğunu söyler. Bu gcc(1) tarafından seçeneklerin ld(1)'ye geçirilmesi için kullanılan düzenektir. Yukarıda, bağlayıcıya aşağıdaki seçenekler geçirilmektedir.

       -soname libName.so.xxx
       
    Bu seçenek kitaplığın soname'ni, kitaplığın yalnızca soname'i saptanmış kitaplık gerektiren programlar tarafından devreye sokulmasına olanak verebilecek biçimde saptar.

9.3.- Kitaplık Kurulumu

Artık ilgili çalıştırılabilenin elde olduğu düşünülebilir. Böylece, bunun, kullanıma olanak verebilecek uygun bir yere yerleştirilmesi gerekir.

Yeni kitaplığımıza gereksinim duyan bir programı derlemek için aşağıdaki güdüm satırı kullanılabilir:

gcc -o program libName.so.xxx.yyy.zzz
Kitaplığın uygun bir yere (/usr/lib), kurulmuş olması durumunda aşağıdaki güdüm satırı yeterlidir:

gcc -o program -lName
(kitaplığın /usr/local/lib'de bulunması durumunda '-L/usr/local/lib' seçeneğinin eklenmesi yeterlidir)

Kitaplığın kurulumu için aşağıdaki işlemler yapılabilir:

  • Kitaplığı /lib ya da /usr/lib'a kopyalayın. Onu ayrı bir konuma (sözgelimi /usr/local/lib), kopyalamaya karar verirseniz bağlayıcının yani ld(1)'in programları bağlarken kitaplığı özdevimli olarak bulabileceğinden emin olamazsınız.

  • libName.so.xxx.yyy.zzz'den libName.so.xxx.'ye simgesel bağlantı yapmak için ldconfig(1)'yi çalıştırın. Bu aşama bize önceki aşamaların doğru biçimde gerçekleştirildiğini ve kitaplığın devinimli bir kitaplık olduğunu söyler. Programların bağlanma biçimi, kitaplıkların koşma anında yüklenmesi dışında, bu aşama tarafından etkilenmez.

  • Bağlayıcının kitaplığı -l seçeneği ile bulabilmesine izin vermek için libName.so.xxx.yyy.zzz (ya da libName.so.xxx, soname)'den libName.so'a, simgesel bir bağlantı kurunuz. Bu düzeneğin işleyebilmesi için kitaplığın adının libName.so

    örüntüsüyle çakışması gerekir.

10.- Durağan bir kitaplık yapımı

Öte yandan durağan bir kitaplık yapımı istendiğinde (ya da durağan bağlantı kopyaları sunabilmek için iki sürüm gerekecektir) aşağıdaki biçimde ilerlenebilir:

Not: Bağlayıcı, kitaplık arayışı sırasında, önce libName.so, daha sonra da libName.a. dosyalarını arar. Eğer her iki kitaplık da (durağan ve devinimli sürümler) aynı sözcükle adlandırılırsa bunlardan hangisinin bağlantıya gireceğinin saptanabilmesi genellikle mümkün değildir (devinimli olanı önce bulunacak olursa hemen bağlantıya girer).

Bu nedenle, aynı kitaplığın her iki sürümüne de gereksinim duyulursa, durağan olanının libName_s.a, devinimli olanının da libName.so olarak adlandırılması salık verilir. Bu doğrultuda, bağlantı yapılırken durağan sürümü bağlamak için

gcc -o program -lName_s
devinimli olanı bağlamak için de
gcc -o program -lName
güdümleri kullanılacaktır.

10.1.- Kaynakların Derlenmesi.
Kaynakları derlemek için herhangi bir özel ölçüm almayacağız. Benzer yoldan bağlama aşamalarında nesnelerin konumu kararlaştırıldıkça, (onu kullanarak devam etmek mümkünse de) -f PIC ile derlemek gerekli değildir.  
10.2.- Kitaplıktaki Nesnelerin Bağlanması
Durağan kitaplıklar durumunda bağlama aşaması yoktur. Tüm nesneler kitaplık dosyasında ar(1) güdümüyle belgeliklenmişlerdir. Daha sonra, simgeleri ivedilikle çözümlemek için ranlib(1) güdümünün kitaplık üzerinde çalıştırılması salık verilir. Gerekli olmamasına karşın, bu güdümün çalıştırılmaması çalıştırılabilendeki modüllerin bağlantılarının kopmasına yolaçabilir. Bunun nedeni, kitaplık oluşturumu süresince modül bağlayıcı tarafından işlenirken modüller arası dolaylı bağlantıların hepsi de birdenbire çözümlenmez: modüle bir başka modül tarafından daha sonra belgelikde (arşivde) gereksinim duyulması durumunda, tüm göndermeler çözümleninceye dek aynı kitaplık içinden geçirilmek zorunda kalınır).  
10.3.- Kitaplık Kurulumu

Yalnızca bir durağan kitaplık kullanılması durumunda durağan kitaplıkların libName.a biçiminde adlandırılacaktır. İki tür kitaplık kullanımı durumunda durağan olanlar için, durağan ve devinimli kitaplık kullanımını kolayca denetleyebilmek amacıyla, libName_s.a adını salık vereceğim.

Bağlama süreci -static seçeneğinin kullanımına izin verir. Bu seçenek /lib/ld-linux.so modülünün yüklenmesini denetler ve kitaplık inceleme sırasını etkilemez. Eğer birileri -static yazar ve ld(1) devinimli bir kitaplık bulursa onun durgun eşdeğerini aramak yerine onunla işgörmeyi sürdürür. Bu durum, kitaplıkta bulunan ve çalıştırılabilene ait olmayan yordamların devreye sokulması, özdevimli devinimli yükleme modülünün bağlanmaması ve dolayısıyla bu sürecin gerçekleştirilememesi nedeniyle, koşma anında yanılgılara yol açar.


11.- Devinimli Bağlantıya Karşı Durağan Bağlantı

Bir program içinde yalnızca durağan olarak içerilmesine izin verilen bir dağıtım için yetkilendirildiğimiz bir kitaplığı kullanan bir programın dağıtımını istediğimizi varsayalım. (Bu durum için Motif ile geliştirilen uygulamalar örnek verilebilir).

Bu tür bir yazılım üretmek için iki yol bulunmaktadır. Birincisi durgun olarak bağlanmış bir çalıştırılabilen üretmektir. Bu durumda yalnızca .a kitaplıkları kullanılacak ve devinimli yükleyicinin kullanımından kaçınılacaktır. Bu tür programlar bir kez yüklenirler ve sistemde, /lib/ld-linux.so'yi de kapsamak üzere, herhangi bir kitaplık yüklenimini gerektirmezler. Bununla beraber ikitabanlı (binary) dosyada gerekli olan yazılımların tümünü taşıma sakıncasına sahip olup bu yüzden dev dosyalardır. İkinci seçenek devinimli bağlanmış program üretimidir. Bunun anlamı, uygulamamızın koşacağı çevrenin ilgili tüm devinimli kitaplıkları sağlaması gerekliliğidir. Bazı durumlarda, sağlanabilen kitaplıkların tümüne sahip olunamasıyla birlikte çalıştırılabilen çok küçüktür (sözgelimi Motif'i olmayan bireyler de vardır).

İçindeki kitaplıkların bir kesiminin durağan diğer kesiminin devinimli olduğu üçüncü bir seçenekten, karışık bir dağıtımdan da süzedilebilir. Bu durumda, çatışmalı kitaplıkları durağan diğerlerini devinimli seçmek mantıksal olarak doğru bir yaklaşımdır. Bu seçenek yazılım dağıtımı için çok uygun bir biçimdir.

Sözgelimi, bir programın üç ayrı sürümü aşağıdaki biçimde derlenebilir:

gcc -static -o program.static 
program.o -lm_s -lXm_s -lXt_s -lX11_s\
-lXmu_s -lXpm_s

gcc -o program.dynamic program.o
-lm -lXm -lXt -lX11 -lXmu -lXpm

gcc -o program.mixed program.o 
-lm -lXm_s -lXt -lX11 -lXmu -lXpm

Son durumda, yalnızca Motif kitaplığı Motif (-lXm_s) durağan olarak bağlanırken diğerleri devinimli olarak bağlanırlar. Programın koştuğu çevre, libm.so.xx libXt.so.xx libX11.so.xx libXmu.so.xx y libXpm.so.xx kitaplıklarının uygun sürümlerini sağlamalıdır.


Daha çok bilgi için:
  • ELF-NASILYAPILIR'a bakınız.


© 1998 Luis Colorado
Bu sanal yörenin bakımı Miguel A Sepulveda tarafından yapılmaktadır..