Copy on Write یا COW
سیستم عامل چطور بدون کپی کردن همه چیز fork میسازه
توی پست های قبلی گفتیم وقتی fork اجرا میشه یک Child Process ساخته میشه
در نگاه اول شاید فکر کنیم سیستم عامل این کارو میکنه
Parent Process
│
▼
کپی کامل حافظه
│
▼
Child Process
یعنی کل حافظه Parent رو برمیداره و دوباره برای Child کپی میکنه
ولی این کار یه مشکل بزرگ داره
فرض کن Parent چند گیگابایت حافظه استفاده کرده
اگه سیستم عامل هر بار که fork اجرا میشه کل حافظه رو کپی کنه
زمان زیادی مصرف میشه
RAM زیادی مصرف میشه
CPU
هم بیخودی درگیر کپی کردن اطلاعات میشه
ولی این بار سیستم عامل یه کم عاقل تر عمل میکنه
راه حل Copy on Write یا COW
سیستم عامل میگه
فعلا چیزی رو کپی نکنید
بعد از fork در ابتدا Parent و Child میتونن از همون Page های حافظه استفاده کنن
به صورت ساده
Physical Memory
│
┌─────────┴─────────┐
│ │
Parent Child
│ │
└─────────┬─────────┘
│
Shared Page
تا وقتی هیچکدوم چیزی رو تغییر نداده باشن لازم نیست یه نسخه جدا ساخته بشه
حالا اگه یکی از اونها بخواد چیزی رو تغییر بده چی میشه
فرض کنید Parent و Child اول کار این مقدار رو دارن
int x = 10
حالا Child میخواد این کارو انجام بده
x = 20
اینجا سیستم عامل متوجه میشه Child میخواد Page مشترک رو تغییر بده
پس تقریبا این اتفاق میفته
قبل از تغییر
Parent
│
▼
┌──────────────┐
│ Page x = 10 │
└──────────────┘
▲
│
Child
یعنی فعلا هر دو به همون Page دسترسی دارن
حالا Child میخواد روی اون Page چیزی بنویسه
سیستم عامل کل حافظه رو کپی نمیکنه
فقط همون Page ای که لازم شده رو کپی میکنه
بعد نتیجه تقریبا این شکلی میشه
Physical Memory
┌──────────────────────┐
│ Page x = 10 │
│ Parent │
└──────────────────────┘
┌──────────────────────┐
│ Page x = 20 │
│ Child │
└──────────────────────┘
پس Parent همچنان x برابر 10 داره
و Child نسخه خودش رو داره که x برابر 20 شده
به همین دلیل اسمش شده Copy on Write
یعنی وقتی نیاز به نوشتن پیش اومد کپی کن
چرا این روش خیلی مهمه
چون توی خیلی از برنامه ها Child بلافاصله بعد از fork میره سراغ exec
یعنی
fork
│
▼
Child
│
▼
exec
یادتون هست exec چیکار میکرد
برنامه فعلی رو با یه برنامه جدید جایگزین میکرد پس اگه سیستم عامل قبل از exec کل حافظه Parent رو کپی میکرد ممکن بود مقدار زیادی از اون حافظه اصلا هیچ وقت استفاده نشه
با COW اتفاق به شکل ساده اینطوریه
fork
│
▼
فعلا حافظه کامل کپی نمیشه
│
▼
Child اجرا میشه
│
▼
exec
│
▼
Program جدید جایگزین میشه
در نتیجه مقدار زیادی زمان و حافظه ذخیره میشه
پشت صحنه چه اتفاقی میفته
بعد از fork سیستم عامل میتونه Page های Parent و Child رو به صورت Shared نگه داره
ولی این Page ها رو برای نوشتن محافظت میکنه
حالا اگه یکی از Process ها بخواد روی همچین Page ای بنویسه
Write Attempt
│
▼
CPU detects protected write
│
▼
Page Fault
│
▼
Kernel handles it
│
▼
Copy the Page
│
▼
Give the writer its own Page
│
▼
Continue execution
یعنی Page Fault همیشه به معنی خراب شدن برنامه نیست
گاهی Page Fault کاملا یه اتفاق طبیعی توی مدیریت حافظه است
این موضوع وقتی برسیم به Virtual Memory و Paging خیلی بیشتر به کارمون میاد
یه نکته مهم
فرض کنید یه برنامه توی Parent یه متغیر رو تغییر میده و انتظار دارید Child هم مقدار جدید رو ببینه
اگه Parent و Child دو Process مستقل باشن معمولا این انتظار درست نیست
بعد از اینکه یکی از Process ها به خاطر COW اون Page رو تغییر بده هر کدوم نسخه خودشون رو دارن
یعنی
Parent Memory
│
▼
Separate Page
Child Memory
│
▼
Separate Page
پس:
Parent Memory ≠ Child Memory
این موضوع برای تحلیل برنامه های چندپردازه ای مهمه
مثلا موقع Debugging ممکنه Parent و Child اول کار رفتار مشابهی داشته باشن
ولی بعد از اینکه یکی از اونها حافظه خودش رو تغییر داد مسیرشون از هم جدا میشه
COW
رو با Shared Memory اشتباه نگیرید
این دوتا شبیه هم به نظر میان ولی یکی نیستن
در COW
اول
│
▼
Post #1714
39
- ❤ 1