| 
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üklenmesiDevinimli (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 DerlenmesiKaynakları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 KurulumuArtı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_sdevinimli olanı bağlamak için de gcc -o program -lNamegü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 KurulumuYalnı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. |