GCC در انبار هر توزیع گنجانده شده است لینوکسو قاعدتاً پشت ذهن نصب می شود. رابط GCC رابط استاندارد کامپایلر در پلت فرم یونیکس است که به ریشه های آن در اواخر دهه 60 و اوایل دهه 70 قرن گذشته باز می گردد - یک رابط خط فرمان. در آخرین ساعت مکانیسم تعامل با koristuvavach vyvodka به دقت احتمالی در این مورد عجله نکنید و با GCC (برای واضح بودن تعدادی ابزار اضافی و یک ویرایشگر متن راحت) ساده تر و پایین تر از IDE های بصری امروزی کار کنید. . نویسندگان مجموعه سعی کردند تا حد امکان فرآیند جمع آوری و ذخیره سازی افزونه ها را خودکار کنند. Koristuvach روی این برنامه کلیک می کند gcc، ارسال آرگومان های خط فرمان (گزینه ها و نام فایل ها) را تفسیر می کند و برای هر فایل ورودی، مشخصاً تا برنامه نویسی محلی، کامپایلر خود را راه اندازی می کند، سپس در صورت لزوم، gccاسمبلر و پیوند دهنده (لینکر) به طور خودکار انتخاب می شوند.

با این حال، کامپایلرها یکی از معدود برنامه های یونیکس برای هر نوع پسوند فایل هستند. با پسوند، GCC نشان می دهد که چه فایلی در مقابل آن قرار دارد و چه نیازهایی (می توان) با آن انجام داد. فایل های کد خروجی من سیپسوند guilty mothers .c در فیلم C++، به عنوان یک گزینه، .cpp، فایل های هدر من سی h، فایل های شی .o و غیره. Yaksto vikorystuvati به اشتباه گسترش یافته است، gccاگر به درستی اجرا نمی کنید (مدتی است منتظر بوده اید، بنابراین باید کار کنید).

بیایید به سراغ تمرین برویم. بیایید یک برنامه ساده بنویسیم، کامپایل و نهایی کنیم. ما اصلی نخواهیم بود، زیرا فایل خروجی نمونه ای از یک برنامه در mov است سیدر عوض بیایید یک فایل با این بسازیم:

/* سلام سی */

#عبارتند از

اصلی( خالی )
{

Printf("Hello World \n");

برگشت 0 ;

اکنون در katalosis با hello.c می توانید دستور را وارد کنید:

$gcc سلام.c

پس از چند ثانیه، فایل a.out در کاتالوگ ظاهر می شود:

$ls
a.out سلام.ج

این فایل تمام شده برنامه ما است. برای استراحت gccبه فایل خروجی نام a.out می دهد (از آنجایی که برای مدت طولانی این نام معنی داشت خروجی اسمبلر).

$file a.out
a.out: ELF 64 بیتی LSB قابل اجرا، x86-64، نسخه 1 (SYSV)، پیوندی پویا (از لبه های اشتراکی استفاده می کند)، برای گنو/لینوکس 2.6.15، بدون حذف

بیایید محصول نرم افزاری Viyshov را راه اندازی کنیم:

$./a.out
سلام دنیا


چرا لازم است مسیر فایل را به صراحت در دستور برای راه اندازی یک فایل از دایرکتوری جریان مشخص کنیم؟ کجا باید به فایلی که پیوند داده می‌شود، بدون دستورالعمل‌های صریح، پوسته، تفسیر دستورات، جستجوی فایل در فهرست‌ها، فهرستی از هر کار با استفاده از متغیر سیستمی PATH.

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

کاتالوگ های موجود در لیست با یک علامت دوتایی از هم جدا می شوند. هنگام جستجوی فایل‌ها، پوسته از طریق دایرکتوری‌ها به ترتیبی که در فهرست مرتب شده‌اند، نگاه می‌کند. برای umovchannyam، z mirkuvan bezpeki جریان کاتالوگ. در لیست گنجانده نشده است ، ظاهراً پوسته پرونده های پیچیده شده در هیچ کجا پیدا نمی شود.

چه چیزی توصیه نمی شود اضافه شود؟ در PATH؟ مهم این است که در زندگی واقعی سیستم مالی ثروتمند، روزی نوعی فرد منزجر کننده وجود داشته باشد که بتوان آن را در فهرست غیرقانونی در دسترس قرار داد. برنامه بدبا نام فایل کامپایل شده که با نام برخی از دستورات که اغلب توسط مدیر محلی با حقوق سوپرخبرنگار فراخوانی می شود اجتناب می شود ... به هر نحوی پاسخ داده خواهد شد. در بالای لیست کاتالوگ ها قرار بگیرید.


سودمند فایلنمایش اطلاعات در مورد نوع (همانطور که توسط سیستم مشاهده می شود) فایل منتقل شده به خط فرمان؛ برای انواع فایل های خاص، هر چیزی را نمایش دهید. اطلاعات تکمیلیچه چیزی را به جای فایل قرار دهیم

$file hello.c
hello.c: متن برنامه ASCII C
$file annotation.doc
annotation.doc: CDF V2 Document، Little Endian، سیستم عامل: Windows، نسخه 5.1، صفحه: 1251، نویسنده: MIH، الگو: Normal.dot، آخرین ذخیره شده توسط: MIH، شماره ویرایش: 83، نام ایجاد کننده برنامه: Microsoft آفیس ورد، کل زمان ویرایش: 09:37:00، آخرین چاپ: پنجشنبه 22 ژانویه 07:31:00 2009، زمان/تاریخ ایجاد: دوشنبه 12 ژانویه 07:36:00 2009، آخرین زمان/تاریخ ذخیره شده: پنجشنبه 22 ژانویه 07: 34:00 2009، تعداد صفحات: 1، تعداد کلمات: 3094، تعداد کاراکترها: 17637، امنیت: 0

اکسل، نیرو و هر چیزی که از کیستوواچ برای خشک کردن موفق نیاز دارید. gcc :)

نام فایل خروجی (و همچنین هر فایل دیگری که در حال تشکیل است) gcc) برای کمک قابل تغییر است گزینه -o:

$ gcc -o سلام hello.c
$ls
سلام سلام.ج
$./سلام
سلام دنیا


در برنامه کاربردی، تابع main() که می چرخد ​​مقدار غیر ضروری 0 را تولید می کند. در سیستم های یونیکس مانند، پس از اتمام کار برنامه، مرسوم است که یک عدد صحیح را به پوسته فرمان برگردانید - صفر برای تکمیل موفقیت آمیز، در غیر این صورت. مفسر پوسته به طور خودکار مقدار وسط قابل تغییر را از آنها حذف می کند؟ . آیا می توانید در عوض با استفاده از دستور اضافی echo$ به آن نگاه کنید؟ :

$./سلام
سلام دنیا
$echo$؟
0

گفته شد که gccاین برنامه برای خودکارسازی فرآیند کامپایل طراحی شده است. بیایید ببینیم در نتیجه شکست دستور gcc hello.c چه اتفاقی می افتد.

فرآیند کامپایل را می توان به 4 مرحله اصلی تقسیم کرد: پردازش پیش پردازنده، کامپایل لیزری، مونتاژ، پیوند.

گزینه ها gccشما مجاز به قطع فرآیند در هر یک از این مراحل هستید.

پیش پردازنده اکنون فایل خروجی را قبل از کامپایل آماده می کند - نظرات را تأیید می کند، به جای فایل های هدر اضافه می کند (دستورالعمل پیش پردازنده #include)، ایجاد ماکروها (ثابت نمادی، دستورالعمل پیش پردازنده #define) را پیاده سازی می کند.

داشتن زمان کوتاه گزینه -Eفعالیت های بیشتر gccمی توانید قطع کنید و به فایل پردازش شده توسط پیش پردازنده نگاه کنید.

$ gcc -E -o hello.i hello.c
$ls
hello.c سلام.i
$ کمتر سلام.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 بدون امضا char __u_char;
typedef بدون علامت کوتاه int __u_short;
typedef بدون امضا int __u_int;
. . .
extern int printf (__const char *__restrict __format, ...);
. . .
شماره 4 "hello.c" 2
اصلی (باطل)
{
printf("Hello World\n");
بازگشت 0;
}

پس از پردازش توسط پیش پردازنده، متن خروجی برنامه ما متورم شد و به راحتی قابل خواندن نبود. کدی که فقط با انگشتان خود تایپ کردیم تا چندین ردیف در اطراف فایل پخش شد. دلیل - اتصال به فایل هدر کتابخانه استاندارد سی. فایل هدر stdio.h خود شامل موارد مختلفی است و همچنین نیاز به گنجاندن سایر فایل های هدر دارد.

بازگشت به فایل توسعه یافته hello.i. به خاطر لذت gccپسوند .i مربوط به فایل هایی با کد خروجی من است سیپردازشی را از پیش پردازنده دریافت نمی کند. این فایل ها بدون پیش پردازنده کامپایل می شوند:

$ gcc -o سلام سلام.i
$ls
سلام سلام.c سلام.i
$./سلام
سلام دنیا

پس از پیش پردازش، مرحله تدوین فرا می رسد. کامپایلر متن خروجی یک برنامه سطح بالا را به کد اسمبلر تبدیل می کند.

معنای کلمه تالیف نامشخص است. برای مثال، ویکی‌پدیا، با تکیه بر استانداردهای بین‌المللی، احترام می‌گذارد که کامپایل عبارت است از «تبدیل یک برنامه کامپایلر متن خروجی هر برنامه، نوشته شده توسط یک برنامه سطح بالا، به زبانی نزدیک به زبان ماشین، که کد " در اصل، برای ما مهم است که نزدیک شویم، زبان اسمبلی در واقع به زبان ماشین نزدیک تر است، پایین تر سی. اما در زندگی روزمره تحت کامپایل، اغلب درک می شود که این به سادگی عملیاتی است که کد خروجی برنامه ای مانند برنامه نویسی من را از کد کامپایل شده تبدیل می کند. این فرآیندی است که شامل تمام مراحل زیر است که ممکن است کامپایل نیز نامیده شود. در این متن نیز چنین ابهامی وجود دارد. از طرف دیگر، عملیات تبدیل متن خروجی یک برنامه به کد اسمبلر من را می توان با ترجمه کلمه تعریف کرد - "تبدیل برنامه ای که توسط یکی از برنامه های ما به برنامه دیگری و صادقانه بگویم ابتدا معادل آن" .

خاموش کردن فرآیند ایجاد فایل کامپایل شده پس از تکمیل شدن کامپایل اجازه می دهد گزینه ها:

$ gcc -S hello.c
$ls
hello.c سلام.s
$file hello.s
hello.s: متن برنامه اسمبلر ASCII
$ کمتر hello.s
فایل "hello.c"
بخش .rodata
LC0:
.string "Hello World"
متن
.globl اصلی
اصلی را تایپ کنید، @function
اصلی:
pushl %ebp
movl %esp، %ebp
andl -16 دلار، %esp
زیر 16 دلار، %esp
movl $.LC0، (%esp)
تماس قرار می دهد
movl $0، %eax
ترک کردن
ret
.سایز اصلی، .-اصلی


کاتالوگ دارای یک فایل hello.s است که برای پیاده سازی برنامه اسمبلر در نظر گرفته شده است. به حساب خود بازگردید، نام فایل خروجی را برای کمک تنظیم کنید گزینه -oمن به این مکان نیاز نداشتم، gccبه طور خودکار آن را تولید می کند و پسوند .c را در نام فایل خروجی با .s جایگزین می کند. برای اکثر عملیات های اساسی gccنام فایل خروجی با استفاده از روش جایگزینی مشابه تشکیل شده است. پسوند .s برای فایل هایی با کد خروجی اسمبلر استاندارد است.

می توانید کد متصل شده را از فایل hello.s استخراج کنید:

$ gcc -o سلام hello.s
$ls
سلام سلام.ج سلام.s
$./سلام
سلام دنیا

مرحله بعدی عملیات اسمبلی، تبدیل کد اسمبلر به کد ماشین است. نتیجه عملیات یک فایل شی است. فایل شی شامل بلوک‌هایی از کد ماشین آماده برای انتشار، بلوک‌های داده، و همچنین فهرستی از تخصیص فایل عملکرد و تغییرات خارجی است ( جدول نمادها ، مگر اینکه آدرس های مطلق را در تابع داده مشخص کرده باشید. فایل شی را نمی‌توان مستقیماً در ویکی راه‌اندازی کرد، اما بعداً (در مرحله پیوند) می‌توان آن را با فایل‌های شی دیگر ادغام کرد (در این صورت، بسته به جدول نمادها، محاسبات و پر کردن آدرس‌ها، عطسه بین فایل‌ها انجام می‌شود. نظرسنجی متقابل). گزینه gcc-c، پس از اتمام مرحله مونتاژ، فرآیند را رد می کند:

$ gcc -c hello.c
$ls
hello.c سلام.o
$file hello.o
hello.o: ELF 64 بیتی LSB قابل جابجایی، x86-64، نسخه 1 (SYSV)، بدون حذف

برای فایل های شی، پسوند استاندارد .o پذیرفته می شود.

پس از حذف فایل شی hello.o، آن را به لینک دهنده منتقل کنید، سپس آدرس ها را محاسبه کنید، کد راه اندازی و خاتمه برنامه، کد فراخوانی توابع کتابخانه را اضافه کنید و در نتیجه آماده کامپایل برنامه هستیم. فایل.

$ gcc -o سلام hello.o
$ls
سلام سلام.c hello.o
$./سلام
سلام دنیا

کسانی که ما را یکباره به دست آورده اند (vernishe gccبرای ما کار کرده است) و مرحله باقی مانده - پیوند (پیوند، ترکیب) را جایگزین می کند.

خوب، شاید در مورد مجموعه و این همه. حالا بیایید ببینیم چه چیزی به نظر یک گزینه مهم است gcc.

گزینه -I way/to/catalogue/with/header/files - ورودی های دایرکتوری را به لیست مسیرها در جستجوی فایل های هدر اضافه می کند. کاتالوگ، موارد اضافی اختیاری -منابتدا بررسی می شود، سپس جستجو در دایرکتوری های سیستم استاندارد ادامه می یابد. گزینه چیست؟ -منبرگردان، کاتالوگ های مشخص شده توسط آنها در سمت راست مشاهده می شود، جهان اکنون یک گزینه دارد.

گزینه -دیوار- نمایش پیشرفت‌ها، اصلاحات احتمالی در کد که از کامپایل برنامه‌ها فراتر نمی‌رود یا به صلاحدید کامپایلر باعث می‌شود تا زمانی که این مشکلات و سایر مشکلات برطرف شود. آن مهم است گزینه korisna، خرده فروشان gccاول koristuvatsya او را توصیه کنید. به عنوان مثال، زمانی که می خواهید فایل زیر را کامپایل کنید، مقدار از قبل نشان داده می شود:

1 /* remark.c */
2
3 ایستا بین المللی k = 0;
4 ایستا بین المللیل( بین المللیآ)؛
5
6 اصلی ()
7 {
8
9 بین المللیآ؛
10
11 بین المللیقبل از میلاد مسیح؛
12
13 ب + 1;
14
15 b = c;
16
17 بین المللی*پ؛
18
19 b = * p;
20
21 }


$ gcc -o remark remark.c
$ gcc -Wall -o remark remark.c
remark.c:7: warning: نوع پیش‌فرض بازگشت به 'int'

remark.c:13: warning: بیانیه بدون تأثیر
remark.c:9: warning: متغیر "a" استفاده نشده
remark.c:21: warning: کنترل به پایان عملکرد non-void می رسد
remark.c: در سطح بالا:
remark.c:3: warning: "k" تعریف شده اما استفاده نشده است
remark.c:4: warning: "l" "ایستا" را اعلام کرد اما هرگز تعریف نشد
remark.c: در تابع 'main':
remark.c:15: warning: "c" در این تابع بدون مقدار اولیه استفاده می شود
remark.c:19: warning: در این تابع از "p" به صورت غیر اولیه استفاده می شود

گزینه -خطا- او در حال انجام مجدد همه ترتیبات برای اصلاح است. هنگامی که تاخیر ظاهر می شود، روند کامپایل را قطع می کند. Vikorist عمیقاً درگیر است گزینه-دیوار.

$ gcc -خطا -o remark remark.c
$ gcc -خطا -Wall -o remark remark.c
cc1: هشدارهایی که به عنوان خطا در نظر گرفته می شوند
remark.c:7: error: نوع پیش فرض را به 'int' برگردانید
remark.c: در تابع 'main':
remark.c:13: error: عبارت بدون اثر
remark.c:9: خطا: متغیر "a" استفاده نشده

گزینه -g- اطلاعات لازم برای کار ویرایشگر را در فایل کامپایل شده قرار می دهد gdb. وقتی هر پروژه ای با نیت رونق بیشتر شکل می گیرد، گزینه -gباید هم در مرحله کامپایل و هم در مرحله پیوند فعال شود.

گزینه های -O1، -O2، -O3- سطح بهینه سازی را برای کد تولید شده توسط کامپایلر تنظیم کنید. با افزایش تعداد، سطح بهینه سازی افزایش می یابد. این گزینه را می توان در چنین برنامه ای استفاده کرد.

فایل خروجی:

/* circle.c */

اصلی( خالی )
{

بین المللیمن؛

برای(i = 0؛ i< 10 ; ++i)
;

برگشتمن؛

کامپایل با بهینه سازی برابر برای پردازش:

$ gcc -S circle.c
$less circle.s
فایل "circle.c"
متن
.globl اصلی
اصلی را تایپ کنید، @function
اصلی:
pushl %ebp
movl %esp، %ebp
زیر 16 دلار، %esp
movl $0, -4 (%ebp)
jmp .L2
L3:
addl $1, -4 (%ebp)
.L2:
cmpl $9, -4 (%ebp)
jle.L3
movl -4(%ebp)، %eax
ترک کردن
ret
.سایز اصلی، .-اصلی
.ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
.section .note.GNU-stack,""@progbits

کامپایل با حداکثر سطح بهینه سازی:

$ gcc-S-O3 circle.c
$less circle.s
فایل "circle.c"
متن
.p2align 4.15
.globl اصلی
اصلی را تایپ کنید، @function
اصلی:
pushl %ebp
movl 10 دلار، %eax
movl %esp، %ebp
popl %ebp
ret
.سایز اصلی، .-اصلی
.ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
.section .note.GNU-stack,""@progbits

در مورد دیگر، در کد استخراج شده هیچ تنشی در هیچ چرخه ای وجود ندارد. در واقع، مقادیر i را می توان در مرحله کامپایل که کامپایل شد محاسبه کرد.

متأسفانه، برای پروژه های واقعی تفاوت در بهره وری در سطوح مختلف بهینه سازی عملاً قابل توجه نیست.

گزینه -O0- به هر بهینه سازی کد اشاره دارد. این گزینه در مرحله تنظیم برنامه مورد نیاز است. همانطور که در بالا نشان داده شد، بهینه سازی می تواند منجر به تغییر در ساختار برنامه ها تا حد ناشناخته شود، ارتباط بین کد کامپایل شده و خروجی آشکار نخواهد بود و ظاهراً در نهایت توسعه برنامه ها غیرممکن خواهد بود. وقتی گزینه فعال است -g، توصیه می شود روشن شود -O0.

گزینه -Os- بهینه سازی را برای کارایی کد و اندازه فایل موجود مشخص می کند. بنابراین بهره وری برنامه ها برابر با بهره وری کد کامپایل شده در حین کامپایل با بهینه سازی برابر مشخص شده در محاسبات خواهد بود.

گزینه -مارچ = معماری- معماری هدف پردازنده را تنظیم می کند. لیست معماری های پشتیبانی شده بزرگ است، به عنوان مثال، برای پردازنده های خانواده اینتل/AMDمی تواند قرار گیرد i386, پنتیوم, پرسکات, opteron-sse3و غیره. کاربران توزیع های باینری مسئول این واقعیت هستند که برای عملکرد صحیح یک برنامه با این گزینه، لازم است که تمام کتابخانه های متصل شده با این گزینه کامپایل شوند.

گزینه های ارسال شده به پیوند دهنده در زیر مورد بحث قرار خواهند گرفت.

اضافی کوچک:

گفته شد که gccنوع (فیلم) فایل های منتقل شده از این پسوند را نشان می دهد و متناسب با نوع حدس زده شده (فیلم)، روی آنها کار کنید. گواتر Koristuvach ایجاد گسترده فایل‌ها را دنبال می‌کند و آن‌ها را به دلخواه انتخاب می‌کند gcc. در عمل gccمی توانید فایل هایی با نام های سفارشی اضافه کنید. گزینه gcc-xبه شما این امکان را می دهد که برنامه نویسی فایل هایی که کامپایل می شوند را به صراحت مشخص کنید. این گزینه به گونه ای گسترش می یابد که تمام فایل های منتقل شده به فرمان را پوشش دهد (تا زمانی که گزینه ظاهر شود -ایکس). آرگومان های گزینه ممکن:

c-header c-cpp-output

c++ c++-header c++-cpp-output

هدف-c هدف-c-هدر هدف-c-cpp-خروجی

هدف-c++ هدف-c++-هدر هدف-c++-cpp-خروجی

اسمبلر اسمبلر-با-cpp

آدا

f77 f77-cpp-input

f95 f95-cpp-input

جاوا

ممکن است معنای استدلال ها از نوشته آنها قابل درک باشد (اینجا cppنیازی به انتظار نیست تا C++، این فایل کد خروجی (پشت پردازش پیش پردازنده) است. بیایید دوباره بررسی کنیم:

$mv hello.c hello.txt
$ gcc -Wall -x c -o hello hello.txt
$./سلام
سلام دنیا

تالیف جداگانه

نقطه قوت حرکت C/C++امکان جداسازی کد خروجی یک برنامه از چندین فایل وجود دارد. بیشتر می توان گفت - امکان تالیف جداگانه اساس یک زبان است، بدون آن یک ویکورستان مؤثر نخواهد بود. سیغیر قابل تصور نیست برنامه نویسی چند فایل خود به شما امکان پیاده سازی را می دهد سیپروژه های بزرگ، به عنوان مثال، مانند لینوکس(اینجا زیر کلمه لینوکسبه عنوان یک هسته و یک سیستم احتراق در نظر گرفته می شود). کامپایل چه چیزی به یک برنامه نویس می دهد؟

1. به شما امکان می دهد کد برنامه (پروژه) خود را برای خواندن آسان تر کنید. فایل خروجی برای ده ها صفحه عملاً نامشهود می شود. با توجه به منطق (تفکر شده) ، شکستن آن به تعدادی قطعات کوچک (پوست در یک فایل جداگانه) بسیار ساده تر خواهد بود که در پیچیدگی پروژه قرار گیرد.

2. به شما این امکان را می دهد که ساعت کامپایل مجدد یک پروژه را سرعت بخشید. اگر تغییرات در یک فایل انجام شود، کامپایل مجدد کل پروژه معنی ندارد، کافی است فقط فایل را برای تغییرات مجدد کامپایل کنید.

3. اجازه می دهد تا کار روی یک پروژه بین چند کارگر تقسیم شود. هر برنامه نویسی سهم خود را در پروژه ایجاد می کند و به آن کمک می کند، و در مقطعی امکان جمع آوری (انتخاب مجدد) تمام کارهایی که به محصول نهایی می رسد وجود خواهد داشت.

4. بدون تالیف جداگانه، هیچ کتابخانه ای وجود نخواهد داشت. برای کتابخانه های اضافی، کد دوباره بررسی شده و به آن گسترش یافته است C/C++علاوه بر این، یک کد باینری، که از یک سو به توسعه دهندگان اجازه می دهد تا مکانیزم ساده ای برای گنجاندن آن در برنامه های خود ارائه دهند و از سوی دیگر، جزئیات پیاده سازی خاصی را از آنها دریافت کنند. هنگام کار بر روی یک پروژه، ابتدا باید به آن فکر کنید، و چرا از آنچه قبلاً جمع آوری کرده اید به چیزی نیاز ندارید؟ آیا می توانید آن را از پشت ببینید و بخشی از کد را به عنوان یک کتابخانه مرتب کنید؟ به نظر من، این رویکرد اساسا زندگی را آسان تر می کند و در زمان زیادی صرفه جویی می کند.

شورای همکاری خلیج فارسبدیهی است که از کامپایل جداگانه پشتیبانی می کند و بر نیاز به برخی از درج های ویژه تأکید می کند. Zagalom، همه چیز بسیار ساده است.

محور یک قنداق عملی است (البته قوی تر و هوشمندتر).

مجموعه ای از فایل های کد خروجی:

/* main.c */

#عبارتند از

#include "first.h"
#include "second.h"

بین المللیاصلی( خالی )
{

اولین()؛
دومین()؛

Printf("عملکرد اصلی...\n");

برگشت 0 ;


/* first.h */

خالیاولین( خالی );


/* first.c */

#عبارتند از

#include "first.h"

خالیاولین( خالی )
{

Printf("اولین تابع... \n");


/* second.h */

خالیدومین( خالی );


/* second.c */

#عبارتند از

#include "second.h"

خالیدومین( خالی )
{

Printf("تابع دوم... \n");

scho محور Zagalom maєmo:

$ls
اول.ج اول.ساعت اصلی.ج دوم.ج دوم.س

تمام این سلطه را می توان در یک دستور کامپایل کرد:

$ gcc -Wall -o main main.c first.c second.c
$./اصلی
اولین تابع ...
تابع دوم ...
عملکرد اصلی ...

اما به جز کدهای ساختاریافته تر و خواناتر که در چندین فایل توزیع شده است، پاداش عملی به ما نمی دهد. تمام مزایای ذکر شده در بالا هنگام استفاده از چنین رویکردی قبل از تدوین ظاهر می شود:

$gcc-Wall-c main.c
ابتدا $gcc-Wall-c.c
$gcc-Wall-c second.c
$ls
اول.ج اول ساعت اول.و اصلی.ج اصلی.و دوم.ج دوم.س دوم.او
$ gcc -o main main.o first.o second.o
$./اصلی
اولین تابع ...
تابع دوم ...
عملکرد اصلی ...

چه چیزی به دست آوردیم؟ از فایل خروجی پوست (کامپایل شده با گزینه ) فایل شی را استخراج کرد. سپس فایل های شی در یک بسته فشرده ترکیب شدند. تعداد کل تیم ها gccموارد بیشتری وجود دارد، اما هیچ کس پروژه هایی را به صورت دستی انتخاب نمی کند، که برای آنها ابزارهای انتخاب وجود دارد (محبوب ترین ساختن). با استفاده از ابزارهای انتخابی، تمام بیش از حد بیمه بیش از یک تدوین جداگانه آشکار می شود.

غذا مقصر است: پیوند دهنده چگونه می تواند فایل های شی را جمع آوری کند که آدرس تماس ها را به درستی محاسبه می کند؟ علائم نشان می دهد که فایل second.o حاوی کد تابع second() است و کد فایل main.o حاوی کد تابع second() است؟ به نظر می رسد همه چیز ساده است - در فایل شیء نامیده می شود جدول نمادها ، که شامل نام موقعیت های مختلف کد (توابع و تغییرات خارجی) است. پیوند دهنده به جدول نمادهای فایل شی پوست نگاه می کند، به دنبال موقعیت های مخفی (با اجتناب از نام ها) می گردد، که در آن مکان واقعی کد تابع (یا بلوک های داده) را که در حال جستجو هستند و، بدیهی است، در آنجا می یابد. تغییر در آدرس لینک فایل کامپایل شده است.

می توانید جدول نمادها را با استفاده از یک ابزار اضافی مشاهده کنید نانومتر.

$nm main.o
تو پرشا
00000000 T اصلی
U قرار می دهد
U دوم
$nm first.o
00000000 T ابتدا
U قرار می دهد
$nm second.o
U قرار می دهد
00000000 T ثانیه

ظاهر عبارت puts استفاده از تابع کتابخانه استاندارد printf() را توضیح می دهد که در مرحله کامپایل به puts() تبدیل شد.

جدول نمادها در اشیاء و در فایل قالب بندی ثبت می شود:

$nm اصلی
08049f20d_DYNAMIC
08049ff4 d _GLOBAL_OFFSET_TABLE_
080484fc R_IO_stdin_used
w_Jv_RegisterClasses
08049f10 d __CTOR_END__
08049f0c d __CTOR_LIST__
08049f18 D __DTOR_END__
08049f14 d __DTOR_LIST__
08048538 r __FRAME_END__
08049f1c d __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_handle
w __gmon_start__
080484aa T __i686.get_pc_thunk.bx
08049f0c d __init_array_end
08049f0c d __init_array_start
08048440 T __libc_csu_fini
08048450 T __libc_csu_init
U [ایمیل محافظت شده]@GLIBC_2.0
0804a014 A_edata
0804a01c A_end
080484dc T_fini
080484f8 R_fp_hw
080482b8 T_init
08048330 T_start
0804a014 b تکمیل شد.7021
0804a00c W data_start
0804a018 b dtor_idx.7023
ابتدا 0804840c T
080483c0 t frame_dummy
080483e4 T اصلی
U [ایمیل محافظت شده]@GLIBC_2.0
08048420 T ثانیه

فعال کردن جدول نمادها برای فایل های به هم پیوسته برای عملیات ساده ضروری است. در اصل، شما واقعاً به هیچ نرم افزاری برای جادوگری نیاز ندارید. برای فایل های لینک شده برنامه های واقعیبه دلیل اهمیت فوق العاده توابع و تغییرات خارجی که تعدادی از کتابخانه های مختلف را پوشش می دهند، جدول نمادها بسیار بزرگ می شود. برای کوتاه کردن اندازه فایل خروجی، می توانید آن را به سرعت حذف کنید گزینه gcc-s.

$ gcc -s -o main main.o first.o second.o
$./اصلی
اولین تابع ...
تابع دوم ...
عملکرد اصلی ...
$nm اصلی
nm: اصلی: بدون علامت

لازم به ذکر است که در حین ترکیب، پیوند دهنده هنگام فراخوانی تابع، متن را بررسی نمی کند و نوع مقداری که در حال چرخش است و نوع و تعداد پارامترهای پذیرفته شده (و همچنین نشانه ای برای گرفتن چنین اطلاعاتی نیست). تمام تأیید صحت کلیک ها ممکن است در مرحله جمع آوری انجام شود. برای برنامه نویسی چند فایلی باید از مکانیزم فایل های هدر فیلم استفاده کرد سی.

کتابخانه ها

کتابخانه - در حرکت سی، فایل حاوی کد شی است که می تواند در مرحله پیوند به برنامه حاوی کتابخانه اضافه شود. در واقع، یک کتابخانه مجموعه ای از فایل های شی به طور خاص مرتب شده است.

هدف کتابخانه ها ارائه یک مکانیسم استاندارد برای بازنگری کد در اختیار برنامه نویس است و مکانیزم آن ساده و قابل اعتماد است.

از نظر سیستم عامل و نرم افزارهای کاربردی کتابخانه ها وجود دارد ایستا і در حال جدا شدن هستند (پویا ).

کد کتابخانه های استاتیک قبل از اینکه بقیه لینک شوند در آرشیو فایل پیوندی گنجانده شده است. به نظر می رسد که کتابخانه به فایل "هارد سیمی" شده است و کد کتابخانه در کد فایل "ریخته می شود". این برنامه، مانند کتابخانه های استاتیک Vikorist، مستقل است و تقریباً روی هر رایانه ای با معماری و سیستم عامل مناسب قابل اجرا است.

کد کتابخانه ای که توسط سیستم عامل به اشتراک گذاشته می شود، به کد برنامه دسترسی پیدا می کند و به آن متصل می شود و برنامه در حین اجرای آن دنبال می شود. قبل از ذخیره فایل برنامه، کد کتابخانه پویا گنجانده نشده است؛ در هنگام کامپایل فایل، تنها فایل ارسال شده به کتابخانه گنجانده می شود. در نتیجه، برنامه کتابخانه vikory که جدا شده است دیگر مستقل نیست و فقط می تواند با موفقیت در سیستمی که کتابخانه در آن نصب شده است راه اندازی شود.

پارادایم کتابخانه هایی که از هم جدا می شوند سه مزیت اصلی دارد:

1. حجم فایلی که ذخیره می شود بسیار کوتاه است. در سیستمی که شامل فایل های باینری خصوصی که حاوی همان کد هستند، نیاز به ذخیره یک کپی از این کد برای هر فایل کامپایل شده وجود دارد.

2. کد کتابخانه ای که به اشتراک گذاشته می شود با چندین اضافات اضافی اصلاح می شود تا در یک مثال در RAM ذخیره شود (در واقعیت، به این سادگی نیست...)، در نتیجه، تقاضای سیستم برای RAM موجود کوتاه می شود.

3. هر زمان که در کد کتابخانه مربوط به آنها تغییراتی ایجاد می شود، نیاز به انتخاب مجدد فایل الحاقی وجود دارد. کد کتابخانه پویا را تغییر داده و تصحیح کنید تا به طور خودکار در برنامه پوست که vikorist است ظاهر شود.

بدون پارادایم کتابخانه ها به اشتراک گذاشته شده، هیچ توزیع از پیش کامپایل شده (دودویی) وجود نخواهد داشت. لینوکس(هرگز چنین اتفاقی نیفتاده است). اندازه توزیع را تصور کنید که هر فایل باینری آن حاوی کد کتابخانه استاندارد است سی(و تمام کتابخانه های دیگری که متصل هستند). بنابراین واضح است که پس از حذف یک نشت بحرانی در یکی از کتابخانه های پرکاربرد، باید برای به روز رسانی سیستم کار کرد.

الان زیاد تمرین نیست

برای مثال، در اینجا مجموعه ای سریع از فایل های خروجی از مثال جلو آمده است. در کتابخانه ای که خود طراحی کرده ایم، کد (پیاده سازی) توابع () first و second را قرار می دهیم.

لینوکس یک طرح نامگذاری برای فایل های کتابخانه ای اتخاذ کرده است (اگرچه همیشه اینطور نیست) - نام فایل کتابخانه با پیشوند lib شروع می شود، پس از آن نام کتابخانه و در نهایت پسوند. بایگانی ) - برای یک کتابخانه استاتیک، .so ( شی مشترک ) - برای یک کتابخانه جداگانه (پویا)، پس از گسترش از طریق یک نقطه، ارقام شماره نسخه تغییر می کند (فقط برای یک کتابخانه پویا). نامی که نمایانگر کتابخانه فایل هدر است (نام دوباره) نام کتابخانه (بدون پیشوند و نسخه) و پسوند .h است. به عنوان مثال: libogg.a، libogg.so.0.7.0، ogg.h.

بیایید یک کتابخانه استاتیک روی cob ایجاد کنیم.

توابع first() و second() به کتابخانه libhello ما اضافه می شوند. نام فایل کتابخانه بدیهی است libhello.a خواهد بود. کتابخانه ها فایل هدر hello.h را تنظیم می کنند.

/* سلام */

خالیاولین( خالی );
خالیدومین( خالی );

بدیهی است که ردیف ها:

#include "first.h"


#include "second.h"

در فایل های main.c، first.c و second.c باید آن را با:

#شامل "hello.h"

خب، حالا بیایید دنباله دستورات زیر را معرفی کنیم:

ابتدا $gcc-Wall-c.c
$gcc-Wall-c second.c
$ ar crs libhello.a اول.o دوم.o
$file libhello.a
libhello.a: آرشیو فعلی

همانطور که گفته شد - یک کتابخانه مجموعه ای از فایل های شی است. دو تیم اول این فایل های شی را ایجاد کردند.

در مرحله بعد، باید فایل های شی را برای مجموعه بنویسید. آرشیو برای چه کسانی استفاده می شود؟ ar- این ابزار تعدادی فایل را به یکی می چسباند، در حالی که استخراج بایگانی ها شامل اطلاعات لازم برای به روز رسانی (دریافت) هر فایل جداگانه (از جمله ویژگی های مالکیت، دسترسی، زمان) است. هر نوع "فشرده سازی" به جای بایگانی یا تبدیل دیگر داده هایی که ذخیره می شود انجام نخواهد شد.

گزینه با آرنام- ایجاد بایگانی، از آنجایی که بایگانی با arname ایجاد نمی شود، در غیر این صورت فایل ها به آرشیو واقعی اضافه می شوند.

گزینه r- حالت به روز رسانی بایگانی را تنظیم می کند، به طوری که در آرشیو فایل با نام های مشخص شده از قبل موجود است و حذف نمی شود و فایل جدید به انتهای آرشیو اضافه می شود.

گزینه ها- فهرستی را به آرشیو اضافه می کند (به روز می کند). این نوع فهرست بایگانی دارای جدولی است که در آن برای هر فایل موجود در فایل‌های آرشیو شده، نام نمادین (نام تابع یا بلوک داده) به نام زیرمجموعه فایل شی تنظیم می‌شود. نمایه بایگانی نیاز به کار سریع با کتابخانه دارد - برای اینکه نیاز به نمایه را پیدا کنید، باید به جدول نماد همه پرونده های موجود در بایگانی نگاه کنید، می توانید بلافاصله به فایل بروید تا از جستجوی آنها جلوگیری کنید. 'من. می توانید با استفاده از ابزاری که قبلاً آشنا هستید، فهرست بایگانی را جستجو کنید. نانومتربا شتاب її گزینه ها(به این ترتیب جدول نمادهای تمام فایل های شی در بایگانی نشان داده می شود):

$nm -s libhello.a
فهرست آرشیو:
اول در first.o
دوم در second.o

first.o:
00000000 T ابتدا
U قرار می دهد

second.o:
U قرار می دهد
00000000 T ثانیه

برای ایجاد یک فهرست آرشیو شما نیاز دارید ابزار ویژه ranlib. کتابخانه libhello.a می تواند به صورت زیر ایجاد شود:

$ ar cr libhello.a اول.o دوم.o
$ranlib libhello.a

با این حال، کتابخانه بدون فهرست آرشیو فوق العاده کار می کند.

اکنون ما در حال افزایش سرعت کتابخانه خود هستیم:

$gcc-Wall-c main.c
$
$./اصلی
اولین تابع ...
تابع دوم ...
عملکرد اصلی ...

پراتسیو...

خوب حالا نظرات ... دو گزینه جدید ظاهر شد gcc:

نام گزینه -l- به پیوند دهنده منتقل می شود، که نشان دهنده نیاز به گنجاندن libname کتابخانه در فایل است. اتصال به معنی نشان دادن این است که فلان توابع (تغییرات خارجی) به کتابخانه اختصاص داده شده است. در برنامه ما، کتابخانه ثابت است، همه نام های نمادین به کدی که در فایل کامپایل شده قرار دارد اختصاص داده می شود. بازگرداندن احترام در گزینه -lنام کتابخانه به عنوان نام بدون پیشوند lib مشخص می شود.

گزینه -L /paths/to/catalog/with/libraries - به مدیر کتابخانه منتقل می شود و به دایرکتوری دستور می دهد تا کتابخانه های در حال اتصال را پیدا کند. ویپاد ما یک نقطه دارد . ، linkovnik ابتدا کتابخانه ها را در کاتالیز جریان، سپس در فهرست های سیستم جستجو کنید.

در اینجا لازم است کمی احترام به دست آوریم. سمت راست برای گزینه های کم است gccترتیب مهم خط مستقیم در خط فرمان. بنابراین پیوند دهنده به دنبال کدی می گردد که با نام های کتابخانه مشخص شده در جدول نمادها و نام فایل ها در خط فرمان مطابقت داشته باشد. بعد ازنام فایل. به جای کتابخانه هایی که قبل از نام فایل دوباره به اشتراک گذاشته شده اند، پیوند دهنده نادیده می گیرد:

$gcc-Wall-c main.c
$ gcc-o main-L. -سلام main.o
main.o: در تابع 'main':
main.c:(.text+0xa): ارجاع تعریف نشده به «اول»
main.c:(.text+0xf): ارجاع تعریف نشده به «ثانیه»

$ gcc -o main main.o -L. -سلام
$./اصلی
اولین تابع ...
تابع دوم ...
عملکرد اصلی ...

چنین ویژگی رفتاری gccقرار است اطلاعات لازم را در مورد امکان ترکیب فایل ها با کتابخانه ها به روش های مختلف به توسعه دهندگان داده شود تا نام هایی که تغییر می کنند را تغییر دهند... به نظر من امکان پذیر است، بهتر است زحمت ندهید. هنگام اتصال کتابخانه ها، لازم است آنها را پس از نام فایلی که به آنها ارجاع داده شده است، تغییر دهید.

ما در حال کشف یک روش جایگزین برای افزودن کتابخانه ها به سیستم هستیم. بسته به توزیع، تغییر LD_LIBRARY_PATH یا LIBRARY_PATH می‌تواند فهرستی از دایرکتوری‌ها را که با علامت دوتایی جدا شده‌اند ذخیره کند، که کتابخانه مسئول جستجوی کتابخانه است. به عنوان یک قاعده، این تغییر در ذهن نشان داده نمی شود، اما هیچ چیز برای انجام آن مهم نیست:

$echo $LD_LIBRARY_PATH

/usr/lib/gcc/i686-pc-linux-gnu/4.4.3/../../../../i686-pc-linux-gnu/bin/ld: نمی توان -lhello را پیدا کرد
collect2: wiki ld با کد نوبت 1 خارج شد
$ صادرات LIBRARY_PATH=.
$ gcc -o main.o -lhello
$./اصلی
اولین تابع ...
تابع دوم ...
عملکرد اصلی ...

دستکاری‌هایی با تغییر وضوح پس‌زمینه با ایجاد و ایجاد کتابخانه‌های قدرت به خوبی تثبیت شده، و بنابراین نیاز به اتصال به هر مکمل غیر استاندارد (منسوخ، به‌روزرسانی، تغییر یافته - به هر حال این شامل کتابخانه موجود در توزیع می‌شود. در حال توزیع است.

اکنون می توانیم یک کتابخانه پویا ایجاد و ایجاد کنیم.

مجموعه فایل های خروجی بدون تغییر از بین می رود. ما دستورات را وارد می کنیم، از آنچه اتفاق افتاده شگفت زده می شویم، نظرات را می خوانیم:

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

چه چیزی از نتایج حذف شد؟

$file libhello.so.2.4.0.5
libhello.so.2.4.0.5: ELF 64 بیتی LSB شی اشتراکی، x86-64، نسخه 1 (SYSV)، پیوند پویا، بدون حذف

فایل libhello.so.2.4.0.5 است که کتابخانه ما در حال اشتراک گذاری است. بیایید کمی در مورد نحوه کار این کار صحبت کنیم.

حالا نظرات:

گزینه -fPIC- هنگام ایجاد فایل های شی از کامپایلر قابل مشاهده است. کد مستقل از موقعیت (PIC - کد مستقل موقعیت )، این اهمیت اصلی روش ارائه آدرس است. به جای درج موقعیت های ثابت (استاتیک)، همه آدرس ها از جابجایی وظایف محاسبه می شوند. جدول جهانی اقلام (جدول افست جهانی - GOT ). فرمت کد مستقل از موقعیت به ماژول ها اجازه می دهد تا در زمان ادغام به کد برنامه اصلی متصل شوند. ظاهراً هدف اصلی کدهای مستقل از موقعیت، ایجاد کتابخانه های پویا است که به اشتراک گذاشته می شوند.

گزینه اشتراک گذاری شده- دستور می دهد gccبا این حال، در نتیجه، این فایلی که در حال کامپایل شدن است مقصر مجموعه نیست، بلکه شیئی است که به اشتراک گذاشته می شود - کتابخانه پویا.

گزینه -Wl,-soname,libhello.so.2- مجموعه ها سونام کتابخانه ها در پاراگراف بعدی در مورد سونام صحبت خواهیم کرد. بیایید اکنون در مورد قالب گزینه بحث کنیم. این طرح شگفت انگیز در نگاه اول با کما برای تعامل یکپارچه بین کشاورز و لینکوونیک در نظر گرفته شده است. تدوین در حال انجام است gccحاکم به طور خودکار، به طور خودکار، مقامات را صدا می کند، gccگزینه های لازم برای تکمیل موفقیت آمیز کار را پاس می کند. اگر توسعه دهنده نیاز داشته باشد که خودش در فرآیند پیوند شرکت کند، می تواند از یک گزینه ویژه برای سرعت بخشیدن به کارها استفاده کند. gcc -Wl، -option، value1، value2 .... تسلیم به نگهبان یعنی چه ( -Wl) گزینه -گزینهبا استدلال ارزش 1, ارزش 2و غیره. در مورد ما، این گزینه به پیوند دهنده داده شد -سونامبا استدلال libello.so.2.

حالا در مورد سونام با ایجاد و گسترش کتابخانه ها، مشکل کنترل نسخه به وجود می آید. برای اینکه سیستم به طور خاص از کتابخانه های پویا استفاده کند، توجه به این نکته مهم است که کتابخانه ای که از کدام نسخه از کتابخانه در هنگام کامپایل برنامه ها استفاده شده است و ظاهراً برای عملکرد موفقیت آمیز آن ضروری است، این شناسه ویژه منتقل می شود - سونام که هم در فایل خود کتابخانه و هم در فایل کامپایل شده برنامه قرار دارد. شناسه soname رشته‌ای است که شامل نام کتابخانه با پیشوند lib، یک نقطه، پسوند so، یک نقطه جدید و یک یا دو رقم (که با یک نقطه از هم جدا شده‌اند) از نسخه کتابخانه - lib name.so. ایکس. y سپس soname از فایل کتابخانه در اولین یا رقم دیگر شماره نسخه ذخیره می شود. اجازه دهید نام فایل کتابخانه ما libhello.so.2.4.0.5 باشد، بنابراین soname کتابخانه می تواند libhello.so.2 باشد. هنگام تغییر رابط کتابخانه، سونام باید تغییر کند! هر گونه تغییر در کد که منجر به جنون در نسخه های قبلی شود، با ظاهر شدن یک نام جدید همراه است.

چگونه همه چیز درست می شود؟ برای دانلود موفقیت آمیز این افزونه، به کتابخانه ای با نام hello نیاز دارید، اجازه دهید سیستم یک فایل کتابخانه به نام libhello.so.2.4.0.5 داشته باشد و به نام کتابخانه libhello.so.2 ثبت شده باشد. در مرحله کامپایل برنامه، لینک دهنده، گزینه را انتخاب کنید -سلامفایلی به نام libhello.so در سیستم پیدا خواهید کرد. در یک سیستم واقعی، libhello.so به صورت نمادین به فایل libhello.so.2.4.0.5 ارسال می شود. پس از دسترسی به فایل کتابخانه، پیوند دهنده باید مقدار soname را در یک مقدار جدید وارد کرده و آن را به همان ترتیب فایل برنامه ای که ذخیره می شود، قرار دهد. هنگامی که برنامه راه اندازی می شود، مدیر کتابخانه پویا اتصال کتابخانه با soname را می خواهد، فایلی را که در حال اتصال است می خواند و سعی می کند کتابخانه ای را در سیستم پیدا کند که نام فایل آن ذخیره می شود. soname. سپس خریدار سعی می کند فایل libhello.so.2 را پیدا کند. اگر سیستم به درستی پیکربندی شده باشد، ممکن است به صورت نمادین libhello.so.2 را به فایل libhello.so.2.4.0.5 ارسال کند که دسترسی به کتابخانه لازم را رد می کند و تداخلی ایجاد نمی کند (و هیچ چیز دیگری را بررسی نمی کند) وصل کنید به الحاقیه اکنون مشخص است که ما تدوین چنین اضافاتی را به سیستم دیگری منتقل کرده ایم که در آن فقط نسخه پیشینکتابخانه ها با soname libhello.so.1. سعی کنید برنامه را اجرا کنید تا زمانی که از کار بیفتد؛ هیچ فایلی به نام libhello.so.2 روی سیستم شما وجود ندارد.

بنابراین، در مرحله کامپایل، پیوند دهنده باید یک فایل کتابخانه (یا به صورت نمادین به فایل کتابخانه ارسال شود) با نام lib بارگذاری کند. بنابراین، در مرحله کامپایل، باید یک فایل (یا به صورت نمادین ارسال شده) را با آن آپلود کنم. من نام lib هستم .so. ایکس. y نام lib چیست؟ ایکس. می توانید به ردیف soname کتابخانه دسترسی داشته باشید.

در توزیع های باینری، به عنوان یک قاعده، فایل کتابخانه libhello.so.2.4.0.5 و پیوند به libhello.so.2 جدید در بسته libhello قرار می گیرد و لازم است پیوند libhello.so همراه با فایل هدر کتابخانه hello. h در بسته libhello-devel بسته می شود (در بسته های توسعه فایلی از نسخه استاتیک کتابخانه libhello.a وجود دارد، کتابخانه استاتیک را نیز می توان در مرحله کامپایل کامپایل کرد) . هنگامی که بسته باز می شود، همه فایل ها و پیام های لیست شده (از جمله hello.h) در یک فهرست ظاهر می شوند.

بیایید به این واقعیت نگاه کنیم که وظایف ردیف soname در کتابخانه ما معتبر است. دسترسی سریع به ابزار مگا ابجدمپبا گزینه :

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


سودمند ابجدمپ- یک ابزار قدرتمند که به شما امکان می دهد اطلاعات اضافی در مورد مکان (های) داخلی یک شی یا فایلی که در حال نهایی شدن است بازیابی کنید. طرف ابزار می گوید ابجدمپبا تشکر از همه برنامه نویسان خوبی که روش های بهینه سازی و کامپایل ایجاد می کنند و فقط برنامه های کاربردی نمی نویسند :) ویدیو با گزینه این جداکننده است. ما به سرعت یک گزینه پیدا کردیم - نمایش متا اطلاعات مختلف در مورد فایل شی.

در این برنامه از کتابخانه، ما نتوانستیم از اصول تالیف جداگانه پیروی کنیم. کامپایل کتابخانه به صورت هوشمند تنها با یک کلیک امکان پذیر بود gcc:

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

اکنون بیایید سعی کنیم به سرعت به کتابخانه ای که بیرون آمده است دسترسی پیدا کنیم:

$gcc-Wall-c main.c
$
/usr/bin/ld: نمی تواند -lhello را پیدا کند
collect2: ld 1 وضعیت خروج را برگرداند

خط کش پارس می کند. می‌توانیم حدس بزنیم که بیشتر درباره پیام‌های نمادین چه گفته شد. libhello.so را ایجاد کنید و دوباره امتحان کنید:

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

الان همه خوشحالن بیایید خلاقیت های باینری را راه اندازی کنیم:

مرسی... پسری هست که نمی تواند کتابخانه libhello.so.2 را پیدا کند. بیایید دوباره پیکربندی کنیم که فایلی که در حال تبدیل است پیامی به libhello.so.2 نوشته شده باشد:

$objdump-p اصلی | grep مورد نیاز است
NEEDED libhello.so.2
نیاز به libc.so.6

$ ln -s libhello.so.2.4.0.5 libhello.so.2
$./اصلی
اولین تابع ...
تابع دوم ...
عملکرد اصلی ...

درخواست شده ... اکنون برای گزینه های جدید نظر دهید gcc.

گزینه -Wl، -rpath،.- طرح از قبل شناخته شده است، گزینه را به لینک دهنده منتقل کنید -rpathبا استدلال . . برای کمک بیشتر -rpathهنگامی که یک فایل با یک برنامه ایجاد می کنید، می توانید مراحل اضافی را ثبت کنید که برای جستجوی فایل های کتابخانه استفاده می شود. ویپادکا نسخه های ما راهی دارد . - فایل های کتابخانه را جستجو کنید و از دایرکتوری جریان شروع کنید.

$objdump-p اصلی | grep RPATH
RPATH.

پس از انتخاب گزینه هنگام شروع برنامه، دیگر نیازی به تغییر تنظیمات نیست. ظاهراً اگر برنامه را به دایرکتوری دیگری منتقل کنید و سعی کنید آن را اجرا کنید، فایل کتابخانه پیدا نمی شود و یک اعلان در مورد حذف مشاهده خواهید کرد:

اصلی $mv..
$../اصلی
اولین تابع ...
تابع دوم ...
عملکرد اصلی ...

می توانید دریابید که کدام کتابخانه ها جدا شده اند و از ابزارهای کمکی اضافی استفاده کنید. ldd:

$ldd اصلی
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)

در visnovku lddبرای هر کتابخانه مورد نیاز، سونام و مسیر بعدی فایل کتابخانه را مشخص کنید، مقادیر منوط به تنظیم سیستم هستند.

اکنون زمان آن است که در مورد مکان قرار دادن فایل های کتابخانه در سیستم، جایی که می توانید سعی کنید آنها را پیدا کنید و نحوه پردازش آنها صحبت کنید.

لطفا با ما تماس بگیرید FHS (استاندارد سلسله مراتب سیستم فایل)سیستم ممکن است دو (حداقل) دایرکتوری برای ذخیره فایل های کتابخانه داشته باشد:

/lib - در اینجا کتابخانه های اصلی توزیع، برنامه های ضروری از /bin و /sbin هستند.

/usr/lib - کتابخانه های مورد نیاز برنامه های کاربردی تحت /usr/bin و /usr/sbin در اینجا ذخیره می شوند.

فایل‌های هدر که کتابخانه‌ها را نشان می‌دهند در پوشه /usr/include قرار دارند.

Zavantazhuvach برای مجموعه فایل های کتابخانه در این فهرست.

علاوه بر موارد ذکر شده در بالا، سیستم برای دایرکتوری /usr/local/lib مقصر است - مقصر در اینجا کتابخانه هایی هستند که به طور مستقل توسط سیستم ساخته شده اند و سیستم مدیریت بسته را دور می زنند (که به انبار توزیع نمی رود. ). به عنوان مثال، در این کاتالوگ کتابخانه هایی وجود خواهد داشت که از کدهای خروجی کامپایل شده اند (برنامه های نصب از دستگاه های خروجی در /usr/local/bin و /usr/local/sbin قرار خواهند گرفت، بدیهی است که ما در مورد توزیع های باینری صحبت می کنیم). فایل‌های هدر کتابخانه‌های این نسخه در /usr/local/include قرار خواهند گرفت.

برای تعدادی از توزیع ها (برای اوبونتواگر می خواهید کتابخانه را از دستگاه های خارجی نصب کنید، مهم است که به دایرکتوری /usr/local/lib نگاه کنید، سیستم کار نمی کند. این به طور ویژه توسط نویسندگان کیت توزیع ایجاد شده است تا به نصب عادت کنند نرم افزار امنیتییا حتی از طریق سیستم Keruvannya در بسته ها. نحوه عمل در این شرایط در زیر توضیح داده خواهد شد.

برای ساده‌سازی و سرعت بخشیدن به فرآیند جستجوی فایل‌های کتابخانه، کاربر به فهرست‌های جستجو نگاه نمی‌کند، بلکه پایگاه داده‌ای را که در فایل /etc/ld.so.cache (کش کتابخانه) ذخیره شده است، جستجو می‌کند. در اینجا می توانید اطلاعاتی در مورد مواردی که فایل کتابخانه در سیستم قرار دارد بیابید. توسعه دهنده، با انتخاب لیست کتابخانه های مورد نیاز برای یک برنامه خاص (لیست کتابخانه های soname، وظایف موجود در فایل برنامه)، با استفاده از /etc/ld.so.cache، مسیر فایل هر کتابخانه و بارگیری لازم را تعیین می کند. آنها را در میات. علاوه بر این، می توانید به دایرکتوری های لیست شده در متغیرهای سیستم LD_LIBRARY_PATH، LIBRARY_PATH و در قسمت RPATH فایل پیوند داده شده (به علاوه) نگاه کنید.

برای به روز رسانی و حفظ وضعیت فعلی حافظه پنهان کتابخانه، از یک ابزار استفاده می شود ldconfig. نحوه اجرا ldconfigبدون هیچ گزینه ای، برنامه به دایرکتوری های مشخص شده در خط فرمان نگاه می کند، به دایرکتوری های /lib و /usr/lib اعتماد می کند، دایرکتوری ها در فایل /etc/ld.so.conf فهرست شده اند. برای هر فایل کتابخانه ای که در دایرکتوری های مشخص شده قرار دارد، توسط soname محافظت می شود که بر اساس پیام نمادین soname ایجاد شده و با اطلاعات در /etc/ld.so.cache به روز می شود.

اجازه دهید به آنچه گفته شد بپردازیم:

$ls
hello.h libhello.so libhello.so.2.4.0.5 main.c
$
$ sudo ldconfig /povniy/shlakh/do/kataogu/c/butt
$ls
hello.h libhello.so libhello.so.2 libhello.so.2.4.0.5 main main.c
$./اصلی
اولین تابع ...
تابع دوم ...
عملکرد اصلی ...

اول ویکلیک ldconfigما کتابخانه خود را در حافظه پنهان ذخیره کردیم و با یک کلیک دیگر آن را روشن کردیم. لطفا توجه داشته باشید که هنگام کامپایل main گزینه حذف شده است -Wl،-rpath،.، در نتیجه جستجوی کتابخانه های لازم در حافظه پنهان.

اکنون نحوه رفع آن مشخص است، زیرا پس از نصب کتابخانه از دستگاه های خروجی، سیستم بوت نمی شود. ابتدا باید یک مسیر جدید به فایل /etc/ld.so.conf به دایرکتوری حاوی فایل های کتابخانه (پشت /usr/local/lib) اضافه کنیم. فرمت /etc/ld.so.conf - فایل حاوی لیستی از تقسیمات است که با دو، یک فاصله، یک برگه یا نمادی از یک ردیف جدید از دایرکتوری ها که در آن کتابخانه ها جستجو می شوند از هم جدا شده اند. برای چی کلیک کنید ldconfigبدون هیچ گزینه ای، اما با حقوق فوق العاده پزشکی قانونی. همه چیز را می توان به دست آورد.

خوب، در نهایت، بیایید در مورد چگونگی وجود نسخه های ایستا و پویا از کتابخانه ها صحبت کنیم. چرا غذا داری؟ علاوه بر این، زمانی که نام های اتخاذ شده و توزیع فایل های کتابخانه مورد بحث قرار گرفت، گفته شد که فایل های نسخه های استاتیک و پویا کتابخانه در یک دایرکتوری ذخیره می شوند. یاک gccآیا می دانید چه نوع کتابخانه ای را می خواهیم جستجو کنیم؟ مزیت یک کتابخانه پویا است. اگر پیوند دهنده فایل کتابخانه پویا را بشناسد، زحمتی برای اضافه کردن آن به فایل برنامه ای که در حال نهایی شدن است ندارد:

$ls
hello.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. -lhello -Wl,-rpath,.
$ldd اصلی
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 اصلی
12K اصلی

اندازه فایل برنامه ذخیره شده را تغییر دهید. Vin حداقل توانایی دارد. همه کتابخانه ها به صورت پویا پیوند داده شده اند.

خوابیدن گزینه gcc-static- اضافه کردن نسخه های ثابت تمام کتابخانه های اضافی ضروری:

$ gcc-static-o main.o-L. -سلام
$file main
اصلی: ELF 64 بیتی LSB قابل اجرا، x86-64، نسخه 1 (GNU/Linux)، پیوند استاتیک، برای گنو/لینوکس 2.6.15، بدون حذف
$ldd اصلی
یک فایل پیوندی پویا نیست
$ du -h اصلی
اصلی 728K

اندازه فایل، که 60 برابر بزرگتر است، کمتر از حالت اول است - فایل شامل کتابخانه استاندارد فیلمبرداری است. سی. حالا برنامه ما به راحتی از دایرکتوری به دایرکتوری منتقل می شود و به ماشین های دیگر منتقل می شود، کد hello library در وسط فایل است، برنامه کاملا مستقل است.

در این صورت، چگونه ایجاد پیوند استاتیک برای برخی از کتابخانه های جانشین ضروری است؟ یک راه حل ممکن این است که یک نسخه ایستا از کتابخانه را با نام جدا شده ایجاد کنید و هنگام کامپایل برنامه ها، نشان دهید که در هر زمان می خواهید از کدام نسخه استفاده کنید:

$ mv libhello.a libhello_s.a
$ gcc -o main main.o -L. -سلام_ها
$ldd اصلی
linux-vdso.so.1 => (0x00007fff021f5000)
libc.so.6 => /lib/libc.so.6 (0x00007fd0d0803000)
/lib64/ld-linux-x86-64.so.2 (0x00007fd0d0ba4000)
$ du -h اصلی
12K اصلی

اندازه کد کتابخانه libhello ناچیز است،

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

اندازه فایل در حال پیوند عملاً با اندازه فایل ایجاد شده با استفاده از پیوندهای پویا برابر است.

خب، احتمالاً همین است. با احترام به همه کسانی که خواندن را در این مکان به پایان رسانده اند.

اکنون که با استاندارد C آشنا شدید، بیایید نگاهی به گزینه هایی بیندازیم که کامپایلر gcc برای اطمینان از انطباق با استاندارد زبان C که در حال نوشتن آن هستید، ارائه می دهد. سه راه برای اطمینان از مطابقت کد شما در C با استانداردها و عدم تداخل با آب وجود دارد: گزینه‌هایی برای کنترل نسخه استاندارد، نوع انطباق با آن و تفاوت در کنترل فایل‌های هدر. و گزینه هایی که از قبل شروع می شوند، کد برنامه را اصلاح خواهم کرد.

gcc طیف گسترده ای از گزینه ها را دارد و در اینجا به مواردی که از نظر ما مهم ترین هستند نگاه می کنیم. فهرست کاملی از گزینه ها را می توان در صفحات راهنمای تعاملی gcc یافت. همچنین به اختصار درباره گزینه های دستور العمل #define که قابل تنظیم هستند صحبت خواهیم کرد. به آنها دستور دهید قبل از هر خطی با دستور #include در کد برنامه خروجی مشخص شوند یا به خط فرمان gcc اضافه شوند. ممکن است از چنین گزینه های متنوعی برای انتخاب یک علامت استاندارد به جای یک علامت ساده تعجب کنید که در انتخاب استاندارد فعلی اختلال ایجاد می کند. دلیل آن این است که بسیاری از برنامه‌های قدیمی‌تر بر رفتار کامپایلر شکل‌گرفته از تاریخ متکی هستند و برای به‌روزرسانی آن‌ها به آخرین استانداردها به کار زیادی نیاز دارند. به ندرت، وقتی در حال مرگ هستید، می خواهید کامپایلر خود را ارتقا دهید تا بتوانید شروع به تجزیه کد برنامه در حال اجرا کنید. در دنیایی که استانداردها در حال تغییر است، مهم است که توانایی کار بر خلاف استاندارد جدید را در نظر بگیرید، حتی اگر آخرین نسخه استاندارد نباشد.

اگر در حال نوشتن یک برنامه کوچک برای یک برنامه خاص هستید، زیرا رعایت استانداردها ممکن است چندان مهم نباشد، اغلب ارزشمند است که پسوندهای gcc را فعال کنید تا کامپایلر قبل از انتشار برنامه به اصلاحات در کد شما فکر کند. حذف کد از مدیر و جلوگیری از مشکل احتمالی همیشه مؤثرتر است. کامپایلر گزینه های زیادی دارد که به بررسی ساده برای مطابقت با استانداردها محدود نمی شود، مانند اینکه آیا کدی را که استاندارد را برآورده می کند یا شاید معنایی مشکوک را شناسایی کند. به عنوان مثال، یک برنامه ممکن است یک سفارش طراحی داشته باشد که به آن اجازه می دهد قبل از پایان آن از سر گرفته شود.

اگر نیاز به نوشتن برنامه ای برای یک ویکی جمعی دارید، زمانی که سطح انطباق با استاندارد و نوع کامپایلری را که کافی می دانید انتخاب می کنید، مهم است که کمی تلاش کنید و به کامپایل کردن کد خود بدون هیچ گونه پیشرفتی برسید. شروع به سوختن کرد اگر اجازه دهید تاخیرها ظاهر شوند و آنها را نادیده بگیرید، یک روز شگفت انگیز ممکن است تاخیرهای جدی تری را آشکار کند که احتمال از دست دادن آنها وجود دارد. اگر کد برنامه شما بدون اطلاع قبلی کامپایل شده باشد، پیشرفت های جدید به ناچار احترام شما را از دست خواهند داد. کامپایل کد برنامه بدون پیشبرد – اولین قدم در نظر گرفتن آن است.

گزینه های کامپایلر برای استانداردسازی

Ansi مهمترین گزینه است زیرا هیچ استانداردی وجود ندارد و کامپایلر با استاندارد زبان ISO C90 مطابقت دارد. ویژگی‌های پسوند gcc را فعال می‌کند که در استاندارد گنجانده نشده‌اند، نظرات به سبک C++ (//) را در برنامه‌ها فعال می‌کند، و مدیریت سه‌نگارهای ANSI (توالی‌های سه کاراکتری) را فعال می‌کند. علاوه بر این، می‌توانید ماکرو __ STRICT_ANSI__ را وارد کنید، که اقدامات پسوندی را در فایل‌های هدر فعال می‌کند که با استاندارد سازگار نیست. استاندارد ممکن است در نسخه های بعدی کامپایلر تغییر کند.

Std= - این گزینه کنترل دقیق تری را روی استاندارد انتخاب شده ارائه می دهد و پارامتری را ارائه می دهد که استاندارد مورد نیاز را به دقت مشخص می کند. در زیر گزینه های اصلی ممکن است:

C89 - از استاندارد C89 پشتیبانی می کند.

ISO9899:1999 - پشتیبانی من نسخه را نگه می دارماستاندارد ISO، C90;

Gnu89 - از استاندارد C89 پشتیبانی کنید، اما مواردی مانند پسوندهای گنو و مواردی از این قبیل را مجاز کنید قابلیت های عملکردی C99. در نسخه 4.2 gcc این گزینه غیرفعال است.

گزینه هایی برای انطباق با استاندارد با دستورالعمل های تعریف شده

ثابت هایی وجود دارند (#defines) که می توانند توسط گزینه های موجود در خط فرمان مشخص شوند یا در متن خروجی برنامه ظاهر شوند. ما قدردانی می کنیم که خط فرمان کامپایلر برای آنها استفاده می شود.

STRICT_ANSI__ - استاندارد ISO در حال منجمد شدن است. اگر گزینه -ansi در خط فرمان کامپایلر نصب شده باشد قابل مشاهده است.

POSIX_C_SOURCE=2 - قابلیت های عملکردی تعریف شده توسط استانداردهای IEEE Std 1003.1 و 1003.2 را فعال می کند. کمی بعد در این بخش به این استانداردها باز خواهیم گشت.

BSD_SOURCE – عملکرد سیستم های BSD را فعال می کند. از آنجایی که با مقادیر POSIX در تضاد هستند، مقادیر BSD اولویت بیشتری دارند.

GNU_SOURCE - به طیف گسترده ای از قدرت ها و عملکردها، از جمله پسوندهای گنو اجازه می دهد. تا جایی که این مقادیر با مقادیر POSIX در تضاد باشند، بقیه اولویت دارند.

گزینه های کامپایلر برای تولید جلو

این گزینه ها از خط فرمان به کامپایلر ارسال می شوند. و دوباره ما فراتر از اصول اولیه بیش از حد کار می کنیم، آخرین لیسترا می توان در راهنمای تعاملی gcc یافت.

Pedantic - این مهمترین گزینه برای بررسی خلوص کد برنامه در زبان C است. هنگامی که گزینه بررسی مطابقت با استاندارد C فعال باشد، شامل چندین طرح سنتی از زبان C، استاندارد مسدود شده و ساخت است. همه پسوندهای گنو طبق استاندارد غیرقابل قبول هستند. Tsu oppsis of the stage، مدرسه حداکثر انتقال کد شما در دهکده ندنیک ї در همین کامپایلر با کد برنامه تمیز شما خیلی احمقانه است و هد برای یک ساعت برای توله سگ آورده شده است. برای پیشی گرفتن از تقلب

Wformat - صحت انواع آرگومان را با استفاده از توابع خانواده printf بررسی می کند.

Wparentheses - وجود قوس ها را بررسی می کند، نیازی به بوی بد نیست. این گزینه برای تأیید اینکه ساختارهای تاشو همانطور که در نظر گرفته شده مقداردهی اولیه شده اند بسیار مفید است.

Wswitch-default - وجود گزینه پیش‌فرض را در عبارات سوئیچ بررسی می‌کند، که توسط سبک برنامه‌نویسی خوب رعایت می‌شود.

Wunused - انواع مختلف مشکلات را بررسی می کند، به عنوان مثال، توابع استاتیک غیرفعال هستند، و پارامترهایی که توضیح داده نشده اند، اصلاح نمی شوند، نتایج به بیرون پرتاب می شوند.

دیوار - شامل اکثر انواع در مقابل gcc، از جمله تمام گزینه های جلو - W (آزار نمی دهد - pedantic). این به شما کمک می کند تا به راحتی به کد نرم افزار تمیز دست یابید.

توجه داشته باشید

هیچ گزینه اضافی از قبل وجود ندارد، تمام جزئیات نشان داده شده است. در صفحات وب gcc. اساسا، ما راکد-وال را توصیه می کنیم. این یک سازش بسیار بین تأییدیه ای است که کد برنامه را تضمین می کند قدرت بالا، و نیاز به کامپایلر برای استنباط بسیاری از پیشرفت های بی اهمیت، که مهم است به صفر برسد.

برای اجرای صحیح gcc، کامپایلر استاندارد لینوکس، باید گزینه های خط فرمان را فعال کنید. علاوه بر این، gcc زبان را گسترش می‌دهد.اگر قصد دارید کد خروجی بنویسید که مطابق با استاندارد ANSI این زبان باشد، برای درک فایل‌های هدر لینوکس، دانستن عملکردهای پسوند gcc به سادگی ضروری است.

اکثر گزینه‌های خط فرمان همان گزینه‌هایی هستند که در کامپایلرهای C یافت می‌شوند. استانداردهای فعلی برای برخی از گزینه‌ها منتقل نمی‌شوند. این بخش دارای بسیاری از مهم ترین گزینه هایی است که در برنامه نویسی روزمره مورد نیاز است.

رعایت استاندارد ISO بسیار مهم است، اما در ارتباط با این، که آب کم ریشه است، شرایطی ایجاد می شود که روش های استاندارد به اندازه کافی مؤثر نیستند. دو زمینه وجود دارد که در آن پسوند gcc به طور گسترده مورد استفاده قرار می گیرد: تعامل با کد اسمبلی (که در http://www.delorie.com/djgpp/doc/brennan/ موجود است) و کتابخانه های تاشو که به طور گسترده توسعه یافته اند (div. بخش 8). برخی از فایل‌های هدر و برخی کتابخانه‌ها به شدت مورد تحقیق قرار گرفته‌اند و برخی پسوندها نیز در فایل‌های هدر سیستم یافت می‌شوند.

البته، یک پسوند بی معنی نیز وجود دارد که هر شکل دیگری از برنامه نویسی را دارد، که حتی می تواند به کدنویسی کمک کند. اطلاعات تکمیلیاین پسوندها را می توان در اسناد gcc در قالب Texinfo یافت.

5.1. گزینه های gcc

gcc گزینه های فرمان زیادی را می پذیرد. خوشبختانه طیف گزینه هایی که به طور موثر مورد نیاز مادران است چندان زیاد نیست و در این قسمت به بررسی آنها می پردازیم.

اکثر گزینه‌ها اجتناب‌شده یا مشابه گزینه‌های سایر کامپایلرها هستند، gcc شامل اسناد گسترده‌ای برای گزینه‌های خود است که از طریق info gcc در دسترس است (مدیر gcc نیز این اطلاعات را نشان می‌دهد، صفحات حرفه‌ای به اندازه اسناد در قالب Texinfo به‌روزرسانی نمی‌شوند. ).

-درباره file_name نام فایل خروجی را مشخص می کند. اگر نیازی به کامپایل در یک فایل شی نیست، باید file_name.c را با file_name.o جایگزین کنید. با این حال، هنگامی که فایلی را ایجاد می کنید که در حال ذخیره است، معمولاً (به دلایل تاریخی) با نام a.out ایجاد می شود. اگر بخواهید فایل خروجی را در دایرکتوری دیگری قرار دهید نیز جالب است.
-با بدون پیوند دادن فایل خروجی، دستورالعمل های خط فرمان را کامپایل می کند. در نتیجه هر فایل خروجی، یک فایل شی ایجاد می شود. وقتی make را انتخاب می کنید، کامپایلر gcc هر فایل شی را فراخوانی می کند. به این ترتیب تشخیص اینکه کدام فایل قابل کامپایل نیست آسان تر است. با این حال، وقتی دستورات را به صورت دستی تایپ می کنید، gcc اغلب از شما می خواهد که هیچ فایلی را حذف نکنید. در مواقعی که ممکن است تعداد معینی از فایل ها در خط فرمان باعث ابهام شود، بهتر است فقط یک فایل را مشخص کنید. برای مثال، جایگزینی gcc -з -о а.о а.с b.с ممکن است zastosuvati gcc -з -o a.o b.c را حس کند.
-دی فو به معنای ماکروهای خط فرمان پیش پردازنده است. ممکن است لازم باشد نمادهایی را تعریف کنیم که توسط پوسته به عنوان خاص تفسیر می شوند. به عنوان مثال، هنگامی که یک ردیف تعیین می شود، هیچ علامت منحصر به فردی برای جدا کردن ردیف ها استفاده نمی شود. پوسته با درجه خاصی به پاکسازی ها نگاه می کند.
من دایرکتوری دایرکتوری را به فهرست دایرکتوری هایی اضافه می کند که فایل ها در آن جستجو می شوند تا گنجانده شوند.
فهرست -L فهرستی را به فهرست دایرکتوری‌هایی که کتابخانه‌ها در آن جستجو می‌شوند اضافه می‌کند، gcc به کتابخانه‌های جامد به جای کتابخانه‌های ایستا ترجیح می‌دهد، تا زمانی که دروازه‌ای نصب نشده باشد.
-من فک میکنم پیوند با کتابخانه lib foo را پیکربندی می کند. مگر اینکه طور دیگری مشخص شده باشد، gcc اولویت را به پیوند از کتابخانه های دارای اسکریپت سنگین (lib foo .so) می دهد تا از کتابخانه های ایستا (lib foo .a). ترکیب کننده در تمام کتابخانه های بازنویسی شده به ترتیبی که رونویسی شده است، عمل می کند. جستجو زمانی پایان می یابد که همه توابع مورد نیاز پیدا شوند.
-استاتیک از طرح‌بندی با کتابخانه‌های بیش از حد ثابت جلوگیری می‌کند. بخش 8.
-g، -ggdb شامل اطلاعات تغذیه ای است. گزینه -g gcc را غیرفعال می‌کند تا حاوی اطلاعات ابزار استاندارد باشد. گزینه -ggdb نشان دهنده نیاز به گنجاندن حجم زیادی از اطلاعات است که ممکن است قابل درک نباشد مدیر gdb.
اگر فضای دیسک دارید یا می‌خواهید برخی از قابلیت‌ها را فدای سرعت طرح‌بندی کنید، از -g استفاده کنید. در این شرایط این امکان وجود دارد که به جای gdb با شخص دیگری روبرو شوید. برای حداکثر لذت، لازم است -ggdb را مشخص کنید. برای این نوع، gcc بیشترین اطلاعات گزارش را برای gdb آماده می کند. توجه داشته باشید که gcc در حالی که جایگزین اکثر کامپایلرها می شود، اطلاعات مفیدی را در بهینه سازی کد قرار می دهد. با این حال، توسعه کدهای بهینه شده ممکن است با ناهماهنگی هایی همراه باشد، و در طول زمان اشکال زدایی، ممکن است خطوط و حذف قطعات کد وجود داشته باشد، که، همانطور که مشخص است، ممکن است کمی کج شود. زمان کمتر نیست، در این صورت می توانید هشدارهای مربوط به کامپایلرهایی را که بهینه سازی می کنند حذف کنید، نحوه کامپایل کد را تغییر دهید.
-O، -O n من gcc را تشویق می کنم تا کد را بهینه کند. مقدار کمی از بهینه سازی در gcc وجود دارد. با وارد کردن عدد (n)، بهینه سازی سطح آواز فعال می شود. بیشترین سطح گسترش بهینه سازی – 2; در حال حاضر نسخه استاندارد gcc بالاترین را دارد سطح بالابهینه سازی 3. توصیه می کنیم از -O2 یا -O3 استفاده کنید. -O3 می‌توانید اندازه برنامه‌ها را افزایش دهید، بنابراین چون ممکن است مهم نباشد، هر دو گزینه را امتحان کنید. اگر حافظه و فضای دیسک برای برنامه شما مهم هستند، می توانید از گزینه -Os استفاده کنید تا اندازه کد را برای مدت زمان اضافی به حداقل برسانید. gcc فقط در صورتی عملکردها را فعال می کند که حداقل بهینه سازی (-O) را بخواهید.
-ansi برنامه ها از تمام استانداردهای ANSI (X3.159-1989) یا ISO معادل آنها (ISO/IEC 9899:1990) (در ابتدا C89 یا بعد از آن C90 نامیده می شد) پشتیبانی می کنند. این امر انطباق مداوم با استاندارد ANSI/ISO را تضمین می کند.
گزینه -ansi پسوندهای gcc را فعال می کند که ممکن است با استانداردهای ANSI/ISO در تضاد باشند. (با توجه به این واقعیت که این پسوندها توسط بسیاری از کامپایلرهای C دیگر پشتیبانی می شوند، در عمل این مشکلی نیست.) این همچنین به معنای ماکرو __STRICT_ANSI__ (همانطور که در ادامه این کتاب توضیح داده شد) است که فایل های هدر برای برنامه کامپایل می شوند. وسط که توسط ANSI/ISO تایید شده است.
-آدم ملانطقی اطلاعیه قبلی در مورد تغییرات مورد نیاز برای استاندارد ANSI/ISO ارائه دهید. این امر انطباق کامل با استاندارد ANSI/ISO را تضمین نمی کند.
-دیوار تولید همه پیشرفت ها در gcc را فعال می کند که یکسان است. به این ترتیب، گزینه هایی را که ممکن است در موقعیت های خاص مفید باشند را فعال نکنید. سطح مشابهی از جزئیات برای برنامه کنترل syntax lint در کد خروجی شما ارائه می شود، gcc به شما اجازه می دهد تا کامپایلر را از قبل به صورت دستی وارد و غیرفعال کنید. کتاب مرجع gcc تمام مراحل را با جزئیات شرح می دهد.
5.2. فایل های هدر
5.2.1. طولانی طولانی

نوع طولانی نشان می دهد که بلوک حافظه استفاده شده به اندازه طول است. در اینتل i86 و دیگر پلتفرم‌های 32 بیتی، long 32 بیت و طولانی مدت 64 بیت طول می‌کشد. در پلتفرم های 64 بیتی، نمایشگرهای طولانی 64 بیت و طولانی می توانند بسته به پلتفرم، 32 یا 64 بیت را اشغال کنند. نوع بلند بلند توسط استاندارد C99 (ISO/IEC 9899:1999) و پسوندهای قدیمی ارائه شده توسط gcc پشتیبانی می شود.

5.2.2. توابع جدید

برخی از بخش‌های فایل‌های هدر لینوکس (از جمله آنهایی که مختص یک سیستم خاص هستند) دارای عملکردهایی هستند که به طور گسترده مورد استفاده قرار می‌گیرند. آنها همانند ماکروها هستند (هزینه ای برای کلیک کردن روی تابع وجود ندارد) و انواع تأییدیه هایی را که با کلیک معمولی روی تابع در دسترس هستند را ارائه می دهند. کدی که تابع مورد نیاز را فراخوانی می کند باید با حداقل بهینه سازی فعال (-O) کامپایل شود.

5.2.3. پسوند کلمات کلیدی جایگزین

gcc دارای دو نسخه از کلمه کلیدی توسعه یافته پوست است (کلمات کلیدی که توسط استاندارد ANSI/ISO تعریف نشده اند): کلمه کلیدیاین کلمه کلیدی است که در دو طرف با دو نماد صندلی مشخص شده است. اگر کامپایلر روی حالت استاندارد تنظیم شود (تنظیم زمانی که گزینه -ansi فعال باشد)، پسوندهای کلیدواژه اصلی شناسایی نمی شوند. بنابراین، برای مثال، کلمه کلیدی ویژگی در سربرگ ممکن است به صورت __خصیصه__ نوشته شود.

5.2.4. ویژگی های

کلمه کلیدی مشخصه توسعه یافته برای انتقال اطلاعات بیشتر در مورد یک تابع به gcc، یک متغیر یا یک نوع اعلان که به کد C اجازه نمی دهد، که با استاندارد ANSI/ISO مطابقت دارد، استفاده می شود. برای مثال، ویژگی aligned تورفتگی gcc را به این واقعیت می دهد که خود نوع قابل تغییر را تأیید می کند. ویژگی packed آنهایی را نشان می دهد که هیچ ذخیره سازی ندارند. noreturn به این معنی است که این تابع هرگز برگردانده نمی شود، که به gcc اجازه می دهد تا موارد جعلی را بهتر بهینه سازی کند و از قبل حذف کند.

ویژگی های تابع با افزودن آنها به تابع تلفظ می شوند، به عنوان مثال:

void die_die_die(int، char*) __ویژگی__ ((__noreturn__));

رشته خصیصه بین بازوها و نقطه ای که کلمه کلیدی مشخصه در آن قرار می گیرد و به دنبال آن ویژگی ها در بازوهای دور پایینی قرار می گیرد. از آنجایی که ویژگی های زیادی وجود دارد، لیست vikory را دنبال کنید و آنها را به کما جدا کنید.

int printm (char*, ...)

ویژگی__((const,

قالب (printf، 1، 2)))؛

در این نرم افزار واضح است که printm به مقادیر مشابهی به جز مقادیر نگاه نمی کند و هیچ عارضه جانبی قبل از تولید کد (const) ندارد، printm نشان می دهد که gcc مسئول بررسی آرگومان های تابع است مانند و printf(). آرگومان اول ردیف قالب بندی است و دومی اولین پارامتر جایگزین (فرمت) است.

این ویژگی‌ها بعداً در مطالب مورد بحث قرار خواهند گرفت (برای مثال، در زیر ساعت مجموعه‌ای از کتابخانه‌ها را که به طور گسترده در بخش 8 مورد بحث قرار خواهند گرفت، شرح خواهم داد). اطلاعات بیشتر در مورد ویژگی ها را می توان در اسناد gcc در قالب Texinfo یافت.

گاهی اوقات ممکن است متوجه شوید که به فایل های هدر لینوکس نگاه می کنید. صرف نظر از همه چیز، تعدادی طرح را خواهید یافت که با استاندارد ANSI/ISO سازگار نیستند. اقدامات آنها آماده است تا با آنها شریک شود. تمام ساختارهایی که در این کتاب مورد بحث قرار گرفته‌اند با جزئیات بیشتری در مستندات gcc ارائه شده‌اند.

گاهی اوقات ممکن است متوجه شوید که به فایل های هدر لینوکس نگاه می کنید. صرف نظر از همه چیز، تعدادی طرح را خواهید یافت که با استاندارد ANSI/ISO سازگار نیستند. اقدامات آنها آماده است تا با آنها شریک شود. تمام ساختارهایی که در این کتاب مورد بحث قرار گرفته‌اند با جزئیات بیشتری در مستندات gcc ارائه شده‌اند.

gcc (کامپایلر GNU C) - مجموعه ای از ابزارهای کاربردی برای کامپایل، مونتاژ و پیوند. روش آنها ایجاد یک فایل آماده برای اجرا در قالبی است که مناسب سیستم عامل شما باشد. برای لینوکس، فرمت ELF (قالب اجرایی و پیوند) در x86 (32 و 64 بیتی) است. آیا می دانید که می توانید از این پارامترهای gcc استفاده کنید؟ اگر به دنبال راه‌هایی برای بهینه‌سازی فایل باینری موجود، آماده‌سازی یک جلسه راه‌اندازی یا به سادگی نظارت بر اقدامات gcc برای تبدیل کد خروجی خود به فایل کامپایل‌شده هستید، آشنایی با این پارامترها ضروری است. آن را هم بخوانید.

من حدس می زنم که gcc پول زیادی به دست خواهد آورد، و نه فقط یک. محور توضیح کوچکی از این معناست:

    پیش پردازش: ایجاد کدی که دیگر دستورالعمل ها را نقض نمی کند. گفتارهای دستور "#if" توسط کامپایلر قابل تجزیه نیستند، بنابراین باید به کد واقعی ترجمه شوند. همچنین در این مرحله، ماکروها تولید می‌شوند و باعث می‌شوند کدهای کیف فرعی کمتر اصلی باشند.

    کامپایل: کد کامپایل گرفته می شود، تحلیل های لغوی و نحوی انجام می شود و کد اسمبلی تولید می شود. در این مرحله، gcc اعلان‌هایی در مورد آسیب‌ها یا هشدارها نمایش می‌دهد تا تحلیلگر هنگام تجزیه کد شما متوجه شود که چه نوع آسیب‌هایی وجود دارد. هنگامی که بهینه سازی درخواست می شود، gcc به تجزیه و تحلیل کد شما و جستجوی میانبرها و دستکاری بیشتر آنها ادامه می دهد. این ربات به سبک rich-pass طراحی شده است که نشان می دهد گاهی اوقات بیش از یک عبور از کد برای بهینه سازی لازم است.

    اسمبلی: یادگاری اسمبلی پذیرفته می شود و کدهای شی برای جایگزینی کدهای دستورالعمل تولید می شوند. مردم اغلب درک نمی کنند که کدهای دستوری در مرحله کامپایل تولید نمی شوند، بلکه در مرحله اسمبلی تولید می شوند. در نتیجه، یک یا چند فایل شی خروجی می‌شود، که می‌تواند جایگزین کدهای دستوری شود که به طور موثر با ماشین مرتبط هستند.

    ترکیب: فایل های شی را به فرمت های کیسه ای تبدیل می کند. کدهای عملیاتی به تنهایی کافی نیستند سیستم عاملاو آنها را شناخت بوها ظاهر می شوند اما دوباره شکل گرفته اند. این فرم که به عنوان فرمت باینری شناخته می شود، نشان می دهد که چگونه سیستم عامل فایل باینری را دانلود می کند، انتقال ها را کامپایل می کند و سایر کارهای ضروری را انجام می دهد. ELF فرمت استاندارد لینوکس در x86 است.

    پارامترهای gcc در اینجا به طور مستقیم و غیرمستقیم در هر چهار مرحله توضیح داده شده است، بنابراین برای وضوح، این مقاله از این الهام گرفته شده است:

    پارامترهای بهینه سازی

    پارامترهایی که توسط تابع استفاده می شود

    پارامترهای موثر بر رفاه

    پارامترهای پیش پردازش

    اول از همه، بیایید با ابزارهای اضافی که به ما در نفوذ به کد کمک می کنند آشنا شویم:

    مجموعه ای از ابزارهای ELF که شامل برنامه هایی مانند objdump و readelf است. اطلاعاتی در مورد ELF به ما بدهید.

    مرحله آسیاب = شیرخشک ایزوله / شیرخشک ایزوله

    حالا مرحله صاف کردن فایل باینری پوست را محاسبه می کنیم. برای بهینه نشده 0.5117٪ بود، در حالی که برای optimizedO2 0.4323٪ بود - در مورد ما، افزایش حتی کوچکتر است. سود واقعی ممکن است با شرط‌بندی‌های واقعی متفاوت باشد، و سهام gcc می‌تواند به تنهایی و بدون هیچ سپرده خارجی تولید شود. لطفاً برای جزئیات بیشتر درباره __builtin_expect() در مستندات gcc بخوانید.