Menü
Bedava
kayıt
ev  /  internet/ Macromedia Flash MX ile ilgili resimli eğitim. Flash soname paylaşılan kitaplığı

Macromedia Flash MX ile ilgili resimli eğitim. Flash soname paylaşılan kitaplığı

Daha önce, sayfalama ve segment bellek yöneticilerinin temel ve banka yöneticilerine göre avantajlarından biri olarak paylaşılan kütüphanelerden bahsetmiştik. Temel adreslemede, her işlemin görüntüsü hem fiziksel hem de mantıksal adres alanında bitişik alanları işgal etmelidir. Bu koşullar altında, paylaşılan kütüphaneyi uygulamak imkansızdır. Ancak sayfa adreslemeyi kullanırken bile işler o kadar basit değildir.

Paylaşılan kitaplıkların ve/veya DLL'lerin kullanımı (bu durumda, aralarındaki fark temel değildir) yükleme sırasında bir tür derleme gerektirir: yürütülebilir modül çözülmemiş adres referanslarına ve ihtiyaç duyduğu kitaplıkların adlarına sahiptir. Yüklendiğinde bu kitaplıklar yüklenir ve bağlantılar çözümlenir. Buradaki sorun, bir kitaplığı yüklerken, kodunda ve verilerinde mutlak adres referanslarını yeniden yapılandırarak taşınması gerekmesidir (bkz. Bölüm 3). Farklı işlemlerde kitaplık farklı adreslere yapılandırılırsa, artık paylaşılmayacaktır (Şekil 5.14!)! Paylaşılan kitaplıkların diğer kitaplıklara çözülmemiş bağlantıları varsa, sorun yalnızca yeniden yerleştirilebilir bağlantılara dış bağlantılar eklendiğinde daha da kötüleşir.

Pirinç. 5.14... Çakışan DLL eşleme adresleri

Biçimin mutlak yüklenebilir modüllerini kullanan eski Unix sistemlerinde a.out Paylaşılan kitaplıklar da sabit adreslere ayarlanmış mutlak modül biçiminde gönderildi. Her kütüphane ITS adresine ayarlanmıştır. Yeni kütüphanelerin tedarikçisi, sistem geliştiricileri ile bu adres üzerinde anlaşmak zorunda kaldı. Bu çok pratik değildi, bu nedenle çok az paylaşılan kitaplık vardı (özellikle işletim sistemiyle gelenler dışında).

Bu soruna daha kabul edilebilir bir çözüm OS / 2 2.x ve Win32'de uygulanmaktadır (bu mimarilerin her ikisi de tek adres alanına sahip sistemlerin geliştirilmesidir). Buradaki fikir, DLL'leri yüklemek için bir adres alanı tahsis etmek ve bu alanı tüm süreçlerin adres alanlarına eşlemektir. Böylece sisteme yüklenen tüm DLL'ler herkes tarafından görülebilir (Şekil 5.15).

Büyük programlar genellikle hazır kitaplıklar gerektirir. Kitaplık, önceden derlenmiş işlevlerin bir koleksiyonudur (örneğin, bir matematik kitaplığı). Exe-shnik oluşturulduğunda bağlantı yapılırken kitaplık istenir. Bu -l seçeneğiyle yapılır: cc -o badmath badmath.o -lm Standart olmayan bir kitaplığın yolunu belirtmeniz gerekirse: cc -o badmath badmath.o -lm -L / usr / önemsiz / lib -lcrud Kitaplık adı .a ile bitiyorsa, bu statik bir kitaplıktır. Statik bir kitaplık bağlandığında, bağlayıcı basitçe ondan tüm parçaları oluşturulan exe dosyasına kopyalar ve sonuç olarak onsuz bağımsız olarak çalışabilir. Exe-shnik paylaşılan bir kitaplık kullanıyorsa, kod yalnızca gerektiği kadar yüklenir. Kütüphaneler genellikle / lib ve / usr / lib dizinlerinde bulunur. / lib dizininde statik kitaplıklar olmamalıdır. Paylaşılan kitaplığın adı .so önekini içerir. Programın hangi kitaplıkları kullandığını belirlemek için şu komutu çalıştırmanız gerekir: ldd prog ld.so yükleyici, paylaşılan kitaplıkları yükler. Kütüphaneye giden yol exe-shnik'in içinde olabilir. Eğer orada değilse, yükleyici, dizinleri listeleyen /etc/ld.so.cache dosyasına bakar. Bir /etc/ld.so.conf dosyası da vardır. /etc/ld.so.cache dosyasının yolunu manuel olarak eklediyseniz, şu komutu çalıştırmanız gerekir: ldconfig -v Ayrıca LD_LIBRARY_PATH sistem değişkeni de vardır. /etc/ld.so.conf dosyasına yollar eklemek iyi bir fikir değil.Büyük kütüphaneler sistem önbelleğine girer ve başınız belaya girebilir. En iyi yol, exe-shnik'te kütüphaneye giden yolu dikmektir: cc -o myprog myprog.o -Wl, -rpath = / opt / belirsiz / lib -L / opt / belirsiz / lib -lweird Paylaşılan kitaplıkların büyümesiyle, örtüşme vb. nedeniyle bunlarla ilgili sorunlar mümkündür. LD_LIBRARY_PATH kullanmak da sorunlu. Bunun yerine bir komut dosyası kullanılabilir: LD_LIBRARY_PATH = / opt / crummy / lib dışa aktarma LD_LIBRARY_PATH exec / opt / crummy / bin / my_prog [e-posta korumalı] Unix'teki ana derleme aracı make'dir. En ayrıntılı açıklama şurada verilmiştir: UNIX Programlama Ortamı veya içinde Projeleri make ile yönetme... Make her zaman bir dosya veya etiket olabilen bir hedefe sahiptir - hedef. Hedef birincil ve ikincil olabilir. Bir hedef oluşturmak için kurallar arayın. Örneğin: OBJS = aux.o main.o # nesne dosyaları tümü: myprog myprog: $ (OBJS) $ (CC) -o myprog $ (OBJS)İlk hedef - tümü - varsayılan olarak ana hedeftir. Bunun kuralı, başka bir kural, başka bir hedef veya bir dosya olabilen myprog'dur. OBJS, bir hedef oluşturmak için bir makrodur. Bu makefile aşağıdaki çıktıyı üretecektir: cc -c -o aux.o aux.c cc -c -o main.o main.c cc -o myprog aux.o main.o make, komut seçenekleriyle birlikte çalıştırılabilir, örneğin: make aux.o Make options: -n -f Sık kullanılan makrolar: CFLAGS - derleyici seçenekleri LDFLAGS - linker seçenekleri make'nin birkaç standart hedefi vardır: clean distclean kurulum testi bağımlı Makefile genellikle başlar ya ile ve şunları içerir, örneğin: X_INCLUDES = -I / usr / X11R6 / dahil X_LIB = -L / usr / X11R6 / lib -lX11 -Xt NG_INCLUDES = -I / usr / yerel / dahil PNG_LIB = -L / usr / yerel / lib -lpng Sonraki, derleyici ve bağlayıcı için seçenekler CFLAGS = $ (CFLAGS) $ (X_INCLUDES) $ (PNG_INCLUDES) LDFLAGS = $ (LDFLAGS) $ (X_LIB) $ (PNG_LIB) Ardından kaynak kodu listelenebilir: UTIL_OBJS = util.o BORING_OBJS = $ (UTIL_OBJS) sıkıcı.o TRITE_OBJS = $ (UTIL_OBJS) basmakalıp.o PROGS = sıkıcı basmakalıp Ve ancak şimdi hedefler ve kurallar var: tümü: $ (PROGS) sıkıcı: $ (BORING_OBJS) $ (CC) -o [e-posta korumalı]$ (BORING_OBJS) $ (LDFLAGS) trite: $ (TRITE_OBJS) $ (CC) -o [e-posta korumalı]$ (TRITE_OBJS) $ (LDFLAGS) Paylaşılan kitaplıklar, Unix sisteminin temel bir bileşenidir. Örneğin Suse 9.1'deki standart C-kütüphanesi 1.3 MB boyutundadır. Bu kitaplığın /usr/bin içinde kullanan tüm programlar için bir kopyası birden fazla gigabayt alacaktır. Bu tür kitaplıklar yalnızca disk alanı değil, aynı zamanda bellek gerektirir. Çekirdek, paylaşılan kitaplığın bir kopyasını bellekte tutmak için tasarlanmıştır. Statik olarak bağlanırken, kütüphane kodunun yürütülebilir dosya koduna statik olarak eklendiği ve onu çalıştırdığınızda, kütüphaneye ihtiyacımız olmadığı - kodu, derleme sırasında yürütülebilir dosyanın gövdesine zaten bağlı olduğu unutulmamalıdır. Dinamik bağlantıyla, paylaşılan kitaplık çalışma zamanında bağlanır.
Dinamik bağlama, kitaplık bağlamanın baskın türüdür. Yalnızca standart kitaplık, binin üzerinde sistem çağrısından oluşur. Sözde gerçekten çalışan programlar için. Prosedür Bağlantı Tablosu (PLT), paylaşılan kitaplıklardan çağrılan işlevlere yapılan çağrılardan oluşan bir tablodur. Bununla ortaya çıkabilecek ilk sorun bir uyumluluk sorunudur. Statik derleme ile bu sorun derleme zamanında çözülür. Dinamik linkleme ile böyle bir garanti yoktur çünkü paylaşımlı kütüphaneyi derlemeden sonra güncelleyebiliriz. Bu durumda, kontrol sürüm numarasıdır - dinamik bağlayıcı kitaplığı bağlamaya çalıştığında, sürüm numarasını kontrol eder ve sayı eşleşmezse bağlanmaz. Sürüm numarası 2 bölümden oluşur - ana (ana) sayı ve ikincil (küçük). Ana numara aynıysa, kural olarak, kitaplığı yüklerken sorun olmamalıdır. Eğer libexample.so kitaplığına sahipsek, bu durumda libexample.so.N sürümüne bir bağlantı olacaktır; burada N, ana ana sürüm numarasıdır ve buradan da libexample.so.NM'ye bir bağlantı olacaktır. M, ana ikincil sürüm numarasıdır. Bu durumda, program tam olarak ihtiyaç duyduğu N sürümünü arayacaktır.
Statik kitaplıklarda kod, .a uzantılı dosyalardadır.Dinamik kitaplıklarda dosyalar .so uzantısına sahiptir. Statik kitaplık formatı, ar yardımcı programı kullanılarak oluşturulur ve format, tar yardımcı programının oluşturduğuna benzer. En son Linux sürümlerindeki dinamik kitaplıklar için bu biçim genellikle ELF ikili biçimindedir. Bir başlık ve bölümlere ayrılmış bölümlerden oluşur. Bağlanırken, statik kitaplıklardan gelen kod doğrudan programın yürütülebilir dosyasına eklenir ve dinamik kitaplıklardan bağlantılar alınarak PLT'ye eklenir. Yüklendiğinde, program gerekli kitaplıkları yükleyen dinamik bir bağlayıcı yükler. Bir programı dinamik olarak bağlarken, derleme zamanında kitaplıkları aramak için yollar ekleyebilirsiniz. gcc için bu sözdizimi -Wl, -R / path gibi görünür. Eğer program zaten bağlantılıysa, LD_LIBRARY_PATH değişkenini kullanabilirsiniz.Ayrıca, kütüphane dizinlerini özel olarak yapılandıran programı başlatmadan önce, yapıldığı gibi özel bir sarmalayıcı komut dosyası çalıştırabilirsiniz. , örneğin, Mozilla'yı başlatırken. Dinamik bağlayıcı, bir dizin listesi içeren /etc/ld.so.conf yapılandırmasına erişir. Ama önce, bağlayıcı LD_LIBRARY_PATH'e erişir. ldd (dinamik bağımlılıkları listele)- paylaşılan kitaplıklarda hata ayıklamak için yardımcı program. Belirli bir modül için paylaşılan kitaplıkları listeler, örneğin: ldd / bin / sh linux-gate.so.1 => (0xffffe000) libreadline.so.4 => /lib/libreadline.so.4 (0x40036000) libhistory.so.4 => /lib/libhistory.so.4 (0x40062000) libncurses.so.5 => /lib/libncurses.so.5 (0x40069000) libdl.so.2 => /lib/libdl.so.2 (0x400af000) libc.so.6 => / lib / tls /libc.so.6 (0x400b2000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
  • Yeni Başlayanlar İçin: Sandeep Grover'dan Linux Journal makalesi "Bağlayıcılar ve Yükleyiciler"
  • "Bağlayıcılar ve Yükleyiciler" kitabı çevrimiçi el yazması.
  • 2002'de Ulrich Drepper tarafından "Paylaşılan kitaplıklar nasıl yazılır" (pdf) başlıklı önerilmiştir. Slaytlar (pdf) ve slaytlarda bahsedilen bir komut dosyası

Paylaşılan bir kitaplık oluşturma

"Merhaba dünya" dışında hiçbir şey yapmayan, neredeyse hiçbir şey yapmayan küçük bir kütüphane yazalım. İlk nesne:

/ * print1.c * / #include void print1 (void) (printf ("1 \ n");)

Benzer şekilde, ikinci nesne:

/ * print2.c * / #include void print2 (void) (printf ("2 \ n");)

Derleyelim:

gcc -Duvar -g -c -fpic print1.c gcc -Wall -g -c -fpic print2.c

Paylaşılan bir kitaplık oluşturun:

gcc -shared -Wlsoname = libprint.so.1 -g \ -o libprint.so.1.0.1 print1.o print2.o

Kütüphaneye bir bağlantı yapıyoruz:

ln -sf libprint.so.1.0.1 libprint.so

Başkalarının bu kütüphaneyi kullanabilmesi için bir başlık yazmanız gerekir:

/ * print.h * / #ifndef PRINT_H #define PRINT_H void print1 (void); void print2 (void); #endif

Bir test programı yazalım:

/ * print.c * / #include "print.h" int main () (print1 (); print2 (); 0 döndür;)

Derleyelim:

gcc -Duvar -g -L. -lprint -o print print.c

Programı çalıştırmak için bağlayıcının kitaplığın nerede olduğunu söylemesi gerekir:

Aşırı yükleme fonksiyonları

Bir kitaplığı yüklemeden önce, yükleyiciye onu aramaya ve yüklemeye nereden başlayacağını her zaman söyleyebiliriz.

Az önce yazdığımız kütüphaneye yeni bir fonksiyon ekleyelim. Bu işlev fopen olarak adlandırılır.

/ * fopen.c * / #include DOSYA * fopen (const char * fn, const char * modu) (printf ("fopen \ n olarak adlandırılır); dönüş NULL;)

Bu fonksiyonu derleyelim ve kütüphaneye koyalım:

gcc -Wall -g -c -fpic fopen.c gcc -shared -Wlsoname = libprint.so.1 -g \ -o libprint.so.1.0.2 print1.o print2.o fopen.o ln -sf libprint.so .1.0.2 libprint.so

Test için bir program yazalım:

/ * print-2.c * / #include int main () (FILE * f; f = fopen ("abc", "r"); if (f == NULL) (printf ("1");) başka (printf ("2"); fclose (f);) 0 döndür;)

Bu programı derleyelim:

gcc -Wall -g -o print print.c

Aşağıdaki önekle başlatmalıyız:

LD_PRELOAD =. / Libprint.so ./print

Bir şey yanlış yapılırsa, şu satır görüntülenir: fopen çağrılır

Bir program oluşturma süreci.

Rusçaya Çeviri: Vladimir Popov

Bugün, sürekli gelişen bir ortamda, yazılım geliştirme süreci, programcılar ve geliştiriciler tarafından geliştirilen beceri ve deneyimlerin evriminin bir ürünüdür.

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

    Bir metin düzenleyicide üst düzey dil kaynak kodu oluşturma. Çok büyük bir programı tek bir dosyaya sığdırmaya çalışırsak, yönetimi zorlaşır. Bu nedenle kaynak kodu, bir veya daha fazla kaynak kod dosyasından oluşturulan işlevsel modüllere bölünür. Bazı diller belirli bir sorunu çözmek için diğerlerinden daha uygun olduğundan, bu modüllerdeki kaynak kod mutlaka aynı dilde yazılmayabilir.

    Programın kaynak koduna sahip dosyalar oluşturulduktan sonra, makine tarafından yürütülebilecek kod bloklarına çevrilmeleri gerekir. Bu kod genellikle olarak adlandırılır nesne kodu... Bu kod, makine tarafından doğrudan çalıştırılabilen özel bir dilde yazılması dışında orijinal kodla aynı eylemleri gerçekleştirir. Kaynak kodun nesne koduna çevrilmesi süreci olarak bilinir. derleme... Derleme parçalar halinde yapılır ve programın (derleyiciye bağlı olarak) bir bölümünü ve genellikle tek seferde bir veya daha fazla dosyayı derler. Derlenmiş nesne kodu bir program, alt program, değişkenler vb. içerir. - Programların çevrilmiş ve bir sonraki adıma hazır olan bölümleri.

    Makine koduna sahip tüm program dosyaları oluşturulduktan sonra, özel bir yardımcı program tarafından gerçekleştirilen bir işlem kullanılarak bağlanmalı veya bağlanmalıdır. bağlayıcı... Bu aşamada, modülün kodunun başka bir modüle ait koda yaptığı tüm referanslar "çözülür" (bir alt program çağırma veya başka bir modülde sahip olunan veya tanımlanan değişkenlere yapılan referanslar gibi). Ortaya çıkan ürün, doğrudan yüklenebilen ve çalıştırılabilen bir programdır.

    Bir programın yürütülmesi, işletim sisteminin önemli bir parçası olan özel bir tür yazılım tarafından gerçekleştirilir, Linux söz konusu olduğunda bu, exec () sistem çağrısıdır. Bu işlev dosyayı bulur, işleme bellek ayırır, dosya içeriğinin (kod ve ilk değişken değerleri içeren) belirli kısımlarını yükler ve genellikle yürütülebilir dosyaya işaret eden programdaki "metin" noktasındaki kontrolü işlemciye aktarır. kendisi.

2.- Programı oluşturma sürecinin kısa tarihçesi.

Bir program oluşturma süreci sürekli gelişmektedir, programların en verimli şekilde yürütülmesini veya sistem kaynaklarının en iyi şekilde kullanılmasını sağlamak gerekir.

Başlangıçta, programlar doğrudan makine kodunda yazılırdı. Daha sonra, daha yüksek seviyeli bir dilde programlar yazmanın mümkün olduğu anlaşıldı, çünkü daha sonraki makine koduna çeviri, çevirinin sistematik doğası nedeniyle otomatikleştirilebilir. Bu, programların performansını artırdı.

Programların nasıl derleneceğini öğrendikten sonra (derlemenin evrimini basitleştirdim, aslında çok karmaşık bir süreç olduğu için çok zor bir adımdı), program oluşturma süreci programın kaynak koduyla bir dosya oluşturmaktan ibaret olmaya başladı. programlayın, derleyin ve en sonunda çalıştırın.

Derleme işleminin çok zahmetli olduğu ve makine zamanı da dahil olmak üzere çok fazla kaynak kapladığı ve bu programlarda yer alan birçok fonksiyonun çeşitli programlarda tekrar tekrar kullanıldığı kısa sürede fark edildi. Ayrıca, biri programın bir bölümünü değiştirdiğinde, eklenen kodu derlemek, değişmeyen tüm kodun yeni bir çevirisi de dahil olmak üzere tüm kaynak kodunun yeniden derlenmesi anlamına geliyordu.

Bu nedenle modüler derleme kullanılmaya başlandı. Anlamı, programı bir yandan ana programa ve diğer yandan tekrar tekrar kullanılan ve zaten özel bir yerde derlenmiş ve saklanmış olan işlevlere bölmekti (arayacağız). bu, kütüphanenin öncülü).

Sonra tekrar tekrar kodlamak için fazladan bir çaba harcamadan bu işlevleri destekleyen programlar geliştirmek mümkün oldu. O zaman bile, programları bağlarken tüm parçaları birleştirmek ve programcı tarafından bilinmesi gerektiğinden süreç karmaşıktı (bu, / kullanan bilinen bir işlevi kullanma olasılığını kontrol etmek için ek maliyetler getirdi). diğer bilinmeyen işlevler gerektirir).

3.- Kütüphane nedir?

Yukarıda açıklanan sorun, kitaplıkların oluşturulmasına yol açtı. Bu, özel parametrelere sahip özel bir dosya türünden (kesin olarak, bir arşiv, tar (1) veya cpio (1)) başka bir şey değildir, formatı bağlayıcının anladığı ve onu bir kütüphane arşivine yönlendirdiğimizde, LINKER YALNIZCA PROGRAM GEREKTİREN MODÜLLERİ SEÇER ve diğer her şeyi hariç tutar. Yeni bir avantaj ortaya çıktı. Artık büyük fonksiyon kütüphanelerini kullanan programlar geliştirmek mümkündü ve programcının bu kütüphanedeki fonksiyonların tüm bağımlılıklarını bilmesine gerek yoktu.

Şimdiye kadar tartıştığımız kütüphaneler geliştirme aşamasında daha ileri gitmedi. Sadece, genellikle arşivin başında bulunan, modül açıklamalarını ve bağlayıcının tüm kitaplığı okumadan çözmesi gereken tanımlayıcıları içeren bir dosya eklediler (ve böylece kitaplığı birden çok kez okuma ihtiyacını ortadan kaldırır). Linux'ta bu işlem (simge tablosunun kütüphane arşivine eklenmesi) ranlib (1) komutu ile gerçekleştirilir. Şimdiye kadar açıklanan kitaplıklar STATİK KÜTÜPHANELER olarak bilinir.

İlk çoklu görev sistemi ortaya çıktıktan sonra ilerleme oldu: bölme kodu... Aynı kodun iki kopyası aynı sistemde çalışıyorsa, bir program genellikle kendi kodunu değiştirmediğinden, her iki işlemin de aynı kodu paylaşabilmesi istenir. Bu fikir, çok kullanıcılı devasa sistemlerde çok fazla bellek boşaltan bellekte birden çok kopya ayırma ihtiyacını ortadan kaldırır.

Bu son yeniliği bir adım daha ileri götüren biri (kim olduğunu bilmiyorum ama fikir harikaydı ;-) çoğu programın aynı kitaplığı kullandığını, ancak farklı programlar olduğundan, kullanılan kitaplıkların parçaları olduğunu düşündü. mutlaka başka bir program tarafından kullanılan aynı parçalar değildi. Üstelik ana kod farklıydı (farklı programlar), bu yüzden metinleri paylaşılmadı. Kahramanımız, aynı kütüphaneyi kullanan farklı programlar bu kütüphaneyi kendi aralarında paylaşabilirse, o zaman biraz hafıza kazanabileceğimizi düşündü. Artık farklı metinlere sahip farklı programlar aynı kitaplık koduyla çalışıyor.

Ancak, süreç şimdi daha karmaşık hale geldi. Yürütülebilir program tam olarak bağlantılı değildir, ancak kitaplık tanımlayıcı referanslarının çözünürlüğü program yüklenene kadar ertelenir. Bağlayıcı (Linux durumunda ld (1)) paylaşılan kitaplık çağrılarını tanır ve kodlarını programa dahil etmez. Sistemin kendisi, çekirdek, exec () yürütülürken, paylaşılan kitaplıkları kullanan bir programın başlatılmasını tanır ve paylaşılan kitaplıkları yükleyen özel kodu yürütür (metinleri için paylaşılan bellek ayırma, kitaplık değerleri için özel bellek ayırma, vb.). Şimdi bu işlem yürütülebilir dosya yüklenirken gerçekleştiriliyor ve tüm prosedür çok daha karmaşık hale geldi.

Elbette linker normal bir kütüphane ile karşılaştığında eskisi gibi davranmaya devam eder.

Paylaşılan kitaplık, nesne kodunu içeren bir arşiv değil, nesne kodunun kendisini içeren bir dosyadır. Bir programı paylaşılan bir kütüphaneye bağlarken, linker kütüphaneyi, programa hangi modüllerin eklenmesi gerektiğini ve hangilerinin eklenmemesi gerektiğini incelemez. Yalnızca çözülmemiş bağlantıların çözümlenmesini sağlar ve kitaplık eklendiğinde listeye nelerin eklenmesi gerektiğini belirler. Tüm paylaşılan kitaplıkların bir arşivini ar (1) kitaplığı yapmak mümkündür, ancak paylaşılan kitaplıklar genellikle farklı modüllerin bağlanmasının bir sonucu olduğundan, bu genellikle yapılmaz, bu nedenle kitaplığa daha sonra, çalışma zamanında ihtiyaç duyulacaktır. Belki de paylaşılan kitaplık adı en uygunu değildir ve onu paylaşılan bir nesne olarak adlandırmak daha doğru olur (ancak anlaşılmayabileceğimiz için bu terimi kullanmıyoruz).

4.- Kütüphane türleri.

Söylediğimiz gibi, Linux'ta iki tür kitaplık vardır: statik ve paylaşımlı. Statik kitaplıklar, ar (1) yardımcı programı kullanılarak bir arşivde birleştirilen ve ranlib (1) yardımcı programıyla dizinlenen modüllerin bir koleksiyonudur. Bu modüller genellikle .a ile biten bir dosyada saklanır (Linux dosya uzantısı kavramını kullanmadığı için uzantı terimini kullanmıyorum). Bağlayıcı, .a dosyasının sonunu tanır ve statik bir kitaplıkmış gibi modülleri aramaya başlar ve çözülmemiş referansları çözen modülleri seçip programa ekler.

Statik kitaplıklardan farklı olarak, paylaşılan kitaplıklar arşivler değil, özel kodla (bunları paylaşılan kitaplıklar olarak atayan) belirlenmiş yeri değiştirilebilen nesnelerdir. ld (1) linker, daha önce bahsedildiği gibi, program koduna modül eklemez, ancak kütüphane tarafından sağlanan tanımlayıcıları izin verildiği şekilde seçer, kütüphanenin ihtiyaç duyduğu tanımlayıcıları ekler ve herhangi bir kod eklemeden çalışmaya devam eder. gerekli kodun zaten ana koda eklenmiş olması. ld (1) bağlayıcısı, paylaşılan kitaplıkları .so ile sona erdirerek tanır (.so.xxx.yyy değil, bunu daha sonra tartışacağız).

5.- Linux'ta bağlama işlemi.

Her program, yürütülebilir bir dosyaya bağlı nesne modüllerinden oluşur. Bu, Linux'ta kullanılan ld (1) bağlayıcısı tarafından yapılır.

ld (1) davranışını değiştiren çeşitli seçenekleri destekler, ancak biz burada kendimizi yalnızca genel olarak kitaplıkların kullanımıyla ilgili olanlarla sınırlayacağız. ld (1) doğrudan kullanıcı tarafından değil, son aşamasında gcc (1) derleyicisinin kendisi tarafından çağrılır. Onun hakkında az bilgi çalışma şekli Linux'ta kitaplıkları kullanmanın yolunu anlamamıza yardımcı olun.

ld (1)'in düzgün çalışması için programa bağlanacak nesnelerin bir listesine ihtiyacı vardır. Bu nesneler herhangi bir sırada (*) belirtilebilir, yukarıdaki kuralı takip ettiğimiz sürece, daha önce belirtildiği gibi, paylaşılan kitaplık .so (.so.xx.yy değil) ve statik kitaplık .a tarafından tanınır. (ve elbette basit nesne dosyaları, adları .o ile bitenlerdir).

(*) Bu tamamen doğru değildir. ld (1), yalnızca kitaplığın dahil edildiği sırada bağlantıları çözen modülleri içerir, bu nedenle, daha sonra dahil edilen bir modülde, bu kitaplığın dahil edildiği sırada görünmediğinden daha sonra bir bağlantı olabilir. , bir komutun gerekli kitaplıkları içermesine neden olabilir ...

Öte yandan ld (1), -l ve -L seçenekleri sayesinde standart kitaplıkların dahil edilmesini sağlar.

Ama ... Standart kitaplık ile ne demek istiyoruz, fark nedir? Numara. Yalnızca bu ld (1), belirli yerlerde standart kitaplıkları arar, parametre listesinde nesneler olarak tanımlananlar ise dosya adlarına göre aranır.

Varsayılan olarak, kitaplıklar / lib ve / usr / lib dizinlerinde aranır (ld (1)'in sürümüne / uygulamasına bağlı olarak ek dizinler olabileceğini duydum). -L, normal bir kütüphane aramasıyla arananlara dizinler eklememize izin verir. Eklemek istediğimiz her dizin için -L dizini belirtilerek kullanılır. Standart kitaplıklar -l Ad seçeneğiyle belirtilir (burada Ad, yüklenecek kitaplığı belirtir) ve ld (1) libName.so adlı bir dosya için uygun sırayla uygun dizinlerde arama yapar. Bulunamazsa, statik versiyonu olan libName.a bulunmaya çalışılacaktır.

ld (1) libName.so'yu bulursa, onu paylaşılan bir kitaplık olarak bağlar, libName.a'yı bulursa, çözülmemiş başvuruları çözerlerse ondan türetilen modülleri bağlar.

Dinamik bağlama, yürütülebilir dosya /lib/ld-linux.so adlı özel bir modül (aslında bu özel modül, paylaşılan kitaplığın kendisidir) tarafından yüklendiğinde gerçekleştirilir.

Aslında dinamik kitaplıkları bağlamak için iki modül vardır: /lib/ld.so (eski a.out biçimini kullanan kitaplıklar için) ve /lib/ld-linux.so (yeni ELF biçimini kullanan kitaplıklar için).

Bu modüllerin özelliği, bir program dinamik olarak her bağlandığında yüklenmeleri gerektiğidir. Adları standarttır (nedeni / lib dizininden taşınamazlar ve ayrıca adları değiştirilemez). /etc/ld-linux.so adını değiştirirsek, paylaşılan kitaplıkları kullanan herhangi bir programı kullanmayı otomatik olarak durdururuz, çünkü bu modül çalışma zamanında çözülmeyen tüm bağlantıların çözümlenmesinden sorumludur.

Son modüle, her kitaplık için o kitaplığı içeren en uygun yürütülebilir dosyayı belirten /etc/ld.so.cache dosyasının varlığı yardımcı olur. Bu konuya daha sonra geri döneceğiz.

7.- sonam. Yürütülebilir kitaplık sürümleri. uyumluluk

Bu bizi paylaşılan kitaplıkların en kafa karıştırıcı konusuna getiriyor: sürümleri.

Sık sık "library libX11.so.3 bulunamadı" mesajını görüyoruz, bu da kafamızı karıştırıyor: libX11.so.6 kütüphanesine sahip olduğumuz için hiçbir şey yapamıyoruz. ld.so (8)'nun libpepe.so.45.0.1 ve libpepe.so.45.22.3'ü tanıması ve libpepe.so.46.22.3'ü birbirinin yerine tanımaması nasıl mümkün olabilir?

Linux'ta (ve ELF biçimini kullanan tüm işletim sistemlerinde), kitaplıklar ayırt edici karakter dizileriyle tanımlanır: soname.

soname, kütüphanenin kendisinde yer alır ve bu sıra, kütüphaneyi oluşturan nesneler bağlanırken belirlenir. Paylaşılan bir kitaplık oluştururken, bu karakter dizisine bir değer vermek için ld (1) seçeneğini (-soname) geçmelisiniz.<имя_библиотеки>).

Bu karakter dizisi, yüklenecek paylaşılan kitaplığı ve yürütülebilir dosyayı tanımlamak için dinamik yükleyici tarafından kullanılır. Şuna benziyor:
Ld-linux.so, programın bir kitaplık gerektirdiğini algılar ve soname adını tanımlar. Daha sonra /etc/ld.so.cache içerisinde isim aranır ve bu kütüphaneyi içeren dosyanın ismi belirlenir. Ardından, istenen soname mevcut kütüphanenin adıyla karşılaştırılır ve eğer aynılarsa, buna ihtiyacımız var! Değilse, bulunana kadar arama devam edecek veya bulunamazsa bir hata mesajı görüntülenecektir.

Soneme, kitaplığın yükleme için uygun olup olmadığını belirlemek için kullanılabilir, çünkü ld-linux.so, gerekli soname ile gerekli dosyanın aynı olup olmadığını kontrol eder. Fark olması durumunda ünlü "libXXX.so.Y bulunamadı" ifadesini alabiliriz. Aranan sonamedir ve döndürülen hata soname tarafından belirlenir.

Kütüphanenin adını değiştirirsek, çok fazla kafa karışıklığı olabilir ve sorunun kendisi kalır. Ancak soname'yi değiştirmek de iyi bir fikir değil, çünkü Linux topluluğunda soname atamak için bir kural vardır:

Bir kitaplığın soname, varsayılan olarak, karşılık gelen kitaplığı ve o kitaplığın ARAYÜZÜ'nü tanımlamalıdır. Kitaplıkta yalnızca dahili işlevselliği etkileyen değişiklikler yaparsak, ancak arayüz değişmeden kalırsa (fonksiyon sayısı, değişkenler, fonksiyon parametreleri), o zaman iki kitaplık birbirinin yerine geçebilir ve genel olarak değişikliklerin küçük olduğunu söyleyeceğiz (her ikisi de) kütüphaneler uyumludur ve birini diğerinin üzerine değiştirebiliriz). Böyle bir durumda, (soneme'nin bir parçası olmayan) küçük sayı sık sık değişir ve kitaplık önemli bir sorun olmadan değiştirilebilir.

Ancak fonksiyonlar eklediğimizde, fonksiyonları kaldırdığımızda ve genel olarak kütüphanenin ARAYÜZÜNÜ DEĞİŞTİRDİĞİMİZ zaman bu kütüphanenin bir önceki ile değiştirilebilir olduğunu söylemek artık mümkün değildir (örneğin, libX11.so.3'ün libX11 ile değiştirilmesi). so.6, yeni işlevler getirdiğinde ve dolayısıyla arayüzü değiştirdiğinde X11R5'ten X11R6'ya geçişin bir parçasıdır). X11R6-v3.1.2'den X11R6-v3.1.3'e geçiş muhtemelen arayüzü değiştirmeyecektir ve kütüphane aynı soname sahip olacaktır - eski sürümü korumak için ona farklı bir ad vermemiz gerekmesine rağmen (bu nedenle sürüm numarası kitaplık adını sona erdirir, soname'de yalnızca büyük sayılar belirtilir).

8.- ldconfig (8)

Daha önce söylediğimiz gibi, /etc/ld.so.cache, ld-linux.so'nun kütüphanede bulunan dosyanın soname'sini dönüştürmesine izin verir. Bu, ldconfig (8) yardımcı programı tarafından oluşturulan bir ikili (verimlilik için) dosyadır.
ldconfig (8) /etc/ld.so.conf içinde belirtilen dizinlerde bulunan her DLL için soname kitaplık adıyla sembolik bir bağlantı oluşturur. Bu durumda, ld.so bir dosyanın adını almak istediğinde, dizin listesinden gerekli soname ile dosyayı seçer. Böylece her kitaplık eklediğinizde ldconfig (8) çalıştırmanıza gerek kalmaz. ldconfig'i sadece listeye bir dizin eklediğimizde çalıştırırız.

9.- Dinamik bir kütüphane yapmak istiyorum.

Dinamik bir kütüphane oluşturmaya başlamadan önce bunun gerçekten gerekli olup olmadığını düşünmeliyiz. Dinamik kitaplıklar, çeşitli nedenlerle sistem aşırı yüklenmesine neden olur:
    Programın yüklenmesi birkaç aşamada gerçekleştirilir; biri ana programı yüklemek için, geri kalanı bu programın kullandığı her bir dinamik bağlantı kitaplığı için (bu son nokta artık nadir olmaktan ve bir avantaj haline geldiğinden, bunu ilgili dinamik bağlantı kitaplığı için dikkate alacağız).

    DLL'ler yeniden yerleştirilebilir kod içermelidir, çünkü sanal adres alanındaki bir işleme ayrılan adres yüklenene kadar bilinmez. Bu durumda, derleyici, kitaplığın yükleme konumunu depolamak için bir kayıt ayırmaya zorlanır ve sonuç olarak, kodu optimize etmek için bir kayıt eksiğimiz olur. Bu, böyle bir sorun değildir, çünkü çoğu durumda ortaya çıkan aşırı yük %5'ten fazla aşırı yük değildir.

Dinamik bir kitaplık için en kabul edilebilir durum, bazı programlar tarafından sürekli olarak kullanılmasıdır (bu, onu yükleyen işlemin sona ermesinden sonra kitaplık metninin boşaltılmasını önlemeye yardımcı olur. Diğer işlemler kitaplık modüllerini kullanırken, bellekte kalır) .

Paylaşılan kitaplık tamamen belleğe yüklenir (yalnızca ihtiyaç duyduğu modüller değil), bu nedenle kullanışlı olması için bütünüyle kullanılması gerekir. Dinamik bağlantı kitaplığı kullanmanın en kötü örneği yalnızca bir işlev kullanmaktır ve kitaplığın %90'ı neredeyse hiç kullanılmaz.

C standart kitaplığı, dinamik bağlantı kitaplığına iyi bir örnektir (C ile yazılmış tüm programlar tarafından kullanılır). Tüm işlevler ortalama olarak kullanılır.

Statik bir kitaplığın seyrek kullanılan işlevleri içermesi gerekmez; kendi modüllerinde bulundukları sürece, bunlara ihtiyaç duymayan herhangi bir programla bağlantılı olmayacaklardır.

9.1.- Kaynak Kodlarının Derlenmesi
Kaynak kodu derlemek, "-f PIC" (koddan bağımsız konumdan bağımsız) kullanmamız dışında normal kaynak koduyla tamamen aynıdır.

Bu adım esastır çünkü statik bir kitaplıkta kitaplık nesnelerinin konumu bağlantı sırasında çözülür, bu nedenle sabit bir zaman alır. Bu adım, eski a.out ikili dosyalarında mümkün değildi, bu da her paylaşılan kitaplığın sanal adres alanında sabit bir konuma yerleştirilmesiyle sonuçlandı. Sonuç olarak, program iki kitaplık kullanmak isterse ve bunları sanal belleğin çakışan bölgelerine yüklerse, herhangi bir zamanda çakışmalar ortaya çıkabilir. Bu, kütüphaneyi dinamik hale getirmek isteyen herkesin, başka hiç kimsenin kullanmaması için bir dizi adres bildirmek zorunda olduğu bir listeyi sürdürmek zorunda kaldığınız anlamına geliyordu.

Daha önce de belirttiğimiz gibi, dinamik bir kitaplığın resmi listeye kaydedilmesi gerekli değildir, çünkü kitaplık yüklendiğinde, kodun taşınması gerekmesine rağmen, o anda tanımlanan konuma yerleştirilir.

9.2.- Nesneleri Kitaplığa Bağlama
Tüm nesneleri derledikten sonra, dinamik olarak yüklenebilir bir nesne oluşturan bir seçenek belirleyerek bunların bağlanması gerekir. gcc -shared -o libName.so.xxx.yyy.zzz -Wl, -soname, libName.so.xxx paylaşılan kitaplık. Her biriyle ayrı ayrı ilgilenelim:
    -paylaştı.
    Bu, bağlayıcıya, sonunda paylaşılan kitaplığı oluşturması gerektiğini ve bu nedenle kitaplığa karşılık gelen çıktı dosyasında yürütülebilir kod içermesi gerektiğini söyler.

    O kütüphane Adı.so.xxx.yyy.zzz.
    Bu, çıktı dosyasının adıdır. Adlandırma kuralına uymak kesinlikle gerekli değildir, ancak bu kitaplığın gelecekteki geliştirme için bir standart olmasını istiyorsak, onu takip etmek daha iyidir.

    wl, -soname, lib Name.so.xxx.
    -Wl seçeneği, gcc (1)'e bağlayıcı için olan seçenekleri (virgülle ayrılmış) izlemesini söyler. Bu mekanizma gcc (1) tarafından seçenekleri ld (1)'e geçirmek için kullanılır. Örnekte, aşağıdaki seçenekleri linker'a iletiyoruz:

-soname libName.so.xxx Bu seçenek, kitaplığın soname adını değiştirir, dolayısıyla bu kitaplık, belirtilen soname gerektiren programlar tarafından istendiğinde yüklenir.
9.3.- Kütüphanenin Kurulması
Eh, ilgili yürütülebilir dosyamız zaten var. Şimdi, kullanabilmek için uygun yere kurulması gerekiyor.

Yeni kütüphanemizi gerektiren bir programı derlemek için aşağıdaki komutu kullanmamız gerekiyor:

Gcc -o program lib Name.so.xxx.yyy.zzz veya kitaplık (/ usr / lib) dizinine kurulmuşsa yeterli olacaktır: gcc -o program -l Name (kütüphane / usr dizininde ise / local / lib, ardından "-L / usr / local / lib" seçeneğini eklemeniz yeterlidir). Kitaplığı kurmak için aşağıdakileri yapın:

    Kütüphaneyi /lib veya /usr/lib dizinine kopyalayın. Farklı bir konuma kopyalamayı seçerseniz (örneğin, / usr / local / lib), programlarınızı bağladığınızda ld (1) bağlayıcısının onu otomatik olarak bulacağından emin olamazsınız.

    libName.so.xxx.yyy.zzz ile libName.so.xxx arasında bir sembolik bağlantı oluşturmak için ldconfig (1)'i çalıştırın. Bu adımda, önceki tüm adımları doğru takip edip etmediğimizi ve kütüphanenin dinamik olarak tanınıp tanınmadığını bileceğiz. Bu adım, programların bağlanmasını değil, yalnızca çalışma zamanında kitaplığın yüklenmesini etkiler.

    Bağlayıcının -l seçeneğiyle kitaplığı bulması için libName.so.xxx.yyy.zzz'den (veya libName.so.xxx, soname) libName.so'ya sembolik bir bağlantı oluşturun. Bu mekanizmanın çalışması için kitaplık adının lib Name.so kalıbıyla eşleşmesi gerekir.

10.- Statik bir kitaplık oluşturma

Öte yandan, statik bir kitaplık oluşturmanız gerekiyorsa (veya statik olarak bağlantılı kopyalar oluşturabilmek için iki sürüme ihtiyacınız varsa), aşağıdakileri yapmanız gerekir:

Not: Kitaplıkları ararken, bağlayıcı önce libName.so adlı bir dosya arar, ardından yalnızca libName.a. Bu kitaplıkların her ikisine de (statik ve dinamik sürümler) aynı adla hitap edersek, genel olarak her durumda ikisinden hangisinin bağlanacağını belirlemek imkansız olacaktır (bağlayıcı onu ilk algıladığından dinamik olan her zaman önce bağlanır. ).

Bu nedenle, aynı kitaplığın iki versiyonuna sahip olmak gerekirse, statik olanı her zaman libName_s.a ve dinamik libName.so biçiminde adlandırmak önerilir. Ardından, bağlantı kurarken şunları belirtmeniz gerekir:

Gcc -o program -l Statik sürümle bağlantı için ad_s, dinamik sürüm için ise: gcc -o program -l

10.1.- Kaynak Kodun Derlenmesi
Kaynak kodunu derlemek için herhangi bir özel adım atmanız gerekmez. Aynı şekilde nesnelerin konumuna link aşamasında karar verilir, -f PIC seçeneği ile derlemeye gerek yoktur (kullanmaya devam etmek mümkün olsa da).
10.2.- Nesneleri Kitaplığa Bağlama
Statik kitaplıklar için bağlantı yapılmaz. Tüm nesneler ar (1) komutuyla bir kitaplık dosyasına arşivlenir. Ayrıca, sembolleri hızlı bir şekilde çözmek için kütüphanede ranlib (1) komutunun çalıştırılması tavsiye edilir. Gerekli olmamasına rağmen, bu komutun yürütülmemesi yürütülebilir dosyadaki modüllerin bağlantısını kaldırabilir, çünkü bağlayıcı kitaplık oluşturma sırasında modülü işlediğinde, modüller arasındaki tüm dolaylı bağımlılıklar hemen çözülmez: diyelim ki, bir arşivin sonundaki bir modülün içinde başka bir modüle ihtiyacı vardır. Arşivin başlangıcında, bu, tüm bağlantıları çözmek için aynı kitaplıktan birden fazla geçiş yapılması gerektiği anlamına gelir.
10.3.- Kütüphanenin Kurulması
Yalnızca statik kitaplıklara sahip olmak istiyorsanız, libName.a biçiminde statik kitaplıkları adlandırmanız önerilir. İki tür kitaplık olması durumunda, statik kitaplığın ne zaman yükleneceğini ve dinamik kitaplığın ne zaman yükleneceğini ayırt etmek için onları libName_s.a olarak adlandırmanızı öneririm.

Oluşturma işlemi, -static seçeneğini girmenize olanak tanır. Bu seçenek /lib/ld-linux.so modülünün yüklenmesini kontrol eder ve kitaplık arama sırasını etkilemez, bu nedenle birisi -static belirtirse ve ld (1) bir dinamik kitaplık bulursa, onunla çalışır (ve çalışmaz). statik kitaplığa bakmaya devam edin). Bu, yürütülebilir dosyanın parçası olmayan bir kitaplıktaki prosedür çağrıları nedeniyle çalışma zamanı hatalarına yol açacaktır - otomatik dinamik yükleme modülü bağlı değildir ve bu nedenle işlem yürütülemez.

11.- Statik ve dinamik yerleşimin karşılaştırılması

Diyelim ki, programa yalnızca statik olarak dahil edilen ve başka hiçbir biçimde dağıtabildiğimiz bir kitaplığı kullanan bir programın dağıtımını oluşturmak istiyoruz (bu duruma bir örnek, Motif kullanılarak oluşturulan uygulamalardır).

Böyle bir program oluşturmanın iki yolu vardır. Birincisi, statik olarak bağlı bir yürütülebilir dosya oluşturmaktır (dinamik yükleyici kullanmadan yalnızca .a kitaplıklarını kullanarak). Bu tür programlar bir kez yüklenir ve sistemden herhangi bir kitaplık gerektirmez (/lib/ld-linux.so bile). Ancak, ihtiyacınız olan her şeyin tek bir ikili dosyada tutulması gerektiği gibi bir dezavantajı vardır ve bu nedenle bunlar genellikle çok büyük dosyalardır. İkinci seçenek, dinamik olarak bağlantılı bir program oluşturmaktır, yani uygulamamızın çalışacağı ortamın ilgili tüm dinamik kitaplıklara sahip olması gerekir. Yürütülebilir dosya çok küçük olabilir, ancak bazen kesinlikle tüm kitaplıklara sahip olmak imkansızdır (örneğin, Motif'e sahip olmayan insanlar vardır).

Bazı kitaplıkların dinamik olarak ve diğerlerinin statik olarak bağlandığı karma bir üçüncü seçenek vardır. Bu durumda, çakışan kitaplığı statik biçiminde ve diğerlerini dinamik biçiminde seçmek mantıklı olacaktır. Bu varyant, yazılım dağıtımının çok yaygın bir şeklidir.

Örneğin, bir programın üç farklı versiyonunu aşağıdaki gibi derleyebilirsiniz:

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ı. karma program.o -lm -lXm_s -lXt -lX11 -lXmu -lXpm Üçüncü durumda, yalnızca Motif kitaplığı (-lXm_s) statik olarak bağlanır ve diğerleri dinamik olarak bağlanır. Programın çalışacağı ortam, libm.so.xx libXt.so.xx libX11.so.xx libXmu.so.xx ve libXpm.so.xx kitaplıklarının uygun sürümlerine sahip olmalıdır.

Paylaşılan kitaplık veya paylaşılan kitaplık programlar arasında paylaşılması amaçlanan bir dosyadır. Program tarafından kullanılan modüller, program için tek bir yürütülebilir dosya kopyalarken bağlayıcı tarafından kopyalanmak yerine, ayrı paylaşılan nesnelerden belleğe yüklenir.

Paylaşılan kitaplıklar statik olarak bağlanabilir; bu, kitaplık modüllerine yapılan başvuruların çözümlendiği ve yürütülebilir dosya oluşturulduğunda modüllere bellek ayrıldığı anlamına gelir. Ancak genellikle paylaşılan kitaplıkları bağlamak, yüklenene kadar ertelenir.

gibi bazı eski sistemler Burroughs MCP Multics ayrıca, genel olsun ya da olmasın, yürütülebilir dosyalar için yalnızca bir biçime sahiptir. Yürütülebilir dosyalarla aynı biçimde kitaplık dosyalarını paylaştılar. Bunun iki ana avantajı vardır: birincisi, her biri iki değil, yalnızca bir önyükleyici gerektirir (ayrı bir önyükleyiciye sahip olmak ek karmaşıklık getirir). İkinci olarak, eğer bir sembol tabloları varsa, yürütülebilir dosyaların paylaşılan kitaplıklar olarak kullanılmasına da izin verir. Birleştirilmiş yürütülebilir ve paylaşılan kitaplıklar için tipik biçimler, ELF ve Mach-O (her ikisi de Unix'te) ve (Windows) şeklindedir.

16 bit Windows gibi bazı eski ortamlarda veya MPE için HP 3000, paylaşılan bir kitaplığa sahip kodda, yalnızca yığın tabanlı (yerel) verilere izin verildi veya paylaşılan kitaplık koduna başka önemli kısıtlamalar getirildi.

Paylaşılan hafıza

Kitaplık kodu, işlemlerle birlikte bellekte ve ayrıca diskte paylaşılabilir. Sanal bellek kullanılıyorsa, işlemler RAM'in farklı işlem adres alanlarına eşlenen fiziksel bir sayfasında yürütülür. Bunun avantajları vardır. Örneğin, OpenStep sisteminde uygulamalar genellikle yalnızca birkaç yüz kilobayt boyutundadır ve hızlı yüklenir; kodlarının çoğu, işletim sistemi tarafından başka amaçlar için önceden yüklenmiş kitaplıklardaydı.

Programlar, Unix'te olduğu gibi bağımsız kod kullanarak RAM'i paylaşabilir ve bu da karmaşık ancak esnek bir mimariyle sonuçlanır. Bu, adres alanını önceden eşleştirme ve paylaşılan her kitaplık için sayfa ayırma gibi çeşitli teknikler aracılığıyla daha fazla paylaşım olasılığının olmasını sağlar. Üçüncü seçenek tek katmanlı depolama tarafından kullanılan IBM Sistemi / 38 ve onun halefleri.

Bazı durumlarda, paylaşılan kitaplıkların farklı sürümleri sorunlara neden olabilir, özellikle farklı sürümlerin kitaplıkları aynı dosya adlarına sahip olduğunda ve sistemde kurulu farklı uygulamalar için kullanıldığında, her biri belirli bir sürüm gerektirir. Böyle bir senaryo olarak bilinir

Paylaşılan kitaplık, içerdiği sembolleri, bu sembolleri film kitaplıklarına kopyalamadan birden çok filmde kullanmanıza olanak tanır. Bu nedenle, paylaşılan kitaplık nesneleri adlandırılmıştır. Kaynaklar(Varlıklar). Bu durumda, paylaşılan kitaplık harici bir dosya olarak kullanılır ve oluşturulan (veya düzenlenen) filme eklenmez.

Örneğin aşağıdaki durumlarda paylaşılan kitaplıkların kullanılması önerilir:

  • aynı film müziğini sitenin birkaç sayfasında kullanırken;
  • sitenin birkaç sayfasında yazı tipinin metin karakterlerini kullanırken;
  • bir filmde veya birden çok filmde birden fazla sahnede kullanılan animasyon öğeleri için tek bir kaynak sağlamak istediğinizde;
  • yaptığınız değişiklikleri kontrol etmeyi kolaylaştırmak için merkezi bir kaynak kitaplığına ihtiyacınız olduğunda.

Flash MX, iki tür paylaşılan kitaplığı destekler:

  • Çalışma süresi- paylaşılan çalışma zamanı kitaplığı; böyle bir kütüphanede bulunan semboller birkaç film tarafından paylaşılabilir, ancak bu semboller sadece doğrudan kaynak filmde düzenlenebilir;
  • Yazar zamanı- geliştirme sırasında paylaşılan kütüphane; böyle bir kütüphanede bulunan semboller birkaç film tarafından paylaşılabilir ve kütüphanenin içeriğini herhangi bir ortak filmde düzenlemeye izin verilir.

Paylaşılan kitaplık kaynaklarının uzak bir sitede barındırılan filmlerde kullanılabilmesi için, kitaplıkla birlikte Flash dosyasının SWF biçiminde dışa aktarılması ve Web sitesine yüklenmesi gerekir.

Yorum Yap
Flash'ın önceki sürümü yalnızca paylaşılan çalışma zamanı kitaplığını destekler
.

Gibi paylaşılan bir kitaplık oluşturmak için Çalışma süresi, gerekli:

  1. Kaynaklarını (içerdiği sembolleri) ayrı bir filmde belirleyin.
  2. Paylaşılan karakterlerin dışa aktarılmasına izin ver.
  3. Kitaplığın barındırılacağı sitenin URL'sini belirtin.
  4. Bu kitaplık ile Flash dosyasını SWF formatına aktarın ve web sitesine yükleyin.

Paylaşılan kütüphane sembollerini kullanabilmek Çalışma süresi diğer filmlerde ("ortak sahipler"), her birinde paylaşılan karakterlere bir bağlantı oluşturmak gerekir.

Şimdi yukarıdaki adımlara daha detaylı bakalım.

Paylaşılan bir kitaplık oluşturduktan sonra, dahil edilen hangi sembollerin diğer filmlere aktarılabileceğini belirtmeniz gerekir. Bu, aşağıdaki adımları gerektirir:

  1. Listeden "paylaşılan" yapmak istediğiniz sembolü seçin.
  2. Sembolün içerik menüsünde komutu seçin bağlama(Bağlayıcı).
  3. Açılan iletişim kutusunda Sembol Bağlantı Özellikleri(Sembol bağlama parametreleri), Şek. 10.12, kutuyu işaretleyin Çalışma zamanı paylaşımı için dışa aktarma(Çalışma zamanında dışa aktarmaya izin verin).
  4. Bir metin kutusunda tanımlayıcı ortak sahip filmine aktarılacağı sembolün adını (tanımlayıcısını) girin; varsayılan, kitaplık sembolü adı olsa da, boşluk içeriyorsa bunları kaldırın.
  5. Bir metin kutusunda URL'si kaynak filmin (yani, paylaşılan kitaplık SWF dosyası) İnternet adresini girin.
  6. Dışa aktarılan sembol, ortak sahipli filmin ilk karesinden doğrudan kullanılacaksa, İlk karede dışa aktar.
  7. Dışa aktarılan sembolün ActionScript'te kullanılabilir olmasını istiyorsanız, ActionScript için dışa aktar.

Pirinç. 10.12... Paylaşılan Kitaplık Sembol Ayarları İletişim Kutusu

Paylaşılan kitaplık kaynaklarını kullanmak için Çalışma süresi bir ortak sahip filminde aşağıdaki adımlar gereklidir:

  1. Menüden seçim yaparak bu filmin kitaplığını açın pencere emretmek Kütüphane.
  2. Kitaplık açılır menüsünden komutu seçin Yeni Sembol; sonuç olarak, ekranda bir iletişim kutusu belirecektir. Yeni Sembol Oluştur(Yeni bir sembol oluşturun), orta kısmı iletişim kutusuna benzer biçimde Sembol Bağlantı Özellikleri(şek.10.13).
  3. Bir metin kutusunda tanımlayıcı ortak sahip filmine aktarılacak sembolün adını girin.
  4. Bir metin kutusunda URL'si kaynak filmin internet adresini girin.


Pirinç. 10.13... Bölünmüş karakterin parametrelerini ayarlamak için iletişim kutusu

Statik ve dinamik kütüphaneler.

Kitaplıklara, kural olarak, bir dizi ilgili problemi çözmeye odaklanan alt rutinlerin veya nesnelerin "koleksiyonları" denir. Organizasyonları ve kullanımları açısından kütüphaneler statik ve dinamiktir.

Statik kitaplıklar (statik kitaplıklar), programcı tarafından programına dahil edilen veya derleme aşamasında birbirine bağlanan önceden derlenmiş nesne dosyaları biçiminde bir dizi kaynak kodu olabilir. Windows'ta bu dosyalar genellikle şu uzantıya sahiptir:<.lib>... Statik bir kitaplık ile bağlantı kurmanın bir sonucu olarak, program kullandığı tüm işlevleri içerir, bu da boyutunu artırır, ancak onu daha bağımsız hale getirir.

Dinamik kitaplıklar (paylaşılan kitaplık, dinamik bağlantı kitaplığı), işletim sistemi tarafından, çalışan bir programın yürütülmesi sırasında zaten "talep" üzerine yüklenir. Gerekli kitaplık zaten belleğe yüklenmişse, yeniden yükleme gerçekleştirilmez. Bu durumda, aynı işlevler veya kitaplık nesneleri, çalışan birkaç program tarafından aynı anda kullanılabilir, bu da RAM kaynaklarının verimli bir şekilde kullanılmasını mümkün kılar. Windows'ta paylaşılan kitaplıklar genellikle şu uzantıya sahiptir:<.dll>.

Kütüphaneyi kullanmak için, derleyiciye onu bağlamanız ve kütüphaneden fonksiyonu çağırmanız gerektiğini (uygun başlık dosyasını kullanarak), fonksiyonun kaynak metnine ihtiyaç duymadığınızı söylemeniz gerekir.

Dinamik bir kitaplık oluşturma.

Microsoft Visual Studio'da bir dinamik bağlantı kitaplığı oluşturmak için bir proje oluşturmak, aptal bir uygulama için bir proje oluşturmak için olağan prosedüre benzer. Proje türü Win32 Konsol Uygulamasıdır, yalnızca şimdi yeni proje sihirbazında "DLL" öğesini seçmeniz gerekir:

Sihirbazda böyle bir öğe yoksa, normal bir Konsol Uygulaması projesi oluşturabilir ve ardından proje özelliklerinde türünü ayarlayabilirsiniz:

Konfigürasyon Özellikleri => Genel => Konfigürasyon Türü: Dinamik Kitaplık (.dll)

Declspec (dllexport) geçersiz gösterimi (const char * str);

#include "dlltest.h"

geçersiz ekran (const char * str)

__declspec (dllexport) değiştiricisi, kitaplığın belirtilen işlevi diğer uygulamalar tarafından kullanılmak üzere dışa aktarmasına olanak tanır.

Projeyi oluşturmanın bir sonucu olarak, uzantılı dinamik bir kütüphane dosyası<.dll>ve ayrıca uzantılı bir içe aktarma kitaplığı dosyası<.lib>... İçe aktarma kitaplığı, dinamik kitaplığın sonraki kullanımını kolaylaştırmak için tasarlanmıştır. İçe aktarma kitaplığının dosya uzantısı, statik kitaplıklar için standart uzantı ile aynı olmasına rağmen, karıştırılmamalıdır.

Dinamik bir kitaplık kullanma.

Bir programda dinamik kitaplığı kullanmanın iki yolu vardır. Örtülü bağlama, kitaplık tarafından sağlanan işlevlerin adreslerini belirlemek için bir içe aktarma kitaplığı kullanmayı içerir. İşletim sistemi, programın yürütülebilir dosyasını yükledikten sonra DLL'yi yükler. Yürütülebilir dosya, dışa aktarılan DLL işlevlerini, işlevler yürütülebilir dosyanın içinde yer alıyormuş gibi çağırır.

Açıkça bağlanırken, DLL'yi kullanan yürütülebilir dosya, DLL'yi açıkça yüklemek ve boşaltmak ve dışa aktarılan DLL işlevlerine erişmek için işlev çağrıları yapmalıdır. İstemci yürütülebilir dosyası, bir işlev işaretçisi kullanarak dışa aktarılan işlevleri çağırır.

Seçilen yöntemden bağımsız olarak, yürütülebilir dosya aynı DLL'yi kullanabilir. Ayrıca, bu mekanizmalar birbirini dışlamaz çünkü bir yürütülebilir dosya dolaylı olarak bir DLL'ye bağlanırken, bir diğeri açıkça bağlanabilir.

Örnek olarak, oluşturulmuş basit kitaplığı bağlamak için örtük bağlantı mekanizmasını (en basit olanı olarak) kullanacağız.

Normal bir konsol uygulamasının ayrı bir projesini oluşturalım (kütüphanenin projesiyle aynı çözüm çerçevesinde mümkündür). Kitaplıkta uygulanan görüntüleme işlevini kullanmak için şunları yapmalısınız:

    İlgili başlık dosyası “dlltest.h”yi bağlayın. Bunu yapmak için, ya doğrudan #include direktifindeki dosya yolunu kullanın (projeler aynı çözüm klasöründe bulunuyorsa, göreli bir yol kullanmak daha iyidir) ya da proje özelliklerinde bu başlığa giden yolu ekleyin bölümdeki dosya

Konfigürasyon Parametreleri => C / C++ => Genel => Ek Dahil Etme Dizinleri

    Uygun içe aktarma kitaplığı dosyasını kullanın. Bunu yapmak için, formun bir yönergesini kullanabilirsiniz (burada yerleşik lib dosyasının göreli yolu kullanılır).

Alternatif olarak, proje özelliklerinde içe aktarma kitaplığı dosyasının yolunu ekleyebilirsiniz.

Konfigürasyon Parametreleri => Bağlayıcı => Giriş => Ek Bağımlılıklar

Şimdi aşağıdaki içeriğe sahip ana program dosyasını oluşturalım:

#pragma yorumu (lib, "../Debug/dlltest.lib")

#include "dlltest.h"

ekran ("Merhaba");

sistem ("duraklat");

Programı başarılı bir şekilde başlatmak için geriye kalan tek şey ilgili DLL'nin kullanılabilir olduğundan emin olmaktır. Program başladığında, işletim sistemi, PATH ortam değişkeni tarafından tanımlanan sistem yollarının yanı sıra programın başlatıldığı klasördeki tüm gerekli kitaplık dosyalarını arayacaktır. Buna göre, yerleşik kitaplığın DLL dosyası, çağıran programın yürütülebilir dosyasıyla aynı klasörde veya PATH'de tanımlanan klasörlerden birinde olmalıdır.