کتابخانه diet c
دیشب که بیخوابی به سرم زده بود توی اینترنت دنبال کتابخانههای استاندارد C میگشتم، همونطور که شاید بدونید Glibc کتابخانه سی گنو و Musl libc کتابخانه ماسل هستند که بیشتر از همه اسمشونو شنیدید.
من دنبال یک راهی بودم تا یک باینری استاتیک (باینری که تمام وابستگیهای مورد نیازش برای اجرا شدن در درون فایل اجرایی خودش قرار گرفته.) کم حجم درست کنم و با Diet Libc آشنا شدم.
از همین الان بگم که این پست طولانیه :)))
کتابخانه Diet چی هستش؟
کتابخانه diet libc یک نسخه بهینه و کمحجم از کتابخانه استاندارد C (libc) است که هدف اصلی آن کاهش اندازه فایلهای اجرایی و بهبود عملکرد در شرایط خاص است. این کتابخانه توسط Felix von Leitner طراحی شده و بیشتر برای محیطهایی که منابع محدود دارند، مانند سیستمهای امبدد (Embedded Systems) یا دستگاههای کوچک، مناسب هستش.
در مقایسه با کتابخانه گنو
خب بدون مقایسه که نمیشد واقعاً به سبک بودنش پیبرد برای همین من چندتا برنامه ساده توی سی نوشتم که این رو با اون ها تست کنم.
ماشین حساب
ساده ترین برنامهای که میشه با یک زبان نوشت ماشین حساب هستش. ماشین حسابی که من در سی نوشتم با ۴ عمل اصلی هستش و کارایی خیلی سادهای هم داره. سورس کدش به این شکل هستش:
#include <stdio.h>
int main() {
char operator;
double num1, num2, result;
printf("Enter an operator (+, -, *, /): ");
scanf("%c", &operator);
printf("Enter two numbers: ");
scanf("%lf %lf", &num1, &num2);
switch (operator) {
case '+':
result = num1 + num2;
break;
case '-':
result = num1 - num2;
break;
case '*':
result = num1 * num2;
break;
case '/':
if (num2 != 0) {
result = num1 / num2;
} else {
printf("Error: Division by zero is not allowed.\n");
return 1;
}
break;
default:
printf("Error: Invalid operator.\n");
return 1;
}
printf("Result: %.2lf %c %.2lf = %.2lf\n", num1, operator, num2, result);
return 0;
}
این ماشین حساب رو با gcc و diet gcc کامپایل کردم. فلگی که به gcc دادم به این شکل بود تا بهم یک باینری استاتیک بدون هیچ پیش نیازی بده:
gcc -static -o calculator calc.c
و با diet gcc هم به شکل ساده کامپایلش کردم:
diet gcc calc.c
که خروجی رو تحت عنوان a.out میده که بعداً میتونید تغییر نامش بدید یا همون اول از فلگ o- برای تنظیم خروجی استفاده کنید.
بعد با دستور ldd پیشنیاز هاشو برسی کردم تا ببینم به چه کتابخانههایی نیاز داره که dietlibc به صورت کلی به شما باینری استاتیک رو فقط میده که خیلی خوبه.
~/test/diet/calc/# ldd calculator
not a dynamic executable
~/test/diet/calc/# ldd dietgcc
not a dynamic executable
از نظر حجمی هم که برسی کنیم کاملاً مشهوده که dietlibc حجم کمتری باینری خروجیش داره
~/test/diet/calc/# ls -la
total 924
drwxr-xr-x 2 sohi sohi 4096 Jan 21 11:41 .
drwxr-xr-x 5 sohi sohi 4096 Jan 21 11:41 ..
-rw-r--r-- 1 sohi sohi 895 Jan 21 00:48 calc.c
-rwxr-xr-x 1 sohi sohi 901736 Jan 21 00:47 calculator
-rwxr-xr-x 1 sohi sohi 25400 Jan 21 00:47 dietcalc
ماشین حسابی که با کتابخانه سی گنو بیلد شده بود حجمی حدود ۸۰۰ کیلوبایت و ماشین حسابی که با diet libc بیلد شده بود حجمی حدوداً ۳۰ کیلوبایت رو در بر داشت.
همینطور من این باینری هارو از نظر syscal با ابزار strace
هم برسی کردم که خروجیش به این شکله:
این برای diet libc هستش
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
0.00 0.000000 0 3 read
0.00 0.000000 0 3 write
0.00 0.000000 0 2 ioctl
0.00 0.000000 0 1 execve
0.00 0.000000 0 1 arch_prctl
------ ----------- ----------- --------- --------- ----------------
100.00 0.000000 0 10 total
و این هم gnu libc
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
45.33 0.000034 17 2 read
45.33 0.000034 11 3 write
9.33 0.000007 7 1 1 lseek
0.00 0.000000 0 2 fstat
0.00 0.000000 0 1 mprotect
0.00 0.000000 0 5 brk
0.00 0.000000 0 1 execve
0.00 0.000000 0 1 arch_prctl
0.00 0.000000 0 1 set_tid_address
0.00 0.000000 0 1 readlinkat
0.00 0.000000 0 1 set_robust_list
0.00 0.000000 0 1 prlimit64
0.00 0.000000 0 1 getrandom
0.00 0.000000 0 1 rseq
------ ----------- ----------- --------- --------- ----------------
100.00 0.000075 3 22 1 total
آیا فقط ماشین حساب رو تست کردم؟
نه! من یک پوستهٔ (shell) و یک سرور http ساده هم نوشتم که اونها رو هم برسی کنم با این کتابخانه، سورسشون رو داخل کدبرگ خودم از لینک زیر میتونید ببینید.