یادگرفتن از یک پرسش: خطای محدودیت میزان حافظه limits.conf

یک مزیت بزرگ لینوکس برای من اینه که توش حل مشکلات می تونن منجر به چیز یاد گرفتن و پیشرفت مهارت ها و دانش آدم بشن. چنین چیزی وقتی راه حل همیشه «دوباره نصب کن» یا «فلان برنامه رو نصب و اجرا کن ببین مشکل حل می شه یا نه» باشه، اتفاق نمی افته. مثلا به این مورد نگاه کنین:

توی فروم فدورا اکبر پرسیده:

سلام خدمت دوستان
وقتی برنامه ardour 2.8.12 را اجرا میکنم پیغام زیر ظاهر میشه البته داخل پیام توضیحاتی داده که احتیاج اطلاعات تخصصی داره:

WARNING: Your system has a limit for maximum amount of locked memory. This might cause Ardour to run out of memory before your system runs out of memory.
You can view the memory limit with ‘ulimit -l’, and it is normally controlled by /etc/security/limits.conf

خب من جواب خیلی دقیق رو نمی دونم. ایده هایی در مورد لیمیت ها، page‌کردن در لینوکس و مدیریت حافظه دارم ولی این مورد به نظر چیز جالبی می یاد و فرصتی است برای یاد گرفتن. اول دستور ulimit رو با man ulimit یاد می گیرم. گفته با سوییچ a- میشه محدودیت ها رو دید. من مال خودم رو چک می کنم:

jadi@jubung:~$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 62804
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 62804
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

و می بینم که محدودیت لاک حافظه برای من ۶۴ کیلوبایت است. این یعنی کاربر من فقط حق داره ۶۴ کیلوبایت حافظه رو لاک کنه و احتمالا مربوط به تابع mlock توی برنامه نویسی. از اینجا شروع به سرچ می کنم و با ترکیب سرچ ها و خونده ها و اطلاعات شخصی ام به نتایج جالبی می رسم.

می دونیم که برنامه ها برای اجرا به حافظه احتیاج دارن. این حافظه معمولا از طریق تعریف متغیر و اینجور چیزها اشغال می شه و این سیستم عامل است که تصمیم می گیره چقدر از این اطلاعات رو واقعا توی مموری رم نگه داره و چقدر از اون رو page کنه توی swap. بذار یک کم برگردیم عقب.

لینوس که اولین بار کرنل رو نوشت، کامپیوترش مشکل کمبود رم داشت. حتی راحت نمی تونست بعضی چیزها رو کمپایل کنه. لینوس یک ابتکار زد – که البته شناخته شده بود ولی از یک کرنل دانشجویی انتظارش نمی رفت – و اونهم این بود که هر بار کامپیوتر رم کم می آورد، بخشی از رم فعلی که در این لحظه مورد استفاده نبود رو روی دیسک می نوشت و بعدا که رم خالی می شد راحت کارهاش رو می کرد و اگر هم در آینده کسی با اون بخش page out شده رم کار داشت، دوباره می رفت از رو دیسک اونو می خوند و می آورد توی رم تحویل برنامه محتاجش می داد. این یک انقلاب بود و خیلی از کسانی که اولین بار لینوکس رو می دیدن، شیفته این قابلیت می شد که می ذاشت شما روی یک کامپیوتر ضعیف، هر کار بزرگی رو با صبر و حوصله انجام بدین. در اصل با این ایده مفهوم «رم کم آوردن» دیگه از بین رفته بود.

همین حالا هم اون پارتیشن swap که درست می کنیم دقیقا کارش همینه. حتی اگر دستور top رو بزنی در دو خط آخر هدر این رو می بینی:

top - 11:00:56 up 1 day, 23:02,  5 users,  load average: 1.06, 1.08, 1.22
Tasks: 230 total,   2 running, 227 sleeping,   0 stopped,   1 zombie
Cpu(s):  9.2%us,  6.6%sy,  0.0%ni, 84.2%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   8062928k total,  7358752k used,   704176k free,   139228k buffers
Swap:  8395772k total,    59136k used,  8336636k free,  2854564k cached

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

اما ممکنه یک برنامه به هردلیلی بخواد جلوی اینکار رو بگیره و مطمئن باشه که براش فلان مقدار رم واقعی از پیش کنار گذاشته شده! تابع mlock اینکار رو می کنه. من می تونم موقع برنامه نویسی به سیستم عامل دستور بدم که «برای من یک مگ رم واقعی بذار کنار، به هیچ کس نده اونو و pageش هم نکن و بذار توی رم آماده به کار باشه». خب اینو همه برنامه ها دوست خواهند داشت از جمله برنامه ضبط صدای تو که چون داره صدای حرفه ای ضبط می کنه اصلا نباید منتظر دیسک و حافظه خالی نبودن و اینها باشه پس سعی می کنه وقتی می یاد بالا برای خودش یک حافظه اختصاصی درخواست کنه.

اما توی سیستم عامل دیدیم که گفتیم:‌

jadi@jubung:~$ ulimit -a | grep memory
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
virtual memory          (kbytes, -v) unlimited

یعنی محدودیتی برای کاربر گذاشتیم که کلا همه برنامه های این کاربر روی هم نتونن بیشتر از ۶۴ کیلوبایت حافظه رو تا لحظه که می خوان توی خود رم واقعی به خودشون اختصاص بدن. این عدد خیلی کوچیکه و در اصل معنی اش اینه که «کسی نمی تونه حافظه رو برای خودش برداره، سیستم عامل است که تقسیم می کنه بر اساس تشخیص خودش». اگر کسی دوست داشته این محدودیت رو به شکل موقت عوض کنه می زنه ulimit -l 1024 یا هر عدد دیگه و اگر بخواد برای همیشه اینو تغییر بده،‌ etc/security/limits.conf/ رو ادیت می کنه.

نکته: به جای عدد اگر بزنی 0 یعنی «نامحدود»

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