Turli xil transport turlarining afzalliklari va kamchiliklari. Transport logistikasi transporti. Xalqaro avtomobil transporti

Linux uchun standart C kompilyatori bo'lgan gcc dan to'g'ri foydalanish uchun siz buyruq qatori parametrlarini o'rganishingiz kerak. Bundan tashqari, gcc C tilini kengaytiradi.Hatto siz manba kodingizni ushbu tilning ANSI standartida yozmoqchi bo'lsangiz ham, Linux sarlavhali fayllarini tushunish uchun bilishingiz kerak bo'lgan ba'zi gcc kengaytmalari mavjud.

Buyruqlar qatori opsiyalarining aksariyati C kompilyatorlari tomonidan qo'llaniladigan variantlar bilan bir xil.Ba'zi variantlar uchun standartlar yo'q. Ushbu bobda biz kundalik dasturlashda qo'llaniladigan eng muhim variantlarni ko'rib chiqamiz.

ISO C standartiga moslashishga harakat qilish foydalidir, lekin C past darajadagi til bo'lganligi sababli, standart xususiyatlar etarlicha ifodali bo'lmagan holatlar mavjud. Gcc kengaytmalari keng qo'llaniladigan ikkita soha mavjud: montaj kodi bilan o'zaro ta'sir qilish (bu mavzular http://www.delorie.com/djgpp/doc/brennan/ saytida yoritilgan) va umumiy kutubxonalar qurish (8-bobga qarang). Sarlavha fayllari umumiy kutubxonalarning bir qismi bo'lganligi sababli, ba'zi kengaytmalar tizim sarlavhasi fayllarida ham paydo bo'ladi.

Albatta, har qanday boshqa dasturlashda foydali bo'lgan ko'plab kengaytmalar mavjud bo'lib, ular haqiqatan ham kodlashda yordam beradi. Ushbu kengaytmalar haqida qo'shimcha ma'lumotni gcc Texinfo hujjatlarida topishingiz mumkin.

5.1. gcc imkoniyatlari

gcc ko'plab buyruq variantlarini qabul qiladi. Yaxshiyamki, siz haqiqatan ham bilishingiz kerak bo'lgan variantlar to'plami unchalik katta emas va bu bobda biz buni ko'rib chiqamiz.

Aksariyat variantlar boshqa kompilyatorlarniki bilan bir xil yoki o'xshash, gcc info gcc orqali mavjud bo'lgan opsiyalarining katta hujjatlarini o'z ichiga oladi (gcc man sahifasi ham bu ma'lumotni beradi, ammo man sahifalari Texinfo hujjatlari kabi tez-tez yangilanmaydi. ).

-o fayl nomi Chiqish faylining nomini belgilaydi. Agar ob'ekt fayliga kompilyatsiya qilsangiz, bu odatda kerak emas, ya'ni sukut bo'yicha filename.c ni filename.o bilan almashtirish kerak. Biroq, agar siz bajariladigan faylni yaratsangiz, sukut bo'yicha (tarixiy sabablarga ko'ra) u a.out nomi ostida yaratilgan. Bu, shuningdek, chiqish faylini boshqa katalogga joylashtirmoqchi bo'lganingizda ham foydalidir.
- Bilan Buyruqlar satrida ko'rsatilgan manba faylni bog'lamasdan kompilyatsiya qiladi. Natijada har bir manba fayl uchun obyekt fayli yaratiladi. make dan foydalanilganda, odatda har bir obyekt fayli uchun gcc kompilyatori chaqiriladi; Shunday qilib, xatolik yuz bergan taqdirda, qaysi fayl kompilyatsiya qilinmaganligini aniqlash osonroq bo'ladi. Biroq, agar siz buyruqlarni qo'lda yozayotgan bo'lsangiz, bitta gcc qo'ng'irog'ida bir nechta fayl ko'rsatilishi odatiy hol emas. Agar buyruq satrida bir nechta fayllarni belgilashda noaniqlik paydo bo'lishi mumkin bo'lsa, faqat bitta faylni ko'rsatish yaxshiroqdir. Masalan, gcc -c -o a.o a.c b.c o'rniga gcc -c -o a.o b.c dan foydalanish mantiqan to'g'ri keladi.
-Dfoo Buyruqlar satrida protsessor makroslarini belgilaydi. Qobiq maxsus belgilar sifatida ko'radigan belgilarni olib tashlashingiz kerak bo'lishi mumkin. Misol uchun, satrni belgilashda " stringni tugatish belgilaridan foydalanishdan qochishingiz kerak. Ikkita eng keng tarqalgan usul "-Dfoo="bar"" va -Dfoo=\"bar\". Birinchi usul, agar bo'lsa, ancha yaxshi ishlaydi. satrda bo'shliqlar mavjud, chunki qobiq bo'shliqqa maxsus tarzda ishlov beradi.
- I katalogi Qo'shilgan fayllarni qidirish uchun kataloglar ro'yxatiga katalog qo'shadi.
-L katalogi Kutubxonalarni qidirish uchun kataloglar ro'yxatiga katalog qo'shadi, agar boshqacha ko'rsatilmagan bo'lsa, gcc umumiy kutubxonalarni statik kutubxonalardan afzal ko'radi.
-l foo Lib foo kutubxonasiga havolalar. Agar boshqacha ko'rsatilmagan bo'lsa, gcc umumiy kutubxonalarga (lib foo .so) statik kutubxonalarga (lib foo .a) nisbatan ulanishni afzal ko'radi. Bog'lovchi barcha ro'yxatga olingan kutubxonalardagi funktsiyalarni ular ro'yxatga olingan tartibda qidiradi. Barcha kerakli funksiyalar topilganda qidiruv tugaydi.
-statik Faqat statik kutubxonalar bilan bog'lanish. 8-bobga qarang.
-g , -ggdb Nosozliklarni tuzatish ma'lumotlarini o'z ichiga oladi. -g parametri gcc standart disk raskadrovka ma'lumotlarini o'z ichiga oladi. -ggdb opsiyasi qo'shishni belgilaydi katta miqdor faqat gdb tuzatuvchisi tushuna oladigan ma'lumot.
Agar disk maydoni cheklangan bo'lsa yoki ulanish tezligi uchun ba'zi funksiyalarni qurbon qilmoqchi bo'lsangiz, -g dan foydalaning. Bunday holda, gdb dan boshqa tuzatuvchidan foydalanishingiz kerak bo'lishi mumkin. Eng to'liq disk raskadrovka uchun -ggdb ni belgilashingiz kerak. Bunday holda, gcc imkon qadar ko'proq tayyorlaydi batafsil ma'lumot gdb uchun. Shuni ta'kidlash kerakki, ko'pchilik kompilyatorlardan farqli o'laroq, gcc ba'zi disk raskadrovka ma'lumotlarini optimallashtirilgan kodga joylashtiradi. Biroq, optimallashtirilgan kodni tuzatuvchida kuzatish qiyin bo'lishi mumkin, chunki ish vaqti siz ishga tushirishni kutayotgan kod qismlarini o'tkazib yuborishi va o'tkazib yuborishi mumkin. Biroq, olish mumkin yaxshi ishlash kompilyatorlarni optimallashtirish kodning bajarilishini qanday o'zgartirishi haqida.
-O, -On Kodni optimallashtirish uchun gcc sabab bo'ladi. Odatiy bo'lib, gcc kichik hajmdagi optimallashtirishni amalga oshiradi; raqamni (n) belgilashda optimallashtirish ma'lum darajada amalga oshiriladi. Eng keng tarqalgan optimallashtirish darajasi 2; hozirda gcc ning standart versiyasida eng yuqori optimallashtirish darajasi 3. -O2 yoki -O3 dan foydalanishni tavsiya etamiz; -O3 ilova hajmini oshirishi mumkin, shuning uchun agar bu muhim bo'lsa, ikkalasini ham sinab ko'ring. Agar ilovangiz uchun xotira va disk maydoni muhim bo'lsa, siz -Os variantidan ham foydalanishingiz mumkin, bu esa bajarilish vaqtini oshirish hisobiga kod hajmini minimallashtiradi. gcc faqat kamida minimal optimallashtirish (-O) qo'llanilganda o'rnatilgan dasturlarni ishga tushiradi.
-ansi Barcha ANSI standartlari (X3.159-1989) yoki ularning ISO ekvivalenti (ISO/IEC 9899:1990) (odatda C89 yoki kamroq C90 deb ataladi) C dasturlarini qo'llab-quvvatlash. E'tibor bering, bu ANSI/ISO standartiga to'liq muvofiqlikni ta'minlamaydi.
-ansi opsiyasi odatda ANSI/ISO standartlariga zid bo'lgan gcc kengaytmalarini o'chiradi. (Ushbu kengaytmalar boshqa ko'plab C kompilyatorlari tomonidan qo'llab-quvvatlanganligi sababli, bu amalda muammo emas.) U shuningdek, sarlavha fayllari ANSI/ISO muvofiqligini qo'llab-quvvatlash uchun foydalanadigan __STRICT_ANSI__ makrosini (ushbu kitobda keyinroq tasvirlanganidek) belgilaydi. muhit.
- pedantik ANSI/ISO C tili standarti talab qiladigan barcha ogohlantirishlar va xatolarni ko'rsatadi.Bu ANSI/ISO standartiga to'liq mos kelishini ta'minlamaydi.
- Devor Barcha gcc ogohlantirishlarini yaratishga ruxsat beradi, bu odatda foydalidir. Lekin bu muayyan holatlarda foydali bo'lishi mumkin bo'lgan variantlarni o'z ichiga olmaydi. Manba kodingiz uchun lint parser uchun shunga o'xshash granülerlik darajasi o'rnatiladi, gcc har bir kompilyator ogohlantirishini qo'lda yoqish va o'chirish imkonini beradi. Gcc qo'llanmasida barcha ogohlantirishlar batafsil tavsiflangan.
5.2. sarlavha fayllari
5.2.1. uzoq uzun

Long uzun turi xotira blokining eng kamida uzunligi kabi katta ekanligini bildiradi. Intel i86 va boshqa 32-bitli platformalarda uzun - 32 bit, uzun - 64 bit. 64-bitli platformalarda koʻrsatgichlar va uzun uzunlar 64 bitni oladi va platformaga qarab uzun 32 yoki 64 bitni olishi mumkin. Long long turi C99 standartida (ISO/IEC 9899:1999) qo'llab-quvvatlanadi va gcc tomonidan taqdim etilgan uzoq muddatli C kengaytmasi hisoblanadi.

5.2.2. O'rnatilgan funktsiyalar

Linux sarlavha fayllarining ba'zi qismlari (ayniqsa, ma'lum bir tizimga xos bo'lganlar) o'rnatilgan funktsiyalardan juda keng foydalanadi. Ular makroslar kabi tezdir (funksiya qo'ng'iroqlari uchun xarajat yo'q) va oddiy funktsiya chaqiruvida mavjud bo'lgan barcha turdagi tasdiqlashni ta'minlaydi. O'rnatilgan funktsiyalarni chaqiruvchi kod kamida minimal optimallashtirish (-O) yoqilgan holda kompilyatsiya qilinishi kerak.

5.2.3. Muqobil kengaytirilgan kalit so'zlar

Gcc-da har bir kengaytirilgan kalit so'z (ANSI/ISO standarti bilan belgilanmagan kalit so'zlar) ikkita versiyaga ega: o'zi kalit so'z va ikkala tomondan ikkita pastki chiziq bilan o'ralgan kalit so'z. Kompilyator standart rejimda foydalanilganda (odatda -ansi opsiyasi yoqilganda), oddiy kengaytirilgan kalit so'zlar tan olinmaydi. Masalan, sarlavha faylidagi atribut kalit so'zi __attribute__ sifatida yozilishi kerak.

5.2.4. Atributlar

Atribut kengaytirilgan kalit so'zi funksiya, o'zgaruvchi yoki e'lon qilingan tur haqida ANSI/ISO C kodida ruxsat etilganidan ko'ra gcc ga ko'proq ma'lumot uzatish uchun ishlatiladi. Masalan, aligned atributi gccga o'zgaruvchi yoki turni qanday tekislash kerakligini aniq aytadi; paketlangan atribut hech qanday to'ldirish ishlatilmasligini bildiradi; noreturn funksiya hech qachon qaytmasligini bildiradi, bu esa gccga yaxshiroq optimallashtirish va soxta ogohlantirishlardan qochish imkonini beradi.

Funktsiya atributlari ularni funksiya deklaratsiyasiga qo'shish orqali e'lon qilinadi, masalan:

void die_die_die(int, char*) __attribute__ ((__noreturn__));

Atribut deklaratsiyasi qavslar va nuqta-vergul orasiga joylashtiriladi va atribut kalit so'zidan keyin qo'sh qavs ichidagi atributlardan iborat. Agar ko'plab atributlar mavjud bo'lsa, vergul bilan ajratilgan ro'yxatni ishlatish kerak.

printm (char*, ...)

Atribut__((const,

format (printf, 1, 2)));

Ushbu misolda siz printm ko'rsatilgan qiymatlardan boshqa qiymatlarni hisobga olmasligini va kod yaratish (const) bilan bog'liq nojo'ya ta'sirlarga ega emasligini ko'rishingiz mumkin, printm gcc funksiya argumentlarini printf() kabi tekshirishi kerakligini ko'rsatadi. argumentlar. Birinchi argument format satri, ikkinchi argument esa birinchi almashtirish parametri (format).

Ba'zi atributlar materialning rivojlanishi davomida muhokama qilinadi (masalan, 8-bobda umumiy kutubxonalar qurish tavsifi paytida). Atributlar haqida to'liq ma'lumotni Texinfo formatidagi gcc hujjatlarida topish mumkin.

Vaqti-vaqti bilan siz o'zingizni Linux sarlavhalari fayllarini ko'rib chiqishingiz mumkin. Siz ANSI/ISOga mos kelmaydigan bir qancha dizaynlarni topishingiz mumkin. Ulardan ba'zilari ko'rib chiqishga arziydi. Ushbu kitobda yoritilgan barcha tuzilmalar gcc hujjatlarida batafsilroq yoritilgan.

Vaqti-vaqti bilan siz o'zingizni Linux sarlavhalari fayllarini ko'rib chiqishingiz mumkin. Siz ANSI/ISOga mos kelmaydigan bir qancha dizaynlarni topishingiz mumkin. Ulardan ba'zilari ko'rib chiqishga arziydi. Ushbu kitobda yoritilgan barcha tuzilmalar gcc hujjatlarida batafsilroq yoritilgan.

Endi siz C standarti haqida bir oz ma'lumotga ega bo'ldingiz, keling, gcc kompilyatori siz yozayotgan tilning C standartiga mos kelishini ta'minlash uchun taklif qiladigan variantlarni ko'rib chiqaylik. Sizning C kodingiz standartlarga mos kelishini va kamchiliklardan xoli ekanligini ta'minlashning uchta yo'li mavjud: standartning qaysi versiyasiga mos kelmoqchi ekanligingizni nazorat qiluvchi variantlar, sarlavha fayllarini boshqaruvchi ta'riflar va yanada qattiqroq kod tekshiruvini ishga tushiradigan ogohlantirish variantlari. .

gcc juda katta imkoniyatlar to'plamiga ega va bu erda biz faqat eng muhim deb hisoblaganlarini ko'rib chiqamiz. Variantlarning to'liq ro'yxatini gcc onlayn man sahifalarida topish mumkin. Foydalanish mumkin bo'lgan #define direktiv variantlarini ham qisqacha muhokama qilamiz; ular odatda manba kodingizda #include qatorlaridan oldin ko'rsatilishi yoki gcc buyruq satrida aniqlanishi kerak. Mavjud standartni ishlatishga majbur qilish uchun oddiy bayroq o'rniga qaysi standartni tanlashni tanlash imkoniyatlarining ko'pligi sizni hayratda qoldirishi mumkin. Buning sababi shundaki, ko'plab eski dasturlar tarixiy kompilyator xatti-harakatlariga tayanadi va ularni eng so'nggi standartlarga yangilash uchun katta ishni talab qiladi. Kamdan-kam hollarda, agar kerak bo'lsa, siz kompilyatoringizni ishlaydigan kodni buzadigan tarzda yangilashni xohlaysiz. Standartlar o'zgarganda, standartning eng so'nggi versiyasi bo'lmasa ham, ma'lum bir standartga qarshi ishlay olish muhimdir.

Agar siz shaxsiy foydalanish uchun kichik dastur yozayotgan bo'lsangiz ham, standartlarga muvofiqligi unchalik muhim bo'lmasligi mumkin bo'lsa ham, dastur ishga tushishidan oldin kompilyatorni kodingizdagi xatolarni izlashga majbur qilish uchun qo'shimcha gcc ogohlantirishlarini kiritish mantiqan to'g'ri keladi. Bu nosozliklarni tuzatuvchidagi kodni bosib o'tish va muammo qayerda bo'lishi mumkinligini bilishdan ko'ra har doim samaraliroqdir. Kompilyatorda oddiy standartlarni tekshirishdan tashqari ko'plab variantlar mavjud, masalan, standartga mos keladigan, ammo shubhali semantikaga ega bo'lgan kodni aniqlash qobiliyati. Masalan, dastur o'zgaruvchiga ishga tushirilgunga qadar unga kirish imkonini beruvchi bajarish tartibiga ega bo'lishi mumkin.

Agar siz umumiy foydalanish uchun dastur yozishingiz kerak bo'lsa, moslik darajasi va kompilyator ogohlantirishlarining turlarini hisobga olgan holda, siz ko'proq kuch sarflash va hech qanday ogohlantirishlarsiz kodingizni kompilyatsiya qilish juda muhimdir. Agar siz ba'zi ogohlantirishlarni qabul qilsangiz va ularga e'tibor bermaslikni odat qilsangiz, bir kun sizni yo'qotish xavfi haqida jiddiyroq ogohlantirish paydo bo'lishi mumkin. Agar sizning kodingiz har doim ogohlantirish xabarlarisiz tuzilsa, sizning e'tiboringizga yangi ogohlantirish keladi. Kodni ogohlantirishsiz kompilyatsiya qilish yaxshi odatdir.

Kuzatuv standartlari uchun kompilyator variantlari

Ansi standartlar bo'yicha eng muhim variant bo'lib, kompilyatorning ISO C90 til standartiga muvofiq ishlashiga sabab bo'ladi. U ba'zi nostandart gcc kengaytmalarini o'chiradi, C dasturlarida C++ uslubidagi izohlarni (//) o'chiradi va ANSI trigraflari (uch belgili ketma-ketliklar) bilan ishlashga imkon beradi. Bundan tashqari, u __STRICT_ANSI__ makrosini o'z ichiga oladi, bu standartga mos kelmaydigan sarlavha fayllaridagi ba'zi kengaytmalarni o'chiradi. Kompilyatorning kelajakdagi versiyalarida qabul qilingan standart o'zgarishi mumkin.

Std= - Bu parametr aynan qaysi standart talab qilinishini ko'rsatuvchi parametrni taqdim etish orqali qaysi standartdan foydalanishni aniqroq boshqarish imkonini beradi. Quyidagi asosiy variantlar mavjud:

C89 - C89 standartini qo'llab-quvvatlaydi;

Iso9899:1999 - ISO standartining so'nggi versiyasini qo'llab-quvvatlash, C90;

Gnu89 - C89 standartini qo'llab-quvvatlang, lekin ba'zi GNU kengaytmalari va ba'zi C99 funksiyalariga ruxsat bering. Gcc ning 4.2 versiyasida bu parametr sukut bo'yicha hisoblanadi.

Aniq direktivalarda standartni kuzatish variantlari

Buyruqlar satrida variantlar sifatida yoki dasturning manba kodidagi ta'riflar sifatida ko'rsatilishi mumkin bo'lgan doimiylar (#defines) mavjud. Biz ularni odatda kompilyator buyruq satridan foydalanish deb hisoblaymiz.

STRICT_ANSI__ ISO C standartidan foydalanishga majbur qiladi. Kompilyator buyruq satrida -ansi opsiyasi berilganda aniqlanadi.

POSIX_C_SOURCE=2 - IEEE Std 1003.1 va 1003.2 tomonidan belgilangan funksiyalarni yoqadi. Biz ushbu standartlarga keyinroq ushbu bobda qaytamiz.

BSD_SOURCE - BSD tizimlarining funksiyalarini yoqadi. Agar ular POSIX ta'riflariga zid bo'lsa, BSD ta'riflari ustunlik qiladi.

GNU_SOURCE - GNU kengaytmalarini o'z ichiga olgan turli xil xususiyatlar va funktsiyalarga ruxsat beradi. Agar bu ta'riflar POSIX ta'riflariga zid bo'lsa, ikkinchisi ustunlik qiladi.

Ogohlantirishlarni chiqarish uchun kompilyator imkoniyatlari

Bu variantlar kompilyatorga buyruq satridan uzatiladi. Va yana, biz faqat asosiylarini sanab o'tamiz, to'liq ro'yxat gcc onlayn yordam qo'llanmasida topish mumkin.

Pedantic C kodini tozalashning eng kuchli variantidir.S standarti bilan tekshirish imkoniyatini yoqishdan tashqari, standart tomonidan taqiqlangan ba'zi an'anaviy C konstruksiyalarini o'chiradi va barcha GNU kengaytmalarini standartdan noqonuniy qiladi. Bu imkoniyatdan C kodingizni iloji boricha ko‘chma qilish uchun qo‘llanilishi kerak.Kasalligi shundaki, kompilyator kodingizning tozaligi haqida juda qayg‘uradi va ba’zida qolgan bir nechta ogohlantirishlardan xalos bo‘lish uchun miyangizni chalg‘itishingiz kerak bo‘ladi.

Wformat - printf turkumi funktsiyalari argumentlari turlarining to'g'riligini tekshiradi.

Wqavslar - kerak bo'lmagan joylarda ham qavslar mavjudligini tekshiradi. Ushbu parametr murakkab tuzilmalar mo'ljallangan tarzda ishga tushirilganligini tekshirish uchun juda foydali.

wswitch-default - odatda yaxshi dasturlash uslubi deb hisoblangan switch iboralarida standart variant mavjudligini tekshiradi.

Wunused - E'lon qilingan, lekin e'lon qilinmagan statik funktsiyalar, foydalanilmagan parametrlar, o'chirilgan natijalar kabi turli holatlarni tekshiradi.

Wall - Ko'pgina gcc ogohlantirish turlarini, shu jumladan oldingi barcha -W opsiyalarini yoqadi (faqat -pedantic qo'llanilmaydi). Uning yordami bilan dastur kodining tozaligiga erishish oson.

Eslatma

Yana ko'plab ilg'or ogohlantirish variantlari mavjud, barcha tafsilotlar uchun gcc veb-sahifalariga qarang. Umuman olganda, biz foydalanishni tavsiya qilamiz -Wall ; Bu dastur kodini tekshirish o'rtasida yaxshi kelishuvdir Yuqori sifatli, va kompilyatorning bekor qilish qiyin bo'lgan juda ko'p ahamiyatsiz ogohlantirishlarni chiqarish zarurati.

GCC har bir tarqatish bilan birga kiritilgan linux va odatda sukut bo'yicha o'rnatiladi. GCC interfeysi UNIX platformasidagi standart kompilyator interfeysi bo'lib, o'tgan asrning 60-yillari oxiri, 70-yillari boshlarida ildiz otgan - buyruq qatori interfeysi. Qo'rqmang, o'tgan vaqt ichida foydalanuvchining o'zaro ta'siri mexanizmi bu holatda mumkin bo'lgan mukammallikka erishildi va GCC bilan ishlang (bir nechta qo'shimcha yordam dasturlari va yaxshi matn muharriri) har qanday zamonaviy vizual IDE-ga qaraganda osonroq. To'plam mualliflari iloji boricha ilovalarni kompilyatsiya qilish va yig'ish jarayonini avtomatlashtirishga harakat qilishdi. Foydalanuvchi boshqaruv dasturini chaqiradi gcc, u o'tkazilgan buyruq qatori argumentlarini (variantlar va fayl nomlari) sharhlaydi va har bir kirish fayli uchun ishlatiladigan dasturlash tiliga muvofiq, o'z kompilyatorini ishga tushiradi, keyin kerak bo'lganda, gcc avtomatik ravishda assembler va bog‘lovchini (bog‘lovchi) chaqiradi.

Qizig'i shundaki, kompilyatorlar fayl kengaytmalari haqida qayg'uradigan bir nechta UNIX dasturlaridan biridir. Kengaytma bo'yicha, GCC uning oldida qanday fayl mavjudligini va u bilan nima qilish kerakligini aniqlaydi. Til manba fayllari C tilda .c kengaytmasiga ega bo'lishi kerak C++, muqobil ravishda, .cpp , tildagi sarlavha fayllari C.h, .o obyekt fayllari va boshqalar. Agar siz noto'g'ri kengaytmadan foydalansangiz, gcc to'g'ri ishlamaydi (agar siz umuman biror narsa qilishga rozi bo'lsangiz).

Keling, amaliyotga o'tamiz. Keling, oddiy dasturni yozamiz, kompilyatsiya qilamiz va bajaramiz. Tildagi misol dasturning manba fayli sifatida original bo'lmaylik C Keling, quyidagi tarkibga ega fayl yarataylik:

/* salom.c */

#o'z ichiga oladi

Asosiy( bekor )
{

Printf("Salom Dunyo\n");

qaytish 0 ;

Endi c hello.c katalogida biz buyruq beramiz:

$ gcc salom.c

Bir necha soniyadan so'ng a.out fayli katalogda paydo bo'ladi:

$ls
a.out hello.c

Bu dasturimizning tugallangan bajariladigan fayli. Standart gcc chiquvchi bajariladigan faylga a.out nomini beradi (bir vaqtlar bu nom assembler chiqishi).

$file a.out
a.out: ELF 64-bitli LSB bajariladigan, x86-64, 1-versiya (SYSV), dinamik bog'langan (umumiy liblardan foydalanadi), GNU/Linux 2.6.15 uchun, o'chirilmagan

Keling, natijani ishga tushiramiz dasturiy ta'minot:

$ ./a.out
Salom Dunyo


Joriy katalogdan faylni bajarish uchun nima uchun ishga tushirish buyrug'ida faylga yo'lni aniq ko'rsatish kerak? Agar bajariladigan faylga yo'l aniq ko'rsatilmagan bo'lsa, qobiq, sharhlovchi buyruqlar, ro'yxati PATH tizim o'zgaruvchisi tomonidan ko'rsatilgan kataloglardan faylni qidiradi.

$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

Ro'yxatdagi kataloglar ikki nuqta bilan ajratilgan. Fayllarni qidirishda qobiq kataloglarni ro'yxatdagi tartibda ko'rib chiqadi. Odatiy bo'lib, xavfsizlik nuqtai nazaridan joriy katalog . ro'yxatga kiritilmagan; shunga ko'ra, qobiq undagi bajariladigan fayllarni qidirmaydi.

Nima uchun qilish tavsiya etilmaydi. PATH da? Haqiqiy ko'p foydalanuvchili tizimda har doim zararli dasturni mahalliy ma'mur tomonidan superuser bilan chaqiradigan ba'zi buyruq nomiga mos keladigan bajariladigan fayl nomi bilan umumiy katalogga joylashtiradigan yomon odam bo'ladi, deb ishoniladi. huquqlari ... Agar fitna muvaffaqiyatli bo'ladi. katalog ro'yxatining boshida joylashgan.


Qulaylik fayl buyruq satrida uzatilgan fayl turi (tizim nuqtai nazaridan) haqidagi ma'lumotlarni ko'rsatadi, ba'zi turdagi fayllar uchun u barcha turdagilarni ko'rsatadi. Qo'shimcha ma'lumot faylning mazmuni haqida.

$file hello.c
hello.c: ASCII C dasturi matni
$file annotation.doc
annotation.doc: CDF V2 Document, Little Endian, Os: Windows, Versiya 5.1, Kod sahifasi: 1251, Muallif: MIH, Andoza: Normal.dot, Oxirgi saqlangan: MIH, Nashr raqami: 83, Yaratilgan ilova nomi: Microsoft Office Word, Jami tahrir vaqti: 09:37:00, Oxirgi chop etilgan: 2009-yil 22-yanvar 07:31:00, Yaratish vaqti/sanasi: 2009-yil 12-yanvar 07:36:00, oxirgi saqlangan vaqt/sana: 22-yanvar 07:34:00 2009, Sahifalar soni: 1, Soʻzlar soni: 3094, Belgilar soni: 17637, Xavfsizlik: 0

Muvaffaqiyatli dastur uchun foydalanuvchidan talab qilinadigan narsa shu gcc :)

Chiqariladigan bajariladigan faylning nomi (shuningdek, tomonidan yaratilgan boshqa har qanday fayl gcc) bilan oʻzgartirish mumkin variantlari -o:

$ gcc -o salom salom.c
$ls
salom salom.c
$./salom
Salom Dunyo


Bizning misolimizda main() funktsiyasi keraksiz ko'rinadigan 0 qiymatini qaytaradi. UNIX-ga o'xshash tizimlarda dastur oxirida qobiqqa butun sonni qaytarish odatiy holdir - muvaffaqiyatli yakunlangan taqdirda, nolga, boshqa har qanday. Qobiq tarjimoni olingan qiymatni avtomatik ravishda ? nomli muhit o'zgaruvchisiga tayinlaydi. . Siz uning mazmunini echo $ yordamida ko'rishingiz mumkinmi? :

$./salom
Salom Dunyo
$ echo $?
0

Bu haqda yuqorida aytilgan edi gcc kompilyatsiya jarayonini avtomatlashtirish uchun moʻljallangan boshqaruv dasturidir. Keling, gcc hello.c buyrug'ini bajarish natijasida nima sodir bo'lishini ko'rib chiqaylik.

Kompilyatsiya jarayonini 4 ta asosiy bosqichga bo'lish mumkin: preprotsessorni qayta ishlash, haqiqiy kompilyatsiya, yig'ish, bog'lash (bog'lash).

Variantlar gcc ushbu bosqichlarning har qandayida jarayonni to'xtatishga imkon beradi.

Preprotsessor dastlabki faylni kompilyatsiya uchun tayyorlaydi - sharhlarni kesib tashlaydi, sarlavha fayllari tarkibini qo'shadi (preprotsessor direktivasi #include ), makrolarni kengaytirishni amalga oshiradi (ramziy konstantalar, preprotsessor direktivasi #define ).

Foyda olish -E variant keyingi harakatlar gcc preprotsessor tomonidan qayta ishlangan fayl mazmunini to'xtatishingiz va ko'rishingiz mumkin.

$ gcc -E -o salom.i salom.c
$ls
salom.c salom.i
$ kamroq salom.i
. . .
# 1 "/usr/include/stdio.h" 1 3 4
№ 28 "/usr/include/stdio.h" 3 4
# 1 "/usr/include/features.h" 1 3 4
. . .
typedef unsigned char __u_char;
typedef unsigned short int __u_short;
typedef unsigned int __u_int;
. . .
extern int printf (__const char *__cheklash __format, ...);
. . .
№4 "salom.c" 2
asosiy (bo'sh)
{
printf("Salom dunyo\n");
qaytish 0;
}

Preprotsessor tomonidan qayta ishlanganidan so'ng, dasturimizning dastlabki matni shishib ketdi va o'qib bo'lmaydigan shaklga ega bo'ldi. Biz bir paytlar o'z qo'llarimiz bilan tergan kod faylning eng oxirida bir necha qatorga qisqartirildi. Buning sababi standart kutubxonaning sarlavha faylini kiritishdir C. stdio.h sarlavha faylining o'zi juda ko'p turli xil narsalarni o'z ichiga oladi va boshqa sarlavha fayllarini kiritishni talab qiladi.

hello.i fayl kengaytmasiga e'tibor bering. Shartnomalar bo'yicha gcc.i kengaytmasi tildagi manba kodi bo'lgan fayllarga mos keladi C preprotsessorni qayta ishlashni talab qilmaydi. Bunday fayllar preprotsessorni chetlab o'tib kompilyatsiya qilinadi:

$ gcc -o salom hello.i
$ls
salom salom.c salom.i
$./salom
Salom Dunyo

Oldindan ishlov berishdan keyin kompilyatsiya navbati keladi. Kompilyator dasturning yuqori darajali tildagi manba kodini assembler tilidagi kodga aylantiradi.

Kompilyatsiya so'zining ma'nosi noaniq. Vikipediyachilar, masalan, murojaat qilib, ko'rib chiqamiz xalqaro standartlar bu kompilyatsiya "kompilyator dasturi tomonidan o'zgartirish manba kodi Yuqori darajadagi dasturlash tilida, mashina kodiga yaqin tilda yoki ob'ekt kodida yozilgan har qanday dastur." Aslida, bu ta'rif bizga mos keladi, assembler tili haqiqatan ham mashina tiliga qaraganda yaqinroq. C. Ammo kundalik hayotda kompilyatsiya ko'pincha har qanday dasturlash tilida dasturning manba kodini bajariladigan kodga aylantiradigan har qanday operatsiya sifatida tushuniladi. Ya'ni, yuqoridagi to'rtta bosqichni o'z ichiga olgan jarayonni kompilyatsiya deb ham atash mumkin. Xuddi shunday noaniqlik ushbu matnda ham mavjud. Boshqa tomondan, dasturning dastlabki matnini assembler tili kodiga aylantirish operatsiyasi so'z tarjimasi bilan ham belgilanishi mumkin - "dasturlash tillaridan birida taqdim etilgan dasturni boshqa tildagi dasturga aylantirish va, ma'lum bir ma'noda, birinchisiga teng".

Kompilyatsiya oxirida bajariladigan faylni yaratish jarayonini to'xtatish imkonini beradi -S variant:

$ gcc -S salom.c
$ls
salom.c salom.s
$file hello.s
salom.s: ASCII assembler dasturi matni
$ kamroq salom.s
.fayl "hello.c"
.bo'lim .rodata
.LC0:
.string "Salom dunyo"
.matn
.glob main
.asosiy, @funksiyani yozing
asosiy:
pushl %ebp
movl %esp, %ebp
va l -16$, %esp
subl $16, %esp
movl $.LC0, (%esp)
qo'ng'iroq qiladi
movl $0, %eks
tark eting
ret
.hajmi asosiy, .-asosiy


Assembler tilida dasturni amalga oshirishni o'z ichiga olgan katalogda hello.s fayli paydo bo'ldi. bilan chiqish fayl nomini ko'rsatish unutmang variantlari -o bu holda kerak emas edi gcc uni manba fayl nomidagi .c kengaytmasini .s bilan almashtirish orqali avtomatik ravishda yaratdi. Ko'pgina asosiy operatsiyalar uchun gcc chiqish faylining nomi shunday almashtirish orqali hosil bo'ladi. .s kengaytmasi assembler tilidagi manba fayllari uchun standart hisoblanadi.

Albatta, siz hello.s faylidan bajariladigan kodni ham olishingiz mumkin:

$ gcc -o salom salom.s
$ls
salom salom.c salom.s
$./salom
Salom Dunyo

Yig'ish operatsiyasining navbatdagi bosqichi assembler tili kodini mashina kodiga tarjima qilishdir. Amaliyot natijasi ob'ekt faylidir. Ob'ekt fayli bajarishga tayyor bo'lgan mashina kodining bloklarini, ma'lumotlar bloklarini va faylda aniqlangan funktsiyalar va tashqi o'zgaruvchilar ro'yxatini o'z ichiga oladi ( belgilar jadvali ), lekin shu bilan birga, u funktsiyalar va ma'lumotlarga havolalarning mutlaq manzillarini ko'rsatmaydi. Ob'ekt faylini to'g'ridan-to'g'ri bajarish mumkin emas, lekin keyinchalik (bog'lanish bosqichida) uni boshqa ob'ekt fayllari bilan birlashtirish mumkin (bu holda, belgilar jadvallariga muvofiq, fayllar o'rtasida mavjud bo'lgan o'zaro bog'liqliklarning manzillari hisoblab chiqiladi va to'ldiriladi. ). Variant gcc-c , yig'ish bosqichining oxirida jarayonni to'xtatadi:

$ gcc -c salom.c
$ls
salom.c salom.o
$file hello.o
hello.o: ELF 64-bitli LSB oʻzgartirilishi mumkin, x86-64, 1-versiya (SYSV), oʻchirilmagan

Obyekt fayllari standart .o kengaytmasidan foydalanadi.

Qabul qilingan hello.o ob'ekt fayli bog'lovchiga uzatilsa, ikkinchisi havolalar manzillarini hisoblab chiqadi, dasturni ishga tushirish va tugatish kodini, kutubxona funktsiyalarini chaqirish kodini qo'shadi va natijada biz tayyor faylga ega bo'lamiz. -dasturning bajariladigan fayli.

$ gcc -o salom salom.o
$ls
salom salom.c salom.o
$./salom
Salom Dunyo

Biz hozir nima qildik (aniqrog'i gcc biz uchun qildi) va oxirgi bosqichning mazmuni mavjud - bog'lash (bog'lash, bog'lash).

Xo'sh, ehtimol kompilyatsiya va hamma narsa haqida. Endi ba'zi, mening fikrimcha, muhim variantlarga to'xtalib o'tamiz. gcc.

Variant - I yo'l/katalog/bilan/sarlavha/fayllar - ko'rsatilgan katalogni sarlavhali fayllarni qidirish yo'llari ro'yxatiga qo'shadi. Katalog variant bo'yicha qo'shiladi -I avval qidiriladi, keyin standart tizim kataloglarida qidirish davom etadi. Variantlar bo'lsa -I bir nechta, ular ko'rsatgan kataloglar variantlar paydo bo'lishi bilan chapdan o'ngga skanerlanadi.

- Devor varianti- dasturni kompilyatsiya qilishga to'sqinlik qilmaydigan, lekin kompilyatorning fikriga ko'ra, uni bajarish jarayonida ma'lum muammolarga olib kelishi mumkin bo'lgan koddagi mumkin bo'lgan xatolar tufayli ogohlantirishlarni ko'rsatadi. Muhim va foydali variant, ishlab chiquvchilar gcc har doim foydalanishni tavsiya eting. Masalan, bunday faylni kompilyatsiya qilishga urinayotganda juda ko'p ogohlantirishlar beriladi:

1 /* remark.c */
2
3 statik int k = 0
4 statik int l( int a);
5
6 asosiy()
7 {
8
9 int a;
10
11 int b, c;
12
13b + 1;
14
15b=c;
16
17 int*p;
18
19b = *p;
20
21 }


$ gcc -o remark remark.c
$ gcc -Wall -o remark remark.c
remark.c:7: ogohlantirish: standartni "int" ga qaytarish

remark.c:13: ogohlantirish: ta'siri yo'q bayonot
remark.c:9: ogohlantirish: foydalanilmagan o'zgaruvchi "a"
remark.c:21: ogohlantirish: boshqaruv bekor bo'lmagan funksiyaning oxiriga etadi
remark.c: Yuqori darajada:
remark.c:3: ogohlantirish: 'k' belgilangan, lekin ishlatilmaydi
remark.c:4: ogohlantirish: "l" "statik" deb e'lon qilingan, lekin hech qachon aniqlanmagan
remark.c: "asosiy" funksiyada:
remark.c:15: ogohlantirish: 'c' bu funksiyada ishga tushirilmagan holda ishlatiladi
remark.c:19: ogohlantirish: "p" bu funksiyada ishga tushirilmagan holda ishlatiladi

Variant - xato- barcha ogohlantirishlarni xatolarga aylantiradi. Agar ogohlantirish paydo bo'lsa, kompilyatsiya jarayonini to'xtatadi. Bilan birga ishlatiladi - Devor varianti.

$ gcc -Werror -o remark remark.c
$ gcc -Werror -Wall -o remark remark.c
cc1: ogohlantirishlar xato sifatida qabul qilinadi
remark.c:7: xato: "int" ga qaytish turi
remark.c: "asosiy" funksiyada:
remark.c:13: xato: ta'siri yo'q bayonot
remark.c:9: xato: foydalanilmagan o'zgaruvchi "a"

Variant -g- tuzatuvchining ob'ekt yoki bajariladigan faylda ishlashi uchun zarur bo'lgan ma'lumotlarni joylashtiradi gdb. Keyinchalik disk raskadrovka qilish uchun loyihani qurishda, variant -g kompilyatsiya vaqtida ham, havola vaqtida ham kiritilishi kerak.

Variantlar -O1 , -O2 , -O3- kompilyator tomonidan yaratilgan kodni optimallashtirish darajasini belgilash. Raqam ortishi bilan optimallashtirish darajasi oshadi. Variantlarning harakatini ushbu misolda ko'rish mumkin.

Asl fayl:

/* circle.c */

Asosiy( bekor )
{

int i;

uchun(i = 0; i< 10 ; ++i)
;

qaytish i;

Standart optimallashtirish darajasi bilan kompilyatsiya qilish:

$ gcc -S doira.c
$ kamroq doiralar
.fayl "circle.c"
.matn
.glob main
.asosiy, @funksiyani yozing
asosiy:
pushl %ebp
movl %esp, %ebp
subl $16, %esp
movl $0, -4(%ebp)
jmp .L2
.L3:
qo'shimcha $1, -4(%ebp)
.L2:
cmpl $9, -4(%ebp)
jle .L3
movl -4(%ebp), %eks
tark eting
ret
.hajmi asosiy, .-asosiy
.ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
.bo'lim .note.GNU-stack,"",@progbits

Maksimal optimallashtirish darajasi bilan kompilyatsiya:

$ gcc -S -O3 doira.c
$ kamroq doiralar
.fayl "circle.c"
.matn
.p2align 4.15
.glob main
.asosiy, @funksiyani yozing
asosiy:
pushl %ebp
movl $10, %x
movl %esp, %ebp
popl %ebp
ret
.hajmi asosiy, .-asosiy
.ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
.bo'lim .note.GNU-stack,"",@progbits

Ikkinchi holda, natijada paydo bo'lgan kodda hech qanday tsikl haqida hatto ishora ham yo'q. Darhaqiqat, i qiymatini kompilyatsiya bosqichida hisoblash mumkin, bu amalga oshirildi.

Afsuski, haqiqiy loyihalar uchun turli xil optimallashtirish darajalarida ishlashdagi farq deyarli sezilmaydi...

Variant -O0- har qanday kodni optimallashtirishni bekor qiladi. Variant dasturni tuzatish bosqichida talab qilinadi. Yuqorida ko'rsatilganidek, optimallashtirish dastur strukturasining tanib bo'lmaydigan darajada o'zgarishiga olib kelishi mumkin, bajariladigan va manba kodi o'rtasidagi bog'liqlik aniq bo'lmaydi, mos ravishda dasturni bosqichma-bosqich tuzatish mumkin bo'lmaydi. Variant yoqilganda -g, kiritish tavsiya etiladi va -O0.

-Os variant- optimallashtirishni kod samaradorligi bilan emas, balki natijada olingan fayl hajmi bo'yicha belgilaydi. Dasturning ishlashi standart optimallashtirish darajasi bilan kompilyatsiya qilish natijasida olingan kodning ishlashi bilan taqqoslanishi kerak.

Variant -march=arxitektura- protsessorning maqsadli arxitekturasini belgilaydi. Qo'llab-quvvatlanadigan arxitekturalar ro'yxati keng, masalan, oila protsessorlari uchun Intel/AMD sozlashingiz mumkin i386, pentium, preskott, opteron-sse3 va hokazo. Ikkilik taqsimot foydalanuvchilari shuni yodda tutishlari kerakki, ko'rsatilgan variantga ega bo'lgan dasturlar to'g'ri ishlashi uchun barcha kiritilgan kutubxonalar bir xil variant bilan kompilyatsiya qilinishi maqsadga muvofiqdir.

Bog'lovchiga uzatilgan variantlar quyida muhokama qilinadi.

Kichik qo'shimcha:

Bu haqda yuqorida aytilgan edi gcc uzatilgan fayllarning turini (dasturlash tilini) ularning kengaytmasi bo'yicha aniqlaydi va taxmin qilingan turga (tilga) muvofiq ular ustida amallarni bajaradi. Foydalanuvchi tuzilgan fayllarning kengaytmalarini shartnomalar talabiga binoan tanlagan holda kuzatishi shart gcc. Aslida gcc ixtiyoriy nomlar bilan fayllarni qo'yishingiz mumkin. gcc -x opsiyasi kompilyatsiya qilingan fayllarning dasturlash tilini aniq belgilash imkonini beradi. Variantning harakati buyruqda ko'rsatilgan barcha keyingi fayllar uchun amal qiladi (keyingi variant paydo bo'lgunga qadar) -x). Mumkin variant argumentlari:

c c-sarlavhasi c-cpp-chiqish

c++ c++-sarlavhasi c++-cpp-chiqish

ob'ektiv-c ob'ektiv-c-sarlavhasi ob'ektiv-c-cpp-chiqish

ob'ektiv-c++ ob'ektiv-c++-sarlavhasi ob'ektiv-c++-cpp-chiqish

assembler assembler-bilan-cpp

ada

f77 f77-cpp-kirish

f95 f95-cpp-kirish

java

Bahslarning maqsadi ularning yozilishidan aniq bo'lishi kerak (bu erda cpp bilan aloqasi yo'q C++, bu dastlabki protsessor tomonidan oldindan ishlangan manba kodli fayl). Keling, tekshiramiz:

$mv hello.c hello.txt
$ gcc -Wall -x c -o salom hello.txt
$./salom
Salom Dunyo

Alohida kompilyatsiya

Tillarning kuchli nuqtasi C/C++ dasturning dastlabki kodini bir nechta fayllarga bo'lish qobiliyatidir. Siz hatto ko'proq aytishingiz mumkin - alohida kompilyatsiya qilish imkoniyati tilning asosidir, u holda samarali foydalanish C tasavvur qilib bo'lmaydi. Bu ko'p faylli dasturlash bo'lib, uni amalga oshirishga imkon beradi C kabi yirik loyihalar linux(bu erda so'z ostida linux yadro ham, butun tizim ham nazarda tutilgan). Dasturchiga alohida kompilyatsiya nima beradi?

1. Dastur (loyiha) kodini yanada o'qilishi mumkin bo'lishiga imkon beradi. Bir necha o'nlab ekranlar uchun manba fayli deyarli katta bo'ladi. Agar biron bir (oldindan tuzilgan) mantiqqa muvofiq, uni bir nechta kichik bo'laklarga (har biri alohida faylda) ajratsangiz, loyihaning murakkabligini engish ancha oson bo'ladi.

2. Loyihani qayta tuzish vaqtini qisqartiradi. Agar bitta faylga o'zgartirishlar kiritilsa, butun loyihani qayta kompilyatsiya qilishning ma'nosi yo'q, faqat ushbu o'zgartirilgan faylni qayta kompilyatsiya qilish kifoya.

3. Loyiha bo'yicha ishlarni bir nechta ishlab chiquvchilar orasida taqsimlash imkonini beradi. Har bir dasturchi loyihaning o'z qismini yaratadi va disk raskadrovka qiladi, lekin istalgan vaqtda yakuniy mahsulotga barcha natijaviy ishlanmalarni yig'ish (qayta tiklash) mumkin bo'ladi.

4. Alohida kompilyatsiya bo'lmasa, kutubxonalar bo'lmaydi. Kutubxonalar orqali kodni qayta ishlatish va tarqatish C/C++, va kod ikkilik bo'lib, bu, bir tomondan, ishlab chiquvchilarga uni o'z dasturlariga kiritish uchun oddiy mexanizmni taqdim etish imkonini beradi, boshqa tomondan, ulardan aniq amalga oshirish tafsilotlarini yashirish imkonini beradi. Loyiha ustida ishlayotganda, har doim o'ylab ko'rishga arziydimi va kelajakda amalga oshirilgan ishlardan biror narsaga muhtoj emasmi? Ehtimol, kodning bir qismini oldindan kutubxona sifatida ajratib ko'rsatish va tartibga solishga arziydimi? Menimcha, bu yondashuv hayotni sezilarli darajada soddalashtiradi va ko'p vaqtni tejaydi.

GCC, albatta, alohida kompilyatsiyani qo'llab-quvvatlaydi va foydalanuvchidan hech qanday maxsus ko'rsatmalar talab qilmaydi. Umuman olganda, hamma narsa juda oddiy.

Mana amaliy misol (juda shartli bo'lsa ham).

Manba kodli fayllar to'plami:

/* main.c */

#o'z ichiga oladi

#"first.h"ni o'z ichiga oladi
#"ikkinchi.h"ni o'z ichiga oladi

int asosiy( bekor )
{

birinchi ();
ikkinchi();

Printf("Asosiy funktsiya... \n" );

qaytish 0 ;


/* first.h */

bekor birinchi ( bekor );


/* first.c */

#o'z ichiga oladi

#"first.h"ni o'z ichiga oladi

bekor birinchi ( bekor )
{

Printf("Birinchi funktsiya... \n" );


/* soniya.h */

bekor ikkinchi( bekor );


/* second.c */

#o'z ichiga oladi

#"ikkinchi.h"ni o'z ichiga oladi

bekor ikkinchi( bekor )
{

Printf("Ikkinchi funksiya... \n" );

Umuman olganda, bizda quyidagilar mavjud:

$ls
birinchi.c birinchi.h asosiy.c ikkinchi.c ikkinchi.s

Bu iqtisodiyotning barchasini bitta buyruqqa jamlash mumkin:

$ gcc -Wall -o main main.c birinchi.c ikkinchi.c
$./asosiy
Birinchi funksiya...
Ikkinchi funksiya...
asosiy funksiyasi...

Faqat bu bizga deyarli hech qanday bonuslarni bermaydi, bir nechta fayllarga tarqalgan yanada tuzilgan va o'qilishi mumkin bo'lgan kod bundan mustasno. Yuqorida sanab o'tilgan barcha afzalliklar kompilyatsiyaga ushbu yondashuvda paydo bo'ladi:

$ gcc -Wall -c main.c
$ gcc -Wall -c birinchi.c
$ gcc -Wall -c soniya.c
$ls
birinchi.c birinchi.h birinchi.o asosiy.c asosiy.o ikkinchi.c ikkinchi.h ikkinchi.o
$ gcc -o main main.o birinchi.o ikkinchi.o
$./asosiy
Birinchi funksiya...
Ikkinchi funksiya...
asosiy funksiyasi...

Biz nima qildik? Har bir manba fayldan (variant bilan kompilyatsiya qilish -c) ob'ekt faylini oldi. Keyin ob'ekt fayllari yakuniy bajariladigan faylga bog'landi. Albatta buyruqlar gcc ko'proq narsa bor, lekin hech kim loyihalarni qo'lda yig'maydi, buning uchun assembler yordam dasturlari mavjud (eng mashhur qilish). Assembler yordam dasturlaridan foydalanganda, yuqorida sanab o'tilgan alohida kompilyatsiyaning barcha afzalliklari o'zini namoyon qiladi.

Savol tug'iladi: qanday qilib bog'lovchi qo'ng'iroq manzilini to'g'ri hisoblab, ob'ekt fayllarini birlashtirishga muvaffaq bo'ladi? U ikkinchi.o faylida ikkinchi() funksiya kodi va main.o fayl kodida uning chaqiruvi borligini u qayerdan biladi? Ma'lum bo'lishicha, hamma narsa oddiy - ob'ekt faylida shunday deb ataladigan narsa bor belgilar jadvali , bu ba'zi kod pozitsiyalarining nomlarini o'z ichiga oladi (funktsiyalar va tashqi o'zgaruvchilar). Bog'lovchi har bir ob'ekt faylining belgilar jadvalini ko'rib chiqadi, umumiy (mos keladigan nomlar bilan) pozitsiyalarni qidiradi, ular asosida foydalanilgan funktsiyalar (yoki ma'lumotlar bloklari) kodining haqiqiy joylashuvi to'g'risida xulosa chiqaradi va shunga mos ravishda, bajariladigan fayldagi chaqiruv manzillarini qayta hisoblab chiqadi.

Yordamchi dastur yordamida belgilar jadvalini ko'rishingiz mumkin nm.

$nm main.o
U birinchi
00000000 T asosiy
U qo'yadi
U ikkinchi
$nm birinchi
Avval 00000000 T
U qo'yadi
$nm soniya
U qo'yadi
00000000 T soniya

Puts chaqiruvi kompilyatsiya vaqtida puts() ga aylangan printf() kutubxonasining standart funksiyasidan foydalanish bilan bog‘liq.

Belgilar jadvali nafaqat obyekt fayliga, balki bajariladigan faylga ham yoziladi:

$nm asosiy
08049f20d_DYNAMIC
08049ff4d _GLOBAL_OFFSET_TABLE_
080484fc R _IO_stdin_used
w _Jv_RegisterClasses
08049f10 d __CTOR_END__
08049f0cd __CTOR_LIST__
08049f18 D __DTOR_END__
08049f14 d __DTOR_LIST__
08048538r __FRAME_END__
08049f1cd __JCR_END__
08049f1c d __JCR_LIST__
0804a014 __bss_start
0804a00c D __data_start
080484b0 t __do_global_ctors_aux
08048360 t __do_global_dtors_aux
0804a010 D __dso_tutqich
w __gmon_start__
080484aa T __i686.get_pc_thunk.bx
08049f0cd __init_array_end
08049f0cd __init_array_start
08048440 T __libc_csu_fini
08048450 T __libc_csu_init
U __libc_start_main@@GLIBC_2.0
0804a014 A _edata
0804a01c A_end
080484dc T_fini
080484f8 R_fp_hw
080482b8 T _init
08048330 T_start
0804a014b tugallandi.7021
0804a00c Vt data_start
0804a018 b dtor_idx.7023
Avval 0804840c T
080483c0 t frame_dummy
080483e4 T asosiy
U puts@@GLIBC_2.0
08048420 T soniya

Bajariladigan faylga belgilar jadvalini kiritish, ayniqsa disk raskadrovka qulayligi uchun zarur. Aslida, dasturni ishga tushirish uchun haqiqatan ham kerak emas. Ko'p funksiya ta'riflari va turli xil kutubxonalarni o'z ichiga olgan tashqi o'zgaruvchilarga ega bo'lgan haqiqiy dastur bajariladigan dasturlar uchun belgilar jadvali juda keng bo'ladi. Chiqish faylining hajmini kamaytirish uchun uni yordamida olib tashlash mumkin gcc -s opsiyasi.

$ gcc -s -o main main.o birinchi.o ikkinchi.o
$./asosiy
Birinchi funksiya...
Ikkinchi funksiya...
asosiy funksiyasi...
$nm asosiy
nm: asosiy: belgilar yo'q

Shuni ta'kidlash kerakki, ulanish paytida bog'lovchi funktsiya chaqiruvi kontekstida hech qanday tekshiruv o'tkazmaydi, qaytarilgan qiymatning turini va qabul qilingan parametrlarning turini va sonini kuzatmaydi (va uni olish uchun hech qanday joy yo'q). dan ma'lumot). Barcha qo'ng'iroqlarni tekshirish kompilyatsiya vaqtida amalga oshirilishi kerak. Ko'p faylli dasturlashda buning uchun tilning sarlavha fayllari mexanizmidan foydalanish kerak. C.

Kutubxonalar

Kutubxona - tilda C, bog'lanish bosqichida kutubxona yordamida dasturga biriktirilishi mumkin bo'lgan ob'ekt kodini o'z ichiga olgan fayl. Aslida, kutubxona maxsus bog'langan ob'ekt fayllari to'plamidir.

Kutubxonalarning maqsadi dasturchiga kodni qayta ishlatish uchun standart mexanizmni taqdim etishdir va mexanizm oddiy va ishonchli.

Operatsion tizim va amaliy dasturiy ta'minot nuqtai nazaridan kutubxonalar statik Va birgalikda (dinamik ).

Statik kutubxona kodi ikkinchisini ulash paytida bajariladigan faylga kiritilgan. Kutubxona faylga "qattiq ulangan", kutubxona kodi fayl kodining qolgan qismi bilan "birlashtirilgan". Statik kutubxonalardan foydalanadigan dastur mustaqil bo'lib qoladi va to'g'ri arxitektura va operatsion tizimga ega deyarli har qanday kompyuterda ishga tushirilishi mumkin.

Birgalikda kutubxona kodi yuklanadi va uni bajarish jarayonida dastur talabiga binoan operatsion tizim tomonidan dastur kodiga bog'lanadi. Dinamik kutubxona kodi dasturning bajariladigan fayliga kiritilmagan, faqat kutubxonaga havola bajariladigan faylga kiritilgan. Natijada, umumiy kutubxonalardan foydalanadigan dastur endi mustaqil emas va faqat tegishli kutubxonalar o'rnatilgan tizimda muvaffaqiyatli ishga tushirilishi mumkin.

Umumiy kutubxona paradigmasi uchta muhim afzalliklarni beradi:

1. Bajariladigan fayl hajmi sezilarli darajada kamayadi. Xuddi shu kodni ishlatadigan ko'plab ikkilik fayllarni o'z ichiga olgan tizimda har bir bajariladigan fayl uchun ushbu kodning nusxasini saqlashga hojat yo'q.

2. Bir nechta ilovalar tomonidan qo'llaniladigan umumiy kutubxona kodi bir nusxada RAMda saqlanadi (aslida bu unchalik oddiy emas...), natijada tizimning mavjud operativ xotiraga bo'lgan ehtiyoji kamayadi.

3. Agar umumiy kutubxona kodiga o'zgartirishlar kiritilgan bo'lsa, har bir bajariladigan faylni qayta tiklashning hojati yo'q. Dinamik kutubxona kodiga kiritilgan o'zgartirishlar va tuzatishlar uni ishlatadigan har bir dasturda avtomatik ravishda aks ettiriladi.

Umumiy kutubxona paradigmasi bo'lmasa, oldindan tuzilgan (ikkilik) taqsimotlar bo'lmaydi linux(ha, nima bo'lishidan qat'iy nazar). Har bir ikkilik faylda standart kutubxona kodi joylashtirilgan tarqatish hajmini tasavvur qiling. C(va boshqa barcha kutubxonalar). Keng tarqalgan kutubxonalardan birida muhim zaiflikni tuzatgandan so'ng tizimni yangilash uchun nima qilish kerakligini tasavvur qiling...

Endi biroz mashq qilish uchun.

Tasavvur qilish uchun, keling, oldingi misoldagi manba fayllar to'plamidan foydalanamiz. Keling, birinchi () va ikkinchi () funktsiyalarining kodini (amalga oshirish) uy qurilishi kutubxonamizga joylashtiramiz.

Linuxda kutubxona fayllari uchun quyidagi nomlash sxemasi mavjud (garchi bu har doim ham kuzatilmasa ham) - kutubxona faylining nomi lib prefiksi bilan boshlanadi, keyin kutubxonaning haqiqiy nomi, oxirida .a ( kengaytmasi bilan boshlanadi. Arxiv ) - statik kutubxona uchun, .so ( umumiy ob'ekt ) - umumiy (dinamik) uchun, kengaytirilgandan so'ng, versiya raqami raqamlari nuqta orqali ko'rsatiladi (faqat dinamik kutubxona uchun). Kutubxonaga mos keladigan sarlavha faylining nomi (yana, qoida tariqasida) kutubxona nomidan (prefiks va versiyasiz) va kengaytmadan iborat .h . Masalan: libogg.a , libogg.so.0.7.0 , ogg.h .

Birinchidan, statik kutubxona yaratamiz va foydalanamiz.

Birinchi () va ikkinchi () funktsiyalari bizning libhello kutubxonamiz tarkibini tashkil qiladi. Kutubxona faylining nomi mos ravishda libhello.a bo'ladi. Keling, hello.h sarlavha faylini kutubxona bilan taqqoslaylik.

/* salom.h */

bekor birinchi ( bekor );
bekor ikkinchi( bekor );

Albatta, qatorlar:

#"first.h"ni o'z ichiga oladi


#"ikkinchi.h"ni o'z ichiga oladi

main.c, first.c va second.c fayllarida quyidagilar bilan almashtirilishi kerak:

#shu jumladan "hello.h"

Xo'sh, endi quyidagi buyruqlar ketma-ketligini kiriting:

$ gcc -Wall -c birinchi.c
$ gcc -Wall -c soniya.c
$ ar crs libhello.a birinchi.o ikkinchi.o
$filelibhello.a
libhello.a: joriy arxiv

Yuqorida aytib o'tilganidek, kutubxona ob'ekt fayllari to'plamidir. Birinchi ikkita buyruq yordamida biz ushbu obyekt fayllarini yaratdik.

Keyinchalik, ob'ekt fayllarini to'plamga bog'lashingiz kerak. Buning uchun arxivator ishlatiladi. ar- yordamchi dastur bir nechta fayllarni bittaga "yopishadi", natijada olingan arxivda har bir alohida faylni tiklash (chiqarish) uchun zarur bo'lgan ma'lumotlar (shu jumladan uning egalik, kirish, vaqt atributlari) mavjud. Arxiv tarkibini har qanday "siqish" yoki saqlangan ma'lumotlarni boshqa o'zgartirish amalga oshirilmaydi.

c arname opsiyasi- arxiv yaratish, agar arname nomli arxiv mavjud bo'lmasa, u yaratiladi, aks holda fayllar mavjud arxivga qo'shiladi.

r variant- arxivni yangilash rejimini o'rnatadi, agar ko'rsatilgan nomga ega fayl arxivda allaqachon mavjud bo'lsa, u o'chiriladi va yangi fayl arxivning oxiriga qo'shiladi.

Variant s- arxiv indeksini qo'shadi (yangilaydi). Bunday holda, arxiv indeksi arxivlangan fayllarda aniqlangan har bir ramziy nom (funktsiya yoki ma'lumotlar bloki nomi) uchun tegishli ob'ekt fayl nomi bilan bog'langan jadvaldir. Arxiv indeksi kutubxona bilan ishlashni tezlashtirish uchun zarur - kerakli ta'rifni topish uchun barcha arxiv fayllarining belgilar jadvallarini ko'rib chiqishning hojati yo'q, siz darhol o'zingiz qidirayotgan nomni o'z ichiga olgan faylga o'tishingiz mumkin. . Siz allaqachon tanish bo'lgan yordamchi dastur yordamida arxiv indeksini ko'rishingiz mumkin nm undan foydalanish variant -lar(arxivning barcha ob'ekt fayllarining belgilar jadvallari ham ko'rsatiladi):

$ nm -s libhello.a
arxiv indeksi:
birinchi ichida birinchi.o
soniyada ikkinchi.o

birinchi.o:
Avval 00000000 T
U qo'yadi

ikkinchisi:
U qo'yadi
00000000 T soniya

Arxiv indeksini yaratish uchun maxsus yordamchi dastur mavjud ranlib. libhello.a kutubxonasi shunday yaratilishi mumkin edi:

$ ar cr libhello.a birinchi.o ikkinchi.o
$ranlib libhello.a

Biroq, kutubxona arxiv indeksisiz yaxshi ishlaydi.

Endi kutubxonamizdan foydalanamiz:

$ gcc -Wall -c main.c
$
$./asosiy
Birinchi funksiya...
Ikkinchi funksiya...
asosiy funksiyasi...

Ishlar...

Xo'sh, endi sharhlar ... Ikkita yangi variant mavjud gcc:

-l nomi varianti- bog'lovchiga uzatiladi, libname kutubxonasini bajariladigan faylga bog'lash zarurligini ko'rsatadi. Ulanish falon kutubxonada falon funktsiyalar (tashqi o'zgaruvchilar) aniqlanganligini bildiradi. Bizning misolimizda kutubxona statik, barcha ramziy nomlar to'g'ridan-to'g'ri bajariladigan faylda joylashgan kodga ishora qiladi. Variantlarga e'tibor bering -l kutubxona nomi lib prefiksisiz nom sifatida beriladi.

Variant - L /yo'l/to/katalog/bilan/kutubxonalar - bog'lovchiga uzatiladi, bog'langan kutubxonalarni o'z ichiga olgan katalogga yo'lni belgilaydi. Bizning holatda, nuqta . , bog'lovchi avval joriy katalogdagi kutubxonalarni, so'ngra tizimda belgilangan kataloglarni qidiradi.

Shu o'rinda kichik bir fikrni aytish kerak. Haqiqat shundaki, bir qator variantlar uchun gcc buyruq satrida ularning paydo bo'lish tartibi muhim. Bog'lovchi buyruq satrida ko'rsatilgan kutubxonalardagi faylning belgilar jadvalida ko'rsatilgan nomlarga mos keladigan kodni shunday qidiradi. keyin ushbu faylning nomi. Fayl nomidan oldin sanab o'tilgan kutubxonalar tarkibi bog'lovchi tomonidan e'tiborga olinmaydi:

$ gcc -Wall -c main.c
$ gcc -o asosiy -L. -salom main.o
main.o: “main” funksiyasida:
main.c:(.text+0xa): “birinchi”ga aniqlanmagan havola
main.c:(.text+0xf): "ikkinchi" ga aniqlanmagan havola

$ gcc -o main main.o -L. -salom
$./asosiy
Birinchi funksiya...
Ikkinchi funksiya...
asosiy funksiyasi...

Bunday xatti-harakatlar gcc Ishlab chiquvchilar foydalanuvchiga fayllarni kutubxonalar bilan turli yo'llar bilan birlashtirish, kesishgan nomlardan foydalanish imkoniyatini berish istagi tufayli ... Menimcha, iloji bo'lsa, bu bilan bezovta qilmaslik yaxshiroqdir. Umuman olganda, havola kutubxonalari ularga havola qilingan fayl nomidan keyin ko'rsatilishi kerak.

Mavjud muqobil yo'l tizimdagi kutubxonalarning joylashishini belgilash. Tarqatishga qarab, LD_LIBRARY_PATH yoki LIBRARY_PATH muhit o'zgaruvchisi bog'lovchi kutubxonalarni izlashi kerak bo'lgan ikkita nuqta bilan ajratilgan kataloglar ro'yxatini saqlashi mumkin. Qoida tariqasida, sukut bo'yicha, bu o'zgaruvchi umuman aniqlanmagan, ammo uni yaratishga hech narsa to'sqinlik qilmaydi:

$ echo $LD_LIBRARY_PATH

/usr/lib/gcc/i686-pc-linux-gnu/4.4.3/../../../../i686-pc-linux-gnu/bin/ld: topilmadi -lhello
collect2: ld qaytish kodi 1 bilan chiqdi
$ eksport LIBRARY_PATH=.
$ gcc -o main main.o -lsalom
$./asosiy
Birinchi funksiya...
Ikkinchi funksiya...
asosiy funksiyasi...

Atrof-muhit o'zgaruvchilari bilan manipulyatsiyalar o'z kutubxonalaringizni yaratish va disk raskadrovka qilishda, shuningdek, ba'zi nostandart (eskirgan, yangilangan, o'zgartirilgan - odatda tarqatish to'plamiga kiritilganidan farq qiladigan) umumiy kutubxonani ilovaga ulashda foydalidir.

Endi dinamik kutubxonani yaratamiz va undan foydalanamiz.

Manba fayllar to'plami o'zgarishsiz qoladi. Biz buyruqlarni kiritamiz, nima bo'lganini ko'ramiz, sharhlarni o'qing:

$ gcc -Wall -fPIC -c birinchi.c
$ gcc -Wall -fPIC -c soniya.c
$ gcc -shared -o libhello.so.2.4.0.5 -Wl,-soname,libhello.so.2 first.o second.o

Natijada nimaga erishdingiz?

$ fayl libhello.so.2.4.0.5
libhello.so.2.4.0.5: ELF 64-bitli LSB umumiy obyekti, x86-64, 1-versiya (SYSV), dinamik bogʻlangan, ajratilmagan

libhello.so.2.4.0.5 fayli bizning umumiy kutubxonamizdir. Keling, uni qanday ishlatish haqida quyida gaplashamiz.

Endi sharhlar:

Variant -fPIC- ob'ekt fayllarini yaratishda kompilyatorni yaratishni talab qiladi pozitsiyadan mustaqil kod (PIC - Position mustaqil kodi ), uning asosiy farqi manzillarni taqdim etish usulidadir. Ruxsat etilgan (statik) pozitsiyalarni belgilash o'rniga, barcha manzillar ushbu maqolada ko'rsatilgan ofsetlar asosida hisoblanadi. global ofset jadvali (global ofset jadvali - GOT ). Joylashuvga bog'liq bo'lmagan kod formati bajariladigan modullarni asosiy dastur kodiga uni yuklash vaqtida ulash imkonini beradi. Shunga ko'ra, pozitsiyadan mustaqil kodning asosiy maqsadi dinamik (umumiy) kutubxonalarni yaratishdir.

- umumiy variant- bildiradi gcc, natijada bajariladigan fayl emas, balki umumiy ob'ekt - dinamik kutubxona qurilishi kerak.

Variant -Wl,-soname,libhello.so.2- to'plamlar soname kutubxonalar. Soname haqida keyingi xatboshida batafsil gaplashamiz. Endi variantning formatini muhokama qilaylik. Bu g'alati, birinchi qarashda, vergul bilan qurilish foydalanuvchi va bog'lovchi o'rtasidagi to'g'ridan-to'g'ri o'zaro ta'sir qilish uchun mo'ljallangan. Kompilyatsiya paytida gcc bog'lovchini o'z xohishiga ko'ra avtomatik ravishda avtomatik ravishda chaqiradi, gcc unga vazifani muvaffaqiyatli bajarish uchun zarur bo'lgan variantlarni o'tkazadi. Agar foydalanuvchi ulanish jarayoniga o'zi aralashishi kerak bo'lsa, u maxsus variantdan foydalanishi mumkin gcc -Wl, -option , qiymat1 , qiymat2 .... Bog'lovchiga o'tish nimani anglatadi ( -Wl) variant -variant argumentlar bilan qiymat 1, qiymat 2 va hokazo. Bizning holatda, bog'lovchiga variant berildi -soname argument bilan libhello.so.2.

Endi soname haqida. Kutubxonalarni yaratish va tarqatishda moslik va versiyani boshqarish muammosi mavjud. Tizim, xususan, dinamik kutubxona yuklagichi ilovani kompilyatsiya qilishda kutubxonaning qaysi versiyasi ishlatilganligi va shunga mos ravishda uning muvaffaqiyatli ishlashi uchun zarur bo'lganligi haqida tasavvurga ega bo'lishi uchun maxsus identifikator taqdim etilgan - soname , kutubxona faylida ham, dasturning bajariladigan faylida ham joylashtirilgan. Soname identifikatori lib , nuqta, so kengaytmasi, yana nuqta va kutubxona versiyasining bir yoki ikkita (nuqta bilan ajratilgan) raqamlari, lib nomi .so prefiksli kutubxona nomini o'z ichiga olgan qatordir. x. y . Ya'ni, soname kutubxona fayli nomiga versiya raqamining birinchi yoki ikkinchi raqamiga mos keladi. Kutubxonamizning bajariladigan faylining nomi libhello.so.2.4.0.5 bo‘lsin, keyin kutubxonaning nomi libhello.so.2 bo‘lishi mumkin. Kutubxona interfeysini o'zgartirganda, uning so'mini o'zgartirish kerak! Oldingi versiyalar bilan nomuvofiqlikka olib keladigan har qanday kod modifikatsiyasi yangi soname bilan birga bo'lishi kerak.

Hammasi qanday ishlaydi? Ba'zi ilovalarni muvaffaqiyatli bajarish uchun salom nomli kutubxona kerak bo'lsin, tizimda bitta bo'lsin va kutubxona fayl nomi libhello.so.2.4.0.5 va unda yozilgan kutubxonaning nomi libhello. .so.2 . Ilovani kompilyatsiya qilish bosqichida, variantga ko'ra, bog'lovchi -salom, tizimda libhello.so nomli faylni qidiradi. Haqiqiy tizimda libhello.so libhello.so.2.4.0.5 fayliga ramziy havola hisoblanadi. Kutubxona fayliga kirgandan so'ng, bog'lovchi unda ro'yxatdan o'tgan soname qiymatini o'qiydi va boshqa narsalar qatorida uni dasturning bajariladigan fayliga joylashtiradi. Ilova ishga tushirilganda, dinamik kutubxona yuklovchisi bajariladigan fayldan o'qilgan soname bilan kutubxonani qo'shish so'rovini oladi va tizimda fayl nomi sonamega mos keladigan kutubxonani topishga harakat qiladi. Ya'ni, yuklovchi libhello.so.2 faylini topishga harakat qiladi. Agar tizim to'g'ri sozlangan bo'lsa, unda libhello.so.2 fayliga libhello.so.2.4.0.5 ramziy havolasi bo'lishi kerak, yuklovchi kerakli kutubxonaga kirish huquqiga ega bo'ladi va keyin ikkilanmasdan (va boshqa hech narsani tekshirmasdan) ilovaga ulang. Endi tasavvur qiling-a, biz shu tarzda tuzilgan dasturni faqat libhello.so.1 nomli kutubxonaning oldingi versiyasi o'rnatilgan boshqa tizimga o'tkazdik. Dasturni ishga tushirishga urinish xatolikka olib keladi, chunki bu tizimda libhello.so.2 nomli fayl mavjud emas.

Shunday qilib, kompilyatsiya vaqtida bog'lovchi lib name .so deb nomlangan kutubxona faylini (yoki kutubxona fayliga ramziy havolani) taqdim etishi kerak, ishga tushirish vaqtida yuklovchiga lib name .so deb nomlangan fayl (yoki ramziy havola) kerak bo'ladi. x. y . Nomi lib nomi nima .shuning uchun u bilan aloqasi bor. x. y foydalanilgan kutubxonaning soname qatoriga mos kelishi kerak.

Ikkilik taqsimotlarda, qoida tariqasida, libhello.so.2.4.0.5 kutubxona fayli va unga libhello.so.2 havolasi libhello paketiga joylashtiriladi va faqat kompilyatsiya qilish uchun zarur bo'lgan libhello.so havolasi, hello.h kutubxona sarlavhasi fayli bilan birga libhello-devel paketiga joylashtiriladi (devel paketi libhello.a kutubxonasining statik versiyasi faylini ham o'z ichiga oladi, statik kutubxonadan faqat kompilyatsiya paytida foydalanish mumkin) bosqich). Paketni ochishda barcha ro'yxatdagi fayllar va havolalar (hello.h dan tashqari) bir xil katalogda bo'ladi.

Keling, berilgan string soname haqiqatan ham kutubxonamiz faylida ro'yxatdan o'tganligiga ishonch hosil qilaylik. Keling, mega yordam dasturidan foydalanaylik objdump variant bilan -p :

$ objdump -p libhello.so.2.4.0.5 | grep SONAME
libhello.so.2


Qulaylik objdump- ob'ekt yoki bajariladigan faylning ichki mazmuni (va tuzilishi) haqida to'liq ma'lumot olish imkonini beruvchi kuchli vosita. Yordamchi dasturning man sahifasida shunday deyilgan objdump Avvalo, bu faqat ba'zi amaliy dasturlarni yozish emas, balki disk raskadrovka va kompilyatsiya vositalarini yaratuvchi dasturchilar uchun foydali bo'ladi :) Xususan, variant bilan -d bu qismlarga ajratuvchi. Biz variantdan foydalandik -p- ob'ekt fayli haqida turli xil meta-ma'lumotlarni ko'rsatish.

Kutubxona yaratishning yuqoridagi misolida biz alohida kompilyatsiya qilish tamoyillariga tinimsiz amal qildik. Albatta, kutubxonani bir qo'ng'iroq bilan shunday kompilyatsiya qilish mumkin edi gcc:

$ gcc -shared -Wall -fPIC -o libhello.so.2.4.0.5 -Wl,-soname,libhello.so.2 first.c second.c

Endi olingan kutubxonadan foydalanishga harakat qilaylik:

$ gcc -Wall -c main.c
$
/usr/bin/ld: -lhello topilmadi
collect2: ld 1 chiqish holatini qaytardi

Bog'lovchi qasam ichadi. Yuqorida ramziy havolalar haqida nima deyilganini eslang. libhello.so ni yarating va qaytadan urinib ko'ring:

$ ln -s libhello.so.2.4.0.5 libhello.so
$ gcc -o main main.o -L. -salom -Wl,-rpath,.

Endi hamma xursand. Yaratilgan ikkilik faylni ishga tushiring:

Xato... Yuklovchi shikoyat qilmoqda, libhello.so.2 kutubxonasini topa olmayapti. Keling, libhello.so.2 ga havola haqiqatan ham bajariladigan faylda ro'yxatdan o'tganligiga ishonch hosil qilaylik:

$ objdump -p asosiy | grep KERAK
libhello.so.2
libc.so.6

$ ln -s libhello.so.2.4.0.5 libhello.so.2
$./asosiy
Birinchi funksiya...
Ikkinchi funksiya...
asosiy funksiyasi...

Bu ishladi ... Endi yangi variantlarga sharhlar gcc.

Variant -Wl,-rpath,.- allaqachon tanish qurilish, bog'lovchiga variantni o'tkazing - rpath argument bilan . . Yordamida - rpath dasturning bajariladigan faylida siz umumiy kutubxona yuklagichi kutubxona fayllarini qidiradigan qo'shimcha yo'llarni qo'shishingiz mumkin. Bizning holatda, yo'l . - kutubxona fayllarini qidirish joriy katalogdan boshlanadi.

$ objdump -p asosiy | grep RPATH
RPATH.

Ushbu parametr tufayli dasturni ishga tushirishda muhit o'zgaruvchilarini o'zgartirishga hojat qolmaydi. Agar siz dasturni boshqa katalogga ko'chirsangiz va uni ishga tushirishga harakat qilsangiz, kutubxona fayli topilmasligi va yuklovchi xato xabarini ko'rsatishi aniq:

$mv asosiy..
$ ../asosiy
Birinchi funksiya...
Ikkinchi funksiya...
asosiy funksiyasi...

Shuningdek, yordamchi dastur yordamida ilovaga qaysi umumiy kutubxonalar kerakligini bilib olishingiz mumkin ldd:

$ ldd asosiy
linux-vdso.so.1 => (0x00007fffaddff000)
libhello.so.2 => ./libhello.so.2 (0x00007f9689001000)
libc.so.6 => /lib/libc.so.6 (0x00007f9688c62000)
/lib64/ld-linux-x86-64.so.2 (0x00007f9689205000)

Yakunida ldd har bir talab qilinadigan kutubxona uchun uning nomi va kutubxona faylining to'liq yo'li ko'rsatilgan, tizim sozlamalariga muvofiq belgilanadi.

Endi kutubxona fayllari tizimda qaerga joylashtirilishi kerakligi, yuklovchi ularni qaerdan topishga harakat qilishi va bu jarayonni qanday boshqarish haqida gapirish vaqti keldi.

Shartnomalarga ko'ra FHS (Fayl tizimi ierarxiyasi standarti) Tizimda kutubxona fayllarini saqlash uchun ikkita (kamida) katalog bo'lishi kerak:

/lib - bu erda /bin va /sbin dan dasturlarning ishlashi uchun zarur bo'lgan tarqatish to'plamining asosiy kutubxonalari to'plangan;

/usr/lib - bu erda /usr/bin va /usr/sbin ilovalari uchun zarur bo'lgan kutubxonalar saqlanadi;

Kutubxonalarga mos keladigan sarlavha fayllari /usr/include katalogida bo'lishi kerak.

Standart yuklovchi ushbu kataloglarda kutubxona fayllarini qidiradi.

Yuqorida sanab o'tilganlarga qo'shimcha ravishda, tizimda /usr/local/lib katalogi bo'lishi kerak - paketlarni boshqarish tizimini chetlab o'tib, foydalanuvchi tomonidan mustaqil ravishda joylashtirilgan kutubxonalar bo'lishi kerak (tarqatish to'plamiga kiritilmagan). Misol uchun, manbalardan tuzilgan kutubxonalar sukut bo'yicha ushbu katalogda bo'ladi (manbalardan o'rnatilgan dasturlar /usr/local/bin va /usr/local/sbin-ga joylashtiriladi, albatta, biz ikkilik taqsimotlar haqida gapiramiz). Bu holda kutubxonalarning sarlavha fayllari /usr/local/include ga joylashtiriladi.

Ba'zi tarqatishlarda (in ubuntu) yuklovchi /usr/local/lib katalogini ko'rish uchun sozlanmagan, shuning uchun foydalanuvchi kutubxonani manbadan o'rnatsa, tizim uni ko'rmaydi. Ushbu tarqatish tarqatish mualliflari tomonidan foydalanuvchini o'rnatishni o'rgatish uchun maxsus qilingan dasturiy ta'minot faqat paketlarni boshqarish tizimi orqali. Bu holatda qanday davom etish kerakligi quyida tavsiflanadi.

Aslida, kutubxona fayllarini topish jarayonini soddalashtirish va tezlashtirish uchun yuklovchi har safar kirishda yuqoridagi kataloglarga qaramaydi, balki /etc/ld.so.cache (kutubxona) faylida saqlangan maʼlumotlar bazasidan foydalanadi. kesh). Bu berilgan sonamega mos keladigan kutubxona fayli tizimning qayerda joylashganligi haqidagi ma'lumotlarni o'z ichiga oladi. Muayyan dastur uchun zarur bo'lgan kutubxonalar ro'yxatini (dasturning bajariladigan faylida ko'rsatilgan soname kutubxonalari ro'yxati) olgan yuklovchi /etc/ld.so.cache yordamida har bir kerakli kutubxona fayliga yo'lni aniqlaydi va uni yuklaydi. xotiraga. Bundan tashqari, yuklovchi LD_LIBRARY_PATH , LIBRARY_PATH tizim oʻzgaruvchilari va bajariladigan faylning RPATH maydonida keltirilgan kataloglarni koʻrib chiqishi mumkin (yuqoriga qarang).

Yordamchi dastur kutubxona keshini yangilab turish va boshqarish uchun ishlatiladi. ldconfig. Yugursa ldconfig hech qanday variantsiz, dastur buyruq satrida ko'rsatilgan kataloglarni, ishonchli kataloglarni /lib va ​​/usr/lib , faylda ko'rsatilgan kataloglarni ko'rib chiqadi /etc/ld.so.conf . Belgilangan kataloglarda topilgan har bir kutubxona fayli uchun soname o'qiladi, soname asosida ramziy havola yaratiladi va /etc/ld.so.cache ma'lumotlari yangilanadi.

Bunga ishonch hosil qilaylik:

$ls
salom.h libhello.so libhello.so.2.4.0.5 main.c
$
$ sudo ldconfig /full/path/to/dir/c/misol
$ls
salom.h libhello.so libhello.so.2 libhello.so.2.4.0.5 main main.c
$./asosiy
Birinchi funksiya...
Ikkinchi funksiya...
asosiy funksiyasi...

Birinchi qo'ng'iroq ldconfig biz kutubxonamizni keshga joylashtirdik, uni ikkinchi qo'ng'iroq bilan chiqarib tashladik. Kompilyatsiya qilishda asosiy variant o'tkazib yuborilganiga e'tibor bering -Wl,-rpath,., natijada yuklovchi kerakli kutubxonalarni faqat keshda qidirdi.

Endi kutubxonani manbadan o'rnatgandan so'ng, tizim uni ko'rmasa, nima qilish kerakligi aniq bo'lishi kerak. Avvalo, kutubxona fayllari bilan katalogga to'liq yo'lni qo'shishingiz kerak (sukut bo'yicha /usr/local/lib ) /etc/ld.so.conf fayliga. /etc/ld.so.conf formati - faylda kutubxonalarni qidirish uchun ikkita nuqta, bo'sh joy, tab yoki yangi qator bilan ajratilgan kataloglar ro'yxati mavjud. Keyin qo'ng'iroq qiling ldconfig hech qanday variantsiz, lekin superfoydalanuvchi huquqlari bilan. Hamma narsa ishlashi kerak.

Oxir-oqibat, keling, kutubxonalarning statik va dinamik versiyalari qanday birlashishi haqida gapiraylik. Haqiqiy savol nima? Yuqorida, kutubxona fayllarining qabul qilingan nomlari va joylashuvi haqida gapirganda, kutubxonaning statik va dinamik versiyalarining fayllari bir katalogda saqlanadi. Qanaqasiga gcc Biz qaysi turdagi kutubxonadan foydalanmoqchi ekanligimizni aniqlang? Odatiy bo'lib, dinamik kutubxona afzalroqdir. Agar bog'lovchi dinamik kutubxona faylini topsa, uni dasturning bajariladigan fayliga bog'lashdan tortinmaydi:

$ls
salom.h libhello.a libhello.so libhello.so.2 libhello.so.2.4.0.5 main.c
$ gcc -Wall -c main.c
$ gcc -o main main.o -L. -salom -Wl,-rpath,.
$ ldd asosiy
linux-vdso.so.1 => (0x00007fffe1bb0000)
libhello.so.2 => ./libhello.so.2 (0x00007fd50370b000)
libc.so.6 => /lib/libc.so.6 (0x00007fd50336c000)
/lib64/ld-linux-x86-64.so.2 (0x00007fd50390f000)
$ du -h asosiy
12K asosiy

Dasturning bajariladigan faylining hajmiga e'tibor bering. Bu mumkin bo'lgan minimaldir. Ishlatilgan barcha kutubxonalar dinamik ravishda bog'langan.

Mavjud gcc -statik variant- ilova uchun zarur bo'lgan barcha kutubxonalarning faqat statik versiyalaridan foydalanish bo'yicha bog'lovchiga ko'rsatma:

$ gcc -static -o main main.o -L. -salom
$ asosiy fayl
asosiy: ELF 64-bit LSB bajariladigan, x86-64, 1-versiya (GNU/Linux), statik bogʻlangan, GNU/Linux 2.6.15 uchun, ajratilmagan
$ ldd asosiy
dinamik bajariladigan fayl emas
$ du -h asosiy
728K asosiy

Bajariladigan faylning hajmi oldingi misolga qaraganda 60 baravar katta - standart til kutubxonalari faylga kiritilgan. C. Endi bizning ilovamiz katalogdan katalogga va hatto boshqa mashinalarga xavfsiz o'tkazilishi mumkin, salom kutubxona kodi fayl ichida, dastur butunlay avtonomdir.

Agar foydalanilgan kutubxonalarning faqat bir qismini statik ravishda bog'lash kerak bo'lsa-chi? Mumkin variant yechim kutubxonaning statik versiyasi nomini umumiy nomidan farqli qilish va dasturni kompilyatsiya qilishda biz bu safar qaysi versiyadan foydalanmoqchi ekanligimizni belgilang:

$ mv libhello.a libhello_s.a
$ gcc -o main main.o -L. -salom
$ ldd asosiy
linux-vdso.so.1 => (0x00007fff021f5000)
libc.so.6 => /lib/libc.so.6 (0x00007fd0d0803000)
/lib64/ld-linux-x86-64.so.2 (0x00007fd0d0ba4000)
$ du -h asosiy
12K asosiy

Libhello kutubxonasi kodining hajmi ahamiyatsiz bo'lgani uchun,

$ du -h libhello_s.a
4.0K libhello.a

natijada bajariladigan faylning o'lchami dinamik bog'lanish yordamida yaratilgan fayl hajmi bilan deyarli bir xil bo'ladi.

Xo'sh, ehtimol hammasi shu. Shu nuqtada o'qishni tugatgan barchaga katta rahmat.

GCC boshqa kompilyatorlardan unumdorlik jihatidan orqada qoladi, degan fikr keng tarqalgan. Ushbu maqolada biz maqbul ishlashga erishish uchun qanday asosiy GCC kompilyatorini optimallashtirishni qo'llash kerakligini aniqlashga harakat qilamiz.

GCCdagi standart variantlar qanday?

(1) Odatiy bo'lib, GCC "-O0" optimallashtirish darajasini ishlatadi. Bu aniq ishlash nuqtai nazaridan optimal emas va yakuniy mahsulotni kompilyatsiya qilish uchun tavsiya etilmaydi.
GCC kompilyatsiya qilinayotgan arxitekturani ”-march=native” varianti o'tkazilmaguncha tanimaydi. Odatiy bo'lib, GCC konfiguratsiya paytida o'rnatilgan opsiyadan foydalanadi. GCC konfiguratsiyasini bilish uchun quyidagilarni bajaring:

Bu shuni anglatadiki, GCC sizning variantlaringizga "-march=corei7" qo'shadi (agar boshqa arxitektura belgilanmagan bo'lsa).
X86 uchun GCC kompilyatorlarining aksariyati (64 bitli Linux uchun asosiy) berilgan variantlarga “-mtune=generic -march=x86-64” qo'shadi, chunki konfiguratsiyada arxitekturaga xos variantlar berilmagan. Siz har doim GCCni ishga tushirishda o'tgan barcha variantlarni, shuningdek uning ichki variantlarini buyruq bilan bilib olishingiz mumkin:

Natijada, odatda qo'llaniladi:

Foydalanish uchun arxitekturani belgilash ishlash uchun muhimdir. Faqatgina istisno, kutubxona funktsiyalarini chaqirish deyarli butun ishga tushirish vaqtini oladigan dasturlarni ko'rib chiqish mumkin. GLIBC ish vaqtida berilgan arxitektura uchun optimal funksiyani tanlashi mumkin. Shuni ta'kidlash kerakki, statik bog'langanda, ba'zi GLIBC funktsiyalari turli arxitekturalar uchun versiyalashtirilmaydi. Ya'ni, agar GLIBC funktsiyalarining tezligi muhim bo'lsa, dinamik yig'ish yaxshiroqdir..
(2) Odatiy bo'lib, 32 bit rejimida x86 uchun GCC kompilyatorlarining aksariyati x87 suzuvchi nuqta modelidan foydalanadi, chunki ular "-mfpmath=sse"siz sozlangan. Faqat GCC konfiguratsiyasida "--with-mfpmath=sse" bo'lsa:

kompilyator sukut bo'yicha SSE modelini ishlatadi.Boshqa barcha hollarda 32-bitli rejimda tuzilishga “-mfpmath=sse” variantini qo'shgan ma'qul.
Shunday qilib, tez-tez ishlatiladi:

32 bitli rejimda ”-mfpmath=sse” variantini qo'shish muhim! Istisno - konfiguratsiyasida "--with-mfpmath=sse" bo'lgan kompilyator.

32 bitli rejimmi yoki 64 bitmi?

32-bitli rejim odatda foydalaniladigan xotira hajmini kamaytirish va natijada u bilan ishlashni tezlashtirish uchun ishlatiladi (ko'proq ma'lumotlar keshga joylashtiriladi).
64 bitli rejimda (32 bitga nisbatan) mavjud umumiy registrlar soni 6 dan 14 gacha, XMM registrlari 8 dan 16 gacha ko'payadi. Shuningdek, barcha 64 bitli arxitekturalar SSE2 kengaytmasini qo'llab-quvvatlaydi, shuning uchun 64 bitli rejimda sizga kerak emas. “-mfpmath” parametrini = sse” qo‘shing.
Hisoblash vazifalari uchun 64 bitli rejimdan, mobil ilovalar uchun 32 bitli rejimdan foydalanish tavsiya etiladi.

Maksimal samaraga qanday erishish mumkin?

Ishlashni maksimal darajada oshirish uchun ma'lum variantlar to'plami yo'q, lekin GCCda sinab ko'rishga arziydigan ko'plab variantlar mavjud. Quyida “-O2” opsiyasiga nisbatan Intel Atom va 2-avlod Intel Core i7 protsessorlari uchun tavsiya etilgan variantlar va o‘sish prognozlari keltirilgan jadval mavjud. Prognozlar GCC 4.7 versiyasida tuzilgan muayyan vazifalar to'plami natijalarining o'rtacha geometrik qiymatiga asoslanadi. Bundan tashqari, kompilyator konfiguratsiyasi x86-64 generic uchun qilingan deb taxmin qiladi.
uchun samaradorlikni oshirish prognozi mobil ilovalar"-O2" ga nisbatan (faqat 32-bitli rejimda, chunki u mobil segment uchun asosiy hisoblanadi):

"-O2" ga nisbatan hisoblash vazifalari samaradorligini oshirish prognozi (64 bitli rejimda):
-m64 -Ofast -flto ~17%
-m64 -Ofast -flto -march=native ~21%
-m64 -Ofast -flto -march=native -funroll-loops ~22%

“-O2 -mfpmath=sse” opsiyalari bilan hisoblash vazifalari uchun 64-bitli rejimning 32-bitga nisbatan afzalligi ~5% ni tashkil qiladi.
Maqolaning barcha ma'lumotlari ma'lum bir ko'rsatkichlar to'plamining natijalariga asoslangan prognozdir.
Quyida maqolada ishlatiladigan variantlarning tavsifi keltirilgan. To'liq tavsif (ingliz tilida): http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Optimize-Options.html"
  • "-O3 -ffast-math" kabi "-Ofast" arifmetik hisoblar uchun yuqori darajadagi optimallashtirish va agressiv optimallashtirish imkonini beradi (masalan, haqiqiy qayta assotsiatsiya)
  • "-flto" o'zaro modul optimallashtirish
  • "-m32" 32 bitli rejim
  • "-mfpmath=sse" XMM registrlarini haqiqiy arifmetikada ishlatishga imkon beradi (x87 rejimida haqiqiy stek o'rniga)
  • "-funroll-loops" tsiklni ochish imkonini beradi

Transport logistikasi(turli transport turlarini tahlil qilish: afzalliklari, kamchiliklari)

Transport moddiy ishlab chiqarishning odamlar va yuklarni tashish bo'limidir. tuzilishida ijtimoiy ishlab chiqarish transport moddiy xizmatlar ishlab chiqarish sohasiga kiradi.

Ta'kidlanishicha, asosiy xom ashyo manbasidan yakuniy iste'molga qadar moddiy oqim yo'lidagi logistika operatsiyalarining muhim qismi turli xil texnologiyalar yordamida amalga oshiriladi. Transport vositasi. Ushbu operatsiyalarning qiymati logistika umumiy qiymatining 50% gacha.

Maqsadga ko'ra transportning ikkita asosiy guruhi ajratiladi: jamoat transporti - sanoat Milliy iqtisodiyot, bu esa iqtisodiyotning barcha tarmoqlari va aholining yuk va yoʻlovchi tashishga boʻlgan ehtiyojlarini qondiradi. Jamoat transporti aylanma sohasiga va aholiga xizmat qiladi. U ko'pincha asosiy yo'nalish deb ataladi (asosiy chiziq ba'zi tizimlarda, bu holda, aloqa tizimida asosiy, asosiy yo'nalish). Jamoat transporti tushunchasi o'z ichiga oladi temir yo'l transporti, suv transporti (dengiz va daryo), avtomobil, havo va quvur transporti).

Nodavlat transporti - ishlab chiqarish ichidagi transport, shuningdek notransport tashkilotlariga tegishli barcha turdagi transport vositalari.

Nodavlat transportida yuk tashishni tashkil etish sanoat logistikasini o'rganish predmeti hisoblanadi. Tarqatish kanallarini tanlash muammosi tarqatish logistikasi sohasida hal etiladi.

Shunday qilib, quyidagi asosiy transport turlari mavjud:

temir yo'l

ichki suv daryosi

avtomobilsozlik

havo

quvur liniyasi

Transport turlarining har biri logistika boshqaruvi nuqtai nazaridan o'ziga xos xususiyatlarga ega, logistika tizimida undan foydalanish imkoniyatini belgilaydigan afzallik va kamchiliklarga ega. Turli transport turlari transport kompleksini tashkil qiladi. Rossiyaning transport kompleksi uning hududida ro'yxatdan o'tgan yuridik va jismoniy shaxslar - transportning barcha turlari bo'yicha transport va ekspeditorlik faoliyatini amalga oshiradigan, temir yo'llar, avtomobil yo'llari va ulardagi inshootlarni, quvurlarni, ishlarni loyihalash, qurish, ta'mirlash va ta'mirlashni amalga oshiradigan tadbirkorlar tomonidan shakllantiriladi. navigatsiya qilinadigan gidrotexnik inshootlarni saqlash bilan bog'liq, suv va havo yo'llari xabarlar, ushlab turish ilmiy tadqiqot transport tizimi tarkibiga kiruvchi va transport vositalari ishlab chiqaruvchi korxonalar, shuningdek, transport jarayoni bilan bog‘liq boshqa ishlarni bajaruvchi tashkilotlar, xodimlarni o‘qitish. Rossiya TK 160 ming km dan ortiq asosiy temir yo'l va kirish yo'llari, 750 ming km asfaltlangan yo'llar, 1,0 million km dengiz tashish liniyalari, 101 ming km ichki yo'llardir. suv yo'llari, 800 ming km aviakompaniyalar. Ushbu kommunikatsiyalar orqali kuniga 4,7 million tonna yuk tashiladi (2000 yil ma'lumotlariga ko'ra), TKda 4 milliondan ortiq kishi ishlaydi, transportning mamlakat yalpi ichki mahsulotidagi ulushi qariyb 9% ni tashkil qiladi. Shunday qilib, transport mamlakatimiz iqtisodiyoti infratuzilmasi va butun ijtimoiy-ishlab chiqarish salohiyatining muhim qismidir.

Jadvalda. 1 (4, 295) Har xil transport turlarining qiyosiy logistik tavsiflari berilgan.

1-jadval Transport turlarining xususiyatlari

Transport turi

Afzalliklar

Kamchiliklar

temir yo'l

yuqori tashish qobiliyati va o'tkazish qobiliyati. Iqlim sharoitlaridan, yil va kun vaqtidan mustaqillik.

Yuk tashishning yuqori muntazamligi. Nisbatan past stavkalar; tranzit yuklar uchun sezilarli chegirmalar. Yuqori tezlik uzoq masofalarga tovarlarni yetkazib berish.

Cheklangan tashuvchilar soni. Ishlab chiqarish-texnik bazaga katta kapital qo'yilmalar. Yuqori material iste'moli va transportning energiya zichligi. Yakuniy savdo nuqtalari (iste'mol) uchun past mavjudligi.

Yukning etarlicha yuqori xavfsizligi.

Qit'alararo tashish imkoniyati. Uzoq masofalarga tashishning arzonligi. Yuqori tashish va tashish qobiliyati. Transportning past kapital zichligi.

Cheklangan transport.

Past etkazib berish tezligi (uzoq o'tish vaqti).

Geografik, navigatsiya va ob-havo sharoitlariga bog'liqlik.

Murakkab port infratuzilmasini yaratish zarurati.

Ichki suv (daryo)

Chuqur dengiz daryolari va suv havzalarida yuqori yuk tashish qobiliyati.

Transportning past narxi. Kam kapital zichligi.

Cheklangan transport. Kam etkazib berish tezligi.

Daryolar va suv omborlarining notekis chuqurligiga, navigatsiya sharoitlariga bog'liqlik. Mavsumiylik. Yuk tashishning ishonchliligi va xavfsizligi etarli emas.

avtomobilsozlik

Yuqori mavjudligi.

Uyma-uy yuklarni yetkazib berish imkoniyati

Yuqori manevrlik, moslashuvchanlik, dinamizm. Yuqori etkazib berish tezligi. Turli marshrutlar va etkazib berish sxemalaridan foydalanish imkoniyati.

Yukning yuqori xavfsizligi. Kichik partiyalarda yuklarni jo'natish imkoniyati.

Kam ishlash. Ob-havo va yo'l sharoitlariga bog'liqlik. uzoq masofalarga tashishning nisbatan yuqori narxi.

Atrof-muhit tozaligining etarli emasligi.

Havo

Yuk yetkazib berishning eng yuqori tezligi. Yuqori ishonchlilik.

Yukning eng yuqori xavfsizligi.

Eng qisqa transport yo'llari.

Tashishning yuqori narxi, boshqa transport turlari orasida eng yuqori ko'rsatkichlar. Tashishning yuqori kapital sig'imi, moddiy va energiya zichligi. Ob-havoga bog'liq. Geografik qulaylik yetarli emas.

quvur liniyasi

Arzon. Yuqori unumdorlik (o'tkazish qobiliyati). Yukning yuqori xavfsizligi. Kam kapital zichligi.

Cheklangan turdagi yuklar (gaz, neft mahsulotlari, emulsiyalar xomashyo). Kichik hajmdagi tashiladigan tovarlarning etarli darajada mavjud emasligi.

Shunday qilib, birinchi navbatda, logistika menejeri o'zining avtotransport parkini yaratish yoki yollangan transportdan (davlat yoki xususiy) foydalanishni hal qilishi kerak. Muqobilni tanlashda ular odatda ma'lum bir mezonlar tizimidan kelib chiqadi, ular quyidagilarni o'z ichiga oladi: O'zingizning avtoulov parkini yaratish va ishlatish xarajatlari. Transport, ekspeditorlik kompaniyalari va boshqa logistika vositachilarining transport xizmatlari uchun to'lov qiymati Tashish tezligi

Yuk tashish sifati (etkazib berish ishonchliligi, yuk xavfsizligi va boshqalar)

Aksariyat hollarda ishlab chiqaruvchi firmalar ixtisoslashgan transport kompaniyalari xizmatlariga murojaat qilishadi.