محسن نوشته

توی لینوکس NameSpace ها چیکار میکنن
منتشر شده در: — Aug 12, 2019

وظیفه کرنل سیستم عامل اشتراک منابع بین پراسس ها هستش. این منابع میتونن نرم یا سخت باشن. بعنوان مثال ارتباطی که از طریق کرنل بین دو پردازه ایجاد میشه و ما به اسم IPC یا Inter Process Communication میشناسیمش یه جور منبع نرمه و دسترسی پراسس ها به کارت شبکه هم میتونه مثالی برای منبع سخت باشه.

واقعیت امر اینه که روی منایع سخت یک لایه نرم افزار قرار میگیره. این لایه توی کرنل سیستم عامل قرار داره و ما این لایه ها را بعنوان Kernel Subsystem میشناسیم. هر کدوم از این زیر سیستم ها یه پشته نرم افزاری هستن که مثلا برای زیر سیستم شبکه ما به اسم Network Stack میشناسیم. هر پشته مجموعه ای از چند لایه نرم افزارن که هر کدوم وظایف خاصی را انجام میدن. اما مهمترین برآیند این وظایف، اینه که یک Abstraction از سخت افزار در اختیار پراسس ها قرار بگیره. با این تفاسیر وقتی میگیم منبع سخت منظورمون واقعا دسترسی مستقیم به مولفه های مثلا کارت شبکه نیست و مثلا اینکه پراسس خودش بره ثبات های کارت شبکه را دست بزنه منظورمون نیست، بلکه منظورمون ارتباط پراسس با لایه Abstractionی هستش که کرنل سیستم عامل برای استفاده از یک منبع در اختیار پراسس قرار میده.

با این مقدمه هر دو نوع منابعی که در اختیار پراسس ها قرار داده میشه تهش با Abstraction های سیستم عامل تبدیل به موجودیت های نرم میشن. حالا یه سوال مهم پیش میاد: اینکه کرنل سیستم عامل با چه روشی این منابع را بین پراسس ها ایزوله میکنه؟ بعنوان مثال: اگه ما بخواهیم ۵۰٪ زمان CPU را به یک پراسس و الباقیشو به سایر پراسس ها تخصیص بدیم، کرنل چطور میتونه کمکمون کنه؟ یا اینکه اگه کمکمون میکنه مکانیزم این کار چیه؟

برای اینکه یه مقدار مغزآشوبی ایجاد کنم به این فکر کنیم که چطور سیستم عامل میتونه توی دسترسی به فایل ها بین پراسس ها ایزولاسیون ایجاد کنه. مثلا ما دو تا پراسس داشته باشیم که هر کدوم فایل سیستم خودشونو داشته باشن و این دو فایل سیستم کاملا از هم ایزوله باشن! با این تفاسیر ما باید دنبال مکانیزمی از کرنل باشیم که با اون مکانیزم کرنل بتونه Abstractionهای منابعی که در اختیار پراسس ها قرار میگیره از هم ایزوله کنه!

قبل اینکه به جواب برسیم، ببینیم چنتا از این Abstraction ها همین الان روی کرنل لینوکس میتونن وجود داشته باشن. من توی ادامه این موارد را لیست و توضیح مختصری در حد حوصله این متن میزارم:

حالا که با این Abstraction ها آشنا شدیم میتونیم به این سوال پاسخ بدیم که کرنل با چه مکانیزمی تصویری که هر پراسس از این Abstraction ها داره را کنترل میکنه؟ NameSpaceها درواقع قابلیتی از کرنل هستن که برای پاسخ به این سوال ایجاد شدن و کمک میکنن هر پراسس بتونه ویوی ایزله خودشو از Abstractionهای سیستم عامل تجربه کنه، به همین سادگی!

حالا ببینیم کنسول لینوکس چطور میتونه توی درک این موضوع بهمون کمک کنه. یه کنسول باز کنید و دستور زیر را روش بزنید:

ls -l /proc/$$/ns

توی این دستور $$‍‍ شناسه یا PID پراسس bash هستش (البته اگه ازش استفاده میکنید) که داره دستوراتی که روی کنسول میزنید را اجرا میکنه. برای اینکه مطمئن بشید، میتونید دستور زیر را استفاده کنید:

1
2
3
ps -p $$
  PID TTY          TIME CMD
10616 pts/4    00:00:00 bash

خروجی دستور اول روی سیستم من:

total 0
lrwxrwxrwx 1 mohsen mohsen 0 Aug 12 15:28 cgroup -> 'cgroup:[4026531835]'
lrwxrwxrwx 1 mohsen mohsen 0 Aug 12 15:28 ipc -> 'ipc:[4026531839]'
lrwxrwxrwx 1 mohsen mohsen 0 Aug 12 15:28 mnt -> 'mnt:[4026531840]'
lrwxrwxrwx 1 mohsen mohsen 0 Aug 12 15:28 net -> 'net:[4026531993]'
lrwxrwxrwx 1 mohsen mohsen 0 Aug 12 15:28 pid -> 'pid:[4026531836]'
lrwxrwxrwx 1 mohsen mohsen 0 Aug 12 16:33 pid_for_children -> 'pid:[4026531836]'
lrwxrwxrwx 1 mohsen mohsen 0 Aug 12 15:28 user -> 'user:[4026531837]'
lrwxrwxrwx 1 mohsen mohsen 0 Aug 12 15:28 uts -> 'uts:[4026531838]'

حالا میتونید ببینید که پراسسی که bash شما را اجرا میکنه (PID: 10616) با چه عینکی (NameSpace) داره Abstractionها سیستم عامل را مشاهده میکنه.

حالا میخوام یه کنسول جدید باز کنید و کنسول قبلی را باز نگه دارید. توی کنسول جدید میخوام یه عینک جدید به پراسسی که bash را اجرا میکنه بزنیم. بنابراین دستور زیر را روی کنسول دوم وارد کنید:

sudo unshare -u bash

این دستور پراسس جدید ایجاد میکنه و بهش میگه برنامه bash را اجرا کنه. سوئیچ u- به کرنل دستور میده که این پراسس را توی NameSpace جدیدی برای UTS-Abstraction اجرا کنه. اگه بخوام انتزاعی تر بگم: یعنی به پراسس ایجاد شده یه عینک بزن که بتونه فقط UTS-Abstraction خودشو ببینه.

دستور زیر را بزنید و ببینید که یه پراسس باPID متفاوت ایجاد شده:

1
2
3
ps -p $$
  PID TTY          TIME CMD
12516 pts/4    00:00:00 bash

حالا NameSpaceهای پراسسی که bash کنسول دوم را اجرا میکنه بینیم:

ls -l /proc/$$/ns
total 0
lrwxrwxrwx 1 root root 0 Aug 12 16:38 cgroup -> 'cgroup:[4026531835]'
lrwxrwxrwx 1 root root 0 Aug 12 16:38 ipc -> 'ipc:[4026531839]'
lrwxrwxrwx 1 root root 0 Aug 12 16:38 mnt -> 'mnt:[4026531840]'
lrwxrwxrwx 1 root root 0 Aug 12 16:38 net -> 'net:[4026531993]'
lrwxrwxrwx 1 root root 0 Aug 12 16:38 pid -> 'pid:[4026531836]'
lrwxrwxrwx 1 root root 0 Aug 12 16:38 pid_for_children -> 'pid:[4026531836]'
lrwxrwxrwx 1 root root 0 Aug 12 16:38 user -> 'user:[4026531837]'
lrwxrwxrwx 1 root root 0 Aug 12 16:38 uts -> 'uts:[4026533008]'

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

حالا روی کنسول دوم دستور زیر را اجرا کنیم:

hostname moqijoon
hostname

دستور اول مقدار hostname را به moqijoon تغییر میده و دستور دوم مقدار hostname را بهمون نشون میده. حالا دستور hostname را روی کنسول اول اجرا کنید:

hostname

جالبه برای من اینه:

MyMint

چی شد؟ دو تا کنسول روی یک ماشین دو تا hostname متفاوت میبینن! مگه میشه؟ مگه داریم؟ میدونیم که پراسس هایی که این دو کنسول را اجرا می کنن توی دو تا UTS مختلف قرار دارند. بنابراین میتونن ویوی متفاوتی از Abstraction مربوط به این NameSpace تجربه کنن.

پیروز باشید.