General setup – بخش اول
در اینجا ما شروع میکنیم به بررسی و توضیح هر مورد که در پیش رومون قرار داره. واقعیت اینه که من میخواستم این سلسله مطالب فقط در این حد باشه که کاربر رو اجمالی با موضوعات آشنا کنه. اما بنابر توصیه دوستان تصمیم گرفتم موضوعات رو تا حدی بشکافیم و از کدها و APIهای لینوکس هم درش بهره ببریم. پس به اتفاق هم میریم که شروع کنیم. من در این مطالب آپشن رو با فونت درشت و پارامتر مربوطه ش رو با فونت مونو مینویسم.
Compile also drivers which will not load [ ]
1 |
CONFIG_COMPILE_TEST |
در اینجا این انتخاب رو میتونید داشته باشید که درایورهایی رو کامپایل
کنید که نه لود میشه رو سیستم شما و نه قابل اجراست. هدف از این قسمت جنبه
تست کامپایله. چون عملا درایوری رو هم که با این آپشن کامپایل کنید براتون
کاربردی نخواهد داشت. ما این پارامتر رو انتخاب نمیکنیم.
با زدن کلید n از کرنلمون خارجش میکنیم.
یه توضیحی اینجا بدم اونم اینه که:
در menuconfig شکلهای خاصی وجود دارند.
علامت کروشه یا [ ] به معنی اینه که اون پارامتر فقط دو حالت y را n رو میپذیره.
پرانتز به معنی اینه که مقداری عددی یا رشته ای یا کاراکتری میپذیره.
این علامت <> هم به این معنیه که اون آپشن علاوه بر y و n، میتونه M
رو هم بپذیره. اگر آپشنی با m انتخاب بشه، بصورت ماجول کامپایل میشه.
Local version – append to kernel release ()
1 |
CONFIG_LOCALVERSION |
افزودن ورژن محلی به انتهای نسخه کرنل.
من در اینجا اینتر میزنم و lts_r1- رو وارد میکنم.
ازین ببعد تو کرنل خودم اگر uname -r رو بزنم در انتهای نسخه کرنل، عبارت
lts_r1- وجود داره. این عبارت این رو به من میفهمونه که کرنل من از شاخه
longterm است و اولین نسخهایه که کانفیگش کردم. در کانفیگهای آینده من اون
عدد رو هی افزایش میدم. این رو در نظر بگیرید که کانفیگ کرنل چیزی نیست که
یکبار انجام بدید و دیگه تموم شه تا ابد. هر سری شما قسمتی رو میسازید و
سری بعد میرید سراغ قسمتهای دیگه و بهبودش میدید. کانفیگ اول شما میشه میشه
سنگ بنای کانفیگ دوم و همینطور الی آخر. سعی نکنید در اولین کانفیگ یه
بیلد خیلی خفت از آب دربیارید. بیلد اولتون فقط در حدی باشه که بتونه بالا
بیاد کافیه. همیشه تو کرنل جا برای بهینه کردن هست.
Automatically append version information to the version string[]
1 |
CONFIG_LOCALVERSION_AUTO |
تعیین نسخه کرنل بصورت خودکار از روی درخت سورس با استفاده از تگهای git. من این رو انتخاب نمیکنم.
Build ID Salt ()
1 |
CONFIG_BUILD_SALT |
بیلد آیدی یک کد همتاست که هر باینری رو به اطلاعات دیباگ اون باینری مرتبط میکنه. بیلد آیدی یک رشته ۱۶۰ بیتی از نوع SHA1 است که با فلگ gcc –build-id برای باینریها و کتابخانهها ایجاد میشه.
افزودن salt به اون ID باعث میشه تا توزیعها بدونن اون بیلد در میان
سایر بیلدها واحد و بیهمتاست حتی اگر محتویات نسخه قبلی و فعلی اون باینری
ثابت باشه، افزودن salt باعث میشه بین هش دو فایل تفاوت وجود داشته باشه و
از دید توزیع یکتا باشه.
افزودن سالت کار سختی نیست اما من استفاده نمیکنم. چنانچه شما خواستید
استفاده کنید میتونید توش هرچیزی بنویسید. از شماره تلفنتون گرفته تا اسم
خودتون.
<— Kernel compression mode (Gzip)
اینجا یه منوی کشوییه. با زدن اینتر سایر گرینه ها رو میتونیم ببینیم.
یه توضیح کوچولو بدم:
در انتخاب مدل فشرده سازی باید بررسی کنید که چه چیزی رو میخواید. اگر کرنل
شما قراره درون یک دستگاه توکار قرار بگیره، مسلما حجم مهمه و باید خیلی
حواستون به نسبت فشرده سازیش باشه. در سیستم خونگی خودم، من مشکل ۲۰ مگ
کمتر و بیشتر در سایز کرنل ندارم، اما سرعتش برام مهمه. پس برمبنای سرعت
انتخاب میکنم.
کلا شیوههای فشردهسازی، الگوریتمهایی هستند که در آن طراح الگوریتم، بسته
به نحوه کاربرد در جایگاهی خاص، الگوریتم یا الگوریتمها رو طراحی میکنه.
الگوریتمهای فشرده سازی باید یک توازن منطقی بین حجم و سرعت برقرار کنند تا
ارزش استفاده رو داشته باشند. مثلا یک الگوریتم با کمرس ضعیف و زمان
طولانی برای کمپرس و دکمپرس توجیهی منطقی برای استفاده نداره.
در نگارشی از کرنل که ما مشغول کانفیگش هستیم، چند متد فشرده سازی وجود داره که بطور خلاصه یه نگاه بهشون میندازیم.
Gzip ()
1 |
CONFIG_KERNEL_GZIP |
متد gzip یه متد متعادل و حد وسط برای فشرده کردن کرنل است. متعادل از نظر توازن بین حد فشرده سازی و زمان لازم برای دکمپرس کردن. همچنین یک معیار نیز هست. ما سرعت و قدرت سایر متدها رو بر حسب این متد میسنجیم.
Bzip2 ()
1 |
CONFIG_KERNEL_BZIP2 |
کندترین متد در لیست ما همینه. اما کرنل رو ۱۰٪ از gzip فشردهتر میکنه.
LZMA ()
1 |
CONFIG_KERNEL_LZMA |
شدیدترین و خفنترین حد فشردهسازی رو lzma داره، ۳۳٪ فشرده تر از gzip! کندترین فشردهسازی هم متعلق به همین متده. سرعتش در دکمپرس کردن بین gzip و bzip2 است.
XZ ()
1 |
CONFIG_KERNEL_XZ |
سرعتش تقریبا اندازه LZMA است. سرعت دکمپرسش از bzip2 بهتره ولی به پای gzip نمیرسه. این متد هم کند فشرده میکنه.
LZO ()
1 |
CONFIG_KERNEL_LZO |
ضعیفترین حد فشرده سازی. سایز کرنلی که با این متد فشرده شده باشه، ۱۰٪ از gzip بزرگتره. ولی سریعترین متد نیز هست، چه در فشرده سازی و چه در دکمپرس کردن داره.
LZ4 (*)
1 |
CONFIG_KERNEL_LZ4 |
از حیث فشردهسازی از LZO بدتره. سایز کرنل منتج از خروجی این متد ۸٪ از LZO هم بیشتره. سرعت خوبی داره در هردوحالت، اما در دکمپرس کردن سرعتش حتی از LZO هم بیشتره.
من شخصا LZ4 رو انتخاب میکنم. شما انتخاب با خودتونه.
در ضمن با فشردن کلید اسپیس میتونید انتخاب کنید.
Default hostname ()
1 |
CONFIG_DEFAULT_HOSTNAME |
اگر دیسک زنده توزیعهای لینوکسی رو بالا آورده باشید، پیش ازینکه شما نام هاستتون رو تعیین کرده باشید یک hostname پیشفرض میبینید. مثلا:
در آرچ لینوکس:
1 |
root@archiso # |
یا در بعضی توزیعهای دیگر:
1 |
user@live $ |
hostname پیشفرض توزیعها از اینجا در کرنل توزیعتون تعریف شده.
Support for paging of anonymous memory (swap) []
1 |
CONFIG_SWAP |
آیا میخواهید سیستمتون swap داشته باشه؟ من میگم خیر ابدا و با فشردن یک اسپیس عطاش رو به لقاش میبخشم و اون ستاره رو ازش میگیرم.
اما swap چیه و چرا نمیخوامش؟
کرنل، آدرسهای موجود در RAM کامپیوتر رو به صفحات یا pageهایی تقسیم میکنه که دستورالعملها در اون قرار بگیرند. زمانی که رم کم بیاد، کرنل پیجهایی که در حال حاضر اولویت کمتری دارند، یا تشخیص میده که پروسههای دیگر، به زودی به اون نیاز ندارند رو، میبره در جایی از پیش تعیین شده بنام swap قرار میده و هروقت در رم فضای خالی ایجاد شد، کرنل پیجها رو از swap به رم منتقل میشه.
این ایده قشنگیه. اما پاشنه آشیل این متد، تفاوت فاحش سرعت رم و سرعت حافظه جانبیه. رم بسیار بسیار سریعتر از حافظههای جانبیه بهمین دلیل اگر شرایطی ایجاد بشه که کرنل مجبور به استفاده از swap بشه، سیستم کند میشه. فلسفه وجودی swap همونه که میگیم لنگه کفش در بیابان نعمته. یک پای آدم کفش داشته باشه بهتر از اینه که اصلا کفش نداشته باشه. این به این معنی نیست که یک لنگه کفش خوبه. بحث بین بد و بدتره. سیستم موقتا کند کار کنه و سرویس بده بهتره تا اصلا کار نکنه و از دسترس خارج بشه. خودِ swap به دو شکل قابل استفادهست. پارتیشن swap و فایل swap. برای اینکه بدانید سوَپ شما از نوع فایل است یا پارتیشن، از دستور:
1 |
swapon -s $ |
استفاده کنید. این دستور علاوه بر دادن اطلاعاتی در مورد سوَپ، در ستون type نوع سوَپ رو هم نشون میده. اما دلیل اینکه ازش استفاده نمیکنم اینه که تو همین کرنل میشه مکانیزمهای جالتری استفاده کرد. سریعتر و سبکتر از swap!
System V IPC [*]
1 |
CONFIG_SYSVIPC |
اینجا جای خطرناکیه. البته که میتونم با گفتن همین جمله مجابتون کنم که انتخابش کنید. ولی اگر دلیلشو بدونید خیلی بهتره.
کلا در هر سیتم عاملی پروسهها باید با همدیگه حرف بزنن.
زمانی که کمپانی AT&T نسخه یونیکس System V (بخونید سیستم فایو) رو
درColumbus UNIX ارائه داد، در اون از ۳ قابلیت پرده برداشت، که بنام sysv
ipc معروف شدند.
اما این ۳ قابلیت چه بود؟
۱- message queues
۲- semaphores
۳- shared memory
صف پیامها. صف چیه؟ کدوم پیامها؟
با یک مثال هر سه قابلیت SysV IPC رو شرح میدم تا بهتر درک کنیم.
فرض کنیم یک کتابخونه داریم با یک سالن مرکزی و ۱۰ تا اتاق مطالعه. یک
خانمی در سالن مرکزی وظیفش فقط اینه که به مراجعه کنندگان جا بده که بشینن
مطالعه کنن.
این خانم کارش به این صورته که فقط لیست جاهای خالی رو داشته باشه و خودش اون جاها رو نمیره ببینه.
اول اتاقهای مطالعه همگی خالی هستند. این خانم از روی لیستش میدونه ۱۰ جالی
خالی وجود داره. هر کسی مراجعه کنه، خانم بهش یک جا میده و یک جای خالی از
لیستش حذف میکنه. تا زمانی که هر ۱۰ اتاق اشغال شوند. هرکسی بیاد مطالعه
کنه باید بره تو صف تا جا خالی شه. خانم فقط از رو لیست کار میکنه. هرکس
مطالعش تموم بشه به خانم میگه که من کارم تموم شد و خانم هم تو لیستش یک
جای خالی رو باز میکنه و بعدی رو میفرسته تو. به این صف آدمها برای مطالعه،
در کامپیوتر، صف پیام میگن که همگی منتظرن پردازش بشن.
به این خانم که مسئولیت کنترل اتاقها رو بعده داره، در کامپیوتر، سِمافور یا نشانبر میگن.
حالا اگر شرایطی پیش بیاد که دو یا چند نفر بتونن بدون ایجاد مزاحمت و
ایجاد بن بست برای افراد دیگر، همزمان ازون اتاق استفاده کنند، مفهوم حافظه
اشتراکی یا shared memory رو در سیستم پیاده کردند. بنبست به حالتی میگن
که جفتشون جوری بخوان از منابع استفاده کنن که نه کار خودشون راه بیفته نه
شریکشون. یکی باید کوتاه بیاد.
اما هر کسی که عضو کتابخونه باشه باید شماره شناسایی داشته باشه که مسئول
کتابخونه(همون خانم) بتونه با چک کردن اون ورود شخص رو به اتاق مطالعه
تایید کنه. در کرنل این کار رو تابعی بنام ()ftok انجام میده که برای هر
پیغام یه توکِن میسازه. هر توکن مثل شماره ملی افراد، یکتاست.
خب اول APIهای SysV IPC رو ببینیم بعد به تفصیل توضیح بدیم.
رابط | صفوف پیام | سمافور(نشانبر) | حافظه اشتراکی |
---|---|---|---|
فایلهای هدر | <sys/msg.h> | <sys/sem.h> | <sys/shm.h> |
ساختار داده مرتبط | msqid_ds | semid_ds | shmid_ds |
ایجاد/بازکردن عضو | ()msgget | ()semget | ()shmget()+shmat |
بستن عضو | هیچ | هیچ | ()shmdt |
عملیات کنترل | ()msgctl | ()semctl | ()shmctl |
اعمال IPC | نوشتن پیغام—()msgsnd خواندن پیغام—()msgrcv | بررسی/تنظیم سمافور—()semop | دسترسی به حافطه در ناحیه اشتراکی |
فرض کنیم یک پروسه میخواد پیغامی بفرسته. بررسی کنیم ببینیم این کار به چه طریقی صورت میگیره:
اول از همه باید اینو بدونیم که هر پیغامی از هر پروسهای اول به بافرِ پیغام منتقل میشه. بافرِ پیغام مثل همون سالن مرکزی انتظار کتابخونهست. کسی که از راه میاد باید بیاد اینجا بره تو صف. بافر پیغام در فایل هدر sys/msg.h تعریف شده است. در این فایل دو عضو مهم تعریف شده اند:
1 2 3 4 5 |
/* message buffer for msgsnd and msgrcv calls */ struct msgbuf { long mtype; /* type of message */ char mtext[1]; /* message text */ }; |
۱- نوع پیام یا mtype بر دو نوع است:
الف) پیغام خصوصی: با استفاده از IPC_PRIVATE
ب)پیغام عمومی: یا استفاده از یک عدد صحیح مثبت
۲- متن پیغام یا mtext از نوع کاراکتری. در نظر داشته باشید که mtext علاوه بر نوع داده کاراکتری میتواند حاوی هر نوع دادهای باشد.
اما خود کرنل نیز فریمورکی برای مدیریت بافر پیامها داره. این فریمورک شامل ۴ بخشه:
1 2 3 4 5 6 7 |
/* one msg structure for each message */ struct msg { struct msg *msg_next; /* next message on queue */ long msg_type; char *msg_spot; /* message text address */ short msg_ts; /* message text size */ }; |
۱- msg_next: یک اشاره گر به پیغام بعدی در بافر
۲- msg_type: اینجا کرنل بر حسب نوع پیغامی که که قبلا در mtype تعریف کردیم، نوع پیام را تشخیص و مدیریت میکنه.
۳- msg_spot: اشارهگری که به ابتدای پیغاممون اشاره میکند.
۴- msg_ts: طول پیغامی که وارد بافر شده است.
ساختار msqid_ds در کرنل
هر کدوم از این ۳ آبجکت IPC(صف پیغامها، سمافور و خافظه اشتراکی)، ساختار دادهای خاص خودشون رو دارند که بوسیله کرنل تعیین میشه. برای صف پیغامها، این ساختار msqid_ds است. کرنل برای هر تمام صف پیامهایی که در سیستم ساخته میشود یک الگو ساخته و ذخیره میکند. این ساختار در sys/msg.h تعریف شده است:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/* one msqid structure for each queue on the system */ struct msqid_ds { struct ipc_perm msg_perm; struct msg *msg_first; /* first message on queue */ struct msg *msg_last; /* last message in queue */ time_t msg_stime; /* last msgsnd time */ time_t msg_rtime; /* last msgrcv time */ time_t msg_ctime; /* last change time */ struct wait_queue *wwait; struct wait_queue *rwait; ushort msg_cbytes; ushort msg_qnum; ushort msg_qbytes; /* max number of bytes on queue */ ushort msg_lspid; /* pid of last msgsnd */ ushort msg_lrpid; /* last receive pid */ }; |
در اینجا درباره هرکدم از اعضای این ساختار توضیحاتی میدم:
۱- msg_perm: یک الگو از ساختار ipc_perm که در linux/ipc.h تعریف شده است.این ساختار اطلاعاتی درباره مجوزهای صف پیغام را نظیر: مجوزهای دسترسی، دادههایی درباره سازنده صف، uid و غیره را نگهداری میکند.
۲- msg_first: اشارهگری که به اولین پیغام در صف اشاره میکند.( راس لیست)
۳- msg_last: اشارهگری که به آخرین پسغام لیست در صف اشاره میکند.(ته لیست)
اما اینا برای چیه؟ برای اینکه کرنل در بهینهترین حالت لیست پیغامها رو آدرسدهی کنی. اشارهگر اضافه نسازه. حافظه بیهوده اشغال نکنه. چون واقعیت اینه که کرنل خیلی بهینه ساخته شده. دلیل دیگرش جلوگیری از segmentation fault است. segfault حالتیه که برنامه سعی کنه در ناحیهای از حافظه بنویسه از از اون ناحیه بخونه در حالی که طبق مجوزهای دسترسیش به اون ناحیه غیر قانونیه و اون ناحیه به اون تخصیص داده نشده.
۴- msg_rtime: برچسب زمانی آخرین باری که پیغامی از صف بازیابی شده است.
۵- msg_ctime: برچسب زمانی آخرین باری که تغییری(Change) در صف داده شده است.
۶و۷- wwait , rwait: اشارهگرهایی به صف انتظار کرنل. زمانی که صف پیغامها پر باشد و جایی برای پیغام جدید نباشد، پیغامهای جدید به خواب میروند. کرنل با استفاده از این دو اشارهگر ردشونو میگیره تا وقتی صف خالی شد بیدارشون کنه بیان تو صف.
۸- msg_cbytes: جمع کل بایتهای کل پیغامهای موجود در صف.
۹- msg_qnum: تعداد کل پیغامهایی که اکنون در صف هستند.
۱۰- msg_qbytes: حداکثر سایز صف بر حسب بایت.
۱۱- msg_lspid: آیدی پروسهای(PID) که آخرین پیغام رو فرستاده.
۱۲- msg_lrpid: آیدی پروسهای که آخرین پیغام را بازیابی کرده است.
ساختار ipc_perm در کرنل
کرنل مجوزهای هر عضو از اعضای سهگانه IPC رو در ساختار ipc_perm ذخیره میکنه. ساختار ipc_perm به این شکل است:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/* one msqid structure for each queue on the system */ struct msqid_ds { struct ipc_perm msg_perm; struct msg *msg_first; /* first message on queue */ struct msg *msg_last; /* last message in queue */ time_t msg_stime; /* last msgsnd time */ time_t msg_rtime; /* last msgrcv time */ time_t msg_ctime; /* last change time */ struct wait_queue *wwait; struct wait_queue *rwait; ushort msg_cbytes; ushort msg_qnum; ushort msg_qbytes; /* max number of bytes on queue */ ushort msg_lspid; /* pid of last msgsnd */ ushort msg_lrpid; /* last receive pid */ }; |
۱- key: کلید IPC یک عضو که همراه با دیگر دادههای اون عضو ذخیره میشه. این کلید همون کد ملی یا شماره شناسایی خودمونه در مثال کتابخونه. اگر این کلید از قبل در کرنل وجود نداشته باشه دیگه نمیتونه تطبیق داده بشه و به پیغام جواب رد داده میشه. همچنان اگر کسی عضو کتابخونه باشه باید شماره شناساییش در سیستم کتابخونه موجود باشه.
۲- uid: شناسه کاربری یا آیدی مالک پیغام.
۳- gid: شناسه گروه مالک پیغام.
۴- cuid: شناسه کاربری سازنده پیغام.
۵- cgid: شناسه گروه سازنده پیغام.
۶- mode: شروط دسترسی به پیغام که به شرح زیره:
الف) R : اگر پروسهای روی سیسکال ()msgrcv در حال انتظاره.
ب) S : اگر پروسهای روی سیسکال ()msgsnd در حال انتظاره.
ج) D : اگر حافظه اشتراکی مرتبط حذف شده باشد.
د) C : اگر با اولین الصاق پروسه به سگمنت حافظه اشتراکی، حافظه اشتراکی پاک میشه.
ه) – : چنانچه هیچکدام از فلگهای بالا تنظیم نشده باشه.
فلگهای زیر بصورت ۳ بیتی بکار میروند.مثلا -wr
و) r : اگر اجازه خواندن دارد.
ز) w : اگر اجازه نوشتن داده شده باشد.
ح) a : اگر اجازه تغییر(alter)داده شده باشد.
ط) – : اگر هیچکدام از مجوزهای بالا داده نشده باشد.
سیسکال یا فراخوانی سیستمی ()msgget
تعریف سیسکال از زبان ویکیپدیا:
هرگاه یک نرمافزار سطح کاربر نیاز به دسترسی به منابع سیستم و سخت افزار را داشته باشد، یکی از توابع درون سیستم عامل را فراخوانی میکند. که به این عمل فراخوان سیستمی میگویند فراخوان سیستمی را گاه فراخوان هستهای (kernel call) نیز مینامند چرا در اکثر پردازندههای مدرن (مثلا معماری x86), برای انجام فراخوان سیستمی پردازنده باید در حالت مد هسته (kernel mode) باشد. به زبانی دیگر هیچ برنامهای حق دسترسی مستقیم به سختافزار را ندارد و باید توسط واسطهای که سیستمعامل در اختیارش قرار میدهد و نامش فراخوان سیستمی است به سختافزار سیستم دسترسی پیدا نماید.
در حقیقت فراخوان سیستمی پس از مدیریت منابع، دومین هدف اصلی یک سیستم عامل میباشد.
سیستم عامل استفاده از رایانه را ساده میسازد. این بدان معناست که مثلاً کاربر یا برنامه نویس بدون درگیر شدن با مسائل سخت افزاری دیسکها، به راحتی پروندهای را بر روی دیسک ذخیره و حذف کند. این کار در واقع با به کار بردن دستورهای سادهای که فراخوانهای سیستمی را صدا میزنند انجام میپذیرد.
در صورت عدم وجود سیستم عامل، کاربر یا برنامهنویس میبایست آشنایی کاملی با سخت افزارهای مختلف رایانه (مثل صفحه نمایش ،دیسکهایگردان، صفحه کلید و غیره) داشته باشد و روتینهایی برای خواندن یا نوشتن آنها به زبانهای سطح-پائین بنویسد. از این جنبه گاه، به سیستم عامل با عنوان ماشین توسعه یافته یا ماشین مجازی یاد میشود که واقعیت سخت افزار را از دید کاربران مخفی میسازد.
حالا بریم سراغ ()msgget:
برای ساخت یک صف پیام یا دسترسی به صف پیام موجود از سیسکال ()msgget استفاده میکنیم.
ساختار این سیسکال رو باز میکنیم:
پروتوتایپ:
1 |
int msgget ( key_t key, int msgflg ); |
این تابع مثل هر تابعی ۲ حالت داره. یا موفقه یا شکست میخوره.
۱- اگر موفق باشه شناسه صف پیام رو بعنوان مقدار return برمیگردونه.
۲- اگر شکست بخوره مقدار ۱- رو برمیگردونه که خودش چند حالته:
الف) EACCES: اجازه دسترسی داده نشد.
ب) EEXIST: صف موجود است. نمیشه بسازیش.
ج) EIDRM: صف برای حذف شدن تیک خورده است.
د) ENOENT: همچین صفی وجود نداره.
ه) ENOMEM: حافظه کافی برای ایجاد صف وجود نداره.
و) ENOSPC: صف به حداکثر اندازه خود رسیده است و جای خالی ندارد.
اولین آرگومانی که به تابع ()msgget صادر کردهایم مقدار کلید است. این مقدار همون مقدار بازگشتی از تابع ()ftok است که توکن رو به ما برمیگردوند. این کلید یا کلیدی که تو بحث ipc_perm توضیح دادیم مطابقت داده میشه. در این حالت اجازه بازکردن یا دسترسی به عملیات بر عهده آرگومان دوم میفته. اینجا msgflg بر حسب تطابق کلید و مجوز درخواست وارده، از روی فلگهای mode اجازه کار رو به درخواست میده.
IPC_CREAT: اگر صف مورد نظر وجود نداشته باشه صف رو میسازه.
IPC_EXCL: چنانچه با IPC_CREAT بکار برده بشه، اگر صف قبلا وجود داشته باشه، ارور EEXIST رو برمیگردونه.
اگر IPC_CREAT به تنهایی به کار برده بشه، یه صف میسازه و شناسه اون صف رو برمیگردونه. چنانچه صف از قبل وجود داشته باشه، مقدار شناسه اون صف موجود رو برمیگردونه.
اگر IPC_EXCL همرا با IPC_CREAT بکار برده بشه، باز هم صف جدید ساخته میشه. اما اگر صف از قبل وجود داشته باشه ارور میده. استفاده از IPC_EXCL به تنهایی بی معنیه و عملا بلااستفاده است. اما وقتی با IPC_CREAT بکار برده میشه، میتونه تضمین بده که هیچ صفی برای دسترسی باز نشده است.
دسترسیهای IPC علاوه بر حالت کاراکتری میتونه حالت اوکتال هم باشه. مثلا ——-rw- رو میتونیم بصورت ۰۶۶۰ نشون بدیم.
با یک مثال اینها رو بررسی کنیم:
1 2 3 4 5 6 7 8 9 10 11 |
int open_queue( key_t keyval ) { int qid; if((qid = msgget( keyval, IPC_CREAT | 0600 )) == -1) { return(-1); } return(qid); } |
به تابع ()open_queue مقدار کلید رو پاس دادیم و ازش میخوایم که شناسه صف رو بهمون برگردونه. شناسه صف یک عدد صحیحه. خودِ مقدار qid رو با سیسکال ()msgget بدست میاریم. میگیم این کلید رو بکیر که کرنل بهمون اجازه کار بده. کلید که تطبیق داده شد، آرگومان دوم تعریف کار و مجوزهای دسترسیه. میگیم یه صف برامون ایجاد کن با این دسترسی. قبلا گفتیم اگر IPC_CREAT صف رو بسازه مقدار شناسه صف رو بر میگردونه. اگر هم صف از قبل وجود داشته باشه باز هم شناسهشو برمیگردونه. اما یه شرط(if) هم براش گذاشتیم. گفتیم به شرطی که به ارور نخوره. چرا به ارور بخوره؟ چون ممکنه کلید تایید نشه یا ممکنه دسترسی اجازه هیچ کاری نداشته باشه.
سیسکال یا فراخوانی سیستمی ()msgsnd
خب در قسمت قبل ما با نحوه ساخت صف پیغام آشنا شدیم. موردی که الان منطقی به نظر میرسه اینه که چجوری پیغاممون رو به صف بفرستیم. برای این منظور از سیسکال ()msgsnd استفاده میکنیم.
با هم پروتوتایپ و API این تابع رو بررسی میکنیم.
پروتوتایپ:
1 |
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); |
شکل کلی این سیسکال به این صورته:
1 2 3 |
#include <sys/types.h> #include <sys/msg.h> int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); |
حالا تک تک عناصر این پروتوتایپ رو بررسی میکنیم:
۱- ()int msgsnd : این تابع یک مقدار از نوع عدد صحیح برمیگردونه. چنانچه موفق باشد ۰ و در صورت شکست ۱- رو برمیگردونه.
۲- msqid : گفتیم که کد شناسایی پیام مثل کد ملی هر فرد یکتاست. این پارامتر کد یکتای شناساگر پیغامه.
۳- msgp* : اشارهگری که به بافر صف اشاره میکنه.
۴- msgsz : اندازه پیغام برحسب بایت.
۵- msgflg : فلگ یا پرچم پیغاممون. میتونیم براش فلگ تعیین کنیم یا نکنیم. اگر بجای نوع فلگ ۰ بزاریم تابع نوع فلگ رو نادیده میگیره. اما میتونیم فلگهایی رو هم به قرار زیر براش قرار بدیم:
الف) IPC_NOWAIT : با این فلگ به کرنل میگیم که اگر صف پر بود کنترل رو به پروسه فراخوانی کننده برگردون. اگر این فلگ رو تعریف نکنیم، چنانچه صف جای خالی نداشته باشه، کرنل پروسه فراخوانی کننده رو موقتا بلاک میکنه تا صف جای خالی پیدا میکنه.
کرنل BSD در نسخههای ابتدایی خودش از سوکتها بجای sysv ipc استفاده میکرد.
کرنل لینوکس همزمان قابلیت پشتیبانی و کارکردن با هردوشون رو داره.
همچنین در کرنل لینوکس یک نوع دیگر از ipc بنام POSIX message queue وجود داره که هنوز بطور کامل استانداردسازی نشده.
خود کلمه IPC مخفف Inter Process Communication بمعنی ارتباطات بین پروسه هاست. اگر این رو از انتخاب خارج کنید، سیستمتون فلج میشه. چون پروسهها قدرت ارتباط با همدیگه رو از دست میدن.
پس مابقی چه شد؟
لطفا ما رو منتظر نذار.
موضوعت جذابه داره منو می خوره
اگه قصد ترجمه نداری لطفا منابع رو به اشتراک بگذار :)))
سلام و ارادت.
اولا خدمتتون عرض کنم من در کنار این کار امورات زندگیمم هست که باید برگزار کنم. چه من و چه مدیر سایت بصورت رایگان مطلب مبنویسیم پس نباید توقع داشته باشید که پارت بیزینسی زندگیمونو کنار بزاریم.
مسئله دوم اینکه من اولش خدممتون عرض کردم که خود کانفیگ کرنل مطالب کمی داره و در عرض ده روز تموم میشه. اما دوستان گفتن عمقی برو لایههای برنامهنویسی و APIهاش رو هم توضیح بده که همین کارو دارم میکنم.
موضوع بعدی آموزش C است که در کنار کرنل دارم پیش میبرم.
و اینکه من برای C و کرنل دارم شکل و اینا آماده میکنم که خیلی زمانبره.
و در آخر اینکه دستم مجروح شده برای همین نبودم. الانم با باند پیچی تایپ میکنم. پارت ۷ کرنل امشب تکمیل میشه و میریم سراغ پارت ۸.
ممنونم که به مطالب سایت توجه دارید.
سلام خدمت titanstrix
از نظر موضوع و شیوهی نگارش عالی است منتظر قسمتهای بعدی هستم.
لطفا تصویر هم قرار دهید.
موفق باشید.
سلام به شما دوست عزیز.
نظر لطفتونه و باعث دلگرمی. منظورتون چه تصویریه؟ چون عموما این مطالب تصویری نیستند. حتی فیزیکی هم نیستند که بشه کشیدشون. اگر منظورتون تصاویر شماتیکه که حتما سعی میکنم بگذارم اما بعد از توصیحات کامل. فعلا این بحث IPC ادامه داره و بعد از تکلمیلش فکر میکنم با مثالهایی که میزنم و کدهایی که بینهایت ساده و روان تشریح میکنم، کاملا براتون قابل لمس و درک باشه اصل قضیه.
سلام و تشکر بابت این ۷ مقاله کرنل…
خاستم بدونم فقط همین ۷ مقاله ست یا بازم ادامه داره؟
سلام. بستگی به بازخوردها داره. اگر کاربران سایت تشخیص بدن که خوبه قطعا ادامه خواهد داشت. هرچند که فعلا قصدم ادامه دادنه چنانچه مشکل یا گرفتاری پیش نیاد.