کپی-در-نوشتن

از ویکی‌پدیا، دانشنامهٔ آزاد

کپی-در-نوشتن (به انگلیسی Copy-on-Write)، که گاهی از آن به عنوان اشتراک‌گذاری ضمنی[۱] یا سایه‌زنی[۲] یاد می‌شود، یک تکنیک مدیریت منابع است که در برنامه‌نویسی رایانه‌ای برای پیاده‌سازی مؤثر عملیات «تکراری» یا «کپی» بر روی منابع قابل تغییر استفاده می‌شود.[۳] اگر منبعی کپی شده باشد اما تغییری در آن ایجاد نشده باشد، می‌توان منبع را بین کپی و اصل به اشتراک گذاشت و نیازی به نسخه برداری از منبع نیست. در حالی که ایجاد تغییر در منبع همچنان نیازمند کپی است و طبق این تکنیک: عملیات کپی تا اولین نوشتن به تعویق می‌افتد. با به اشتراک گذاشتن منابع از این طریق، می‌توان با اضافه کردن سربار کمی در تغییرات منابع، مصرف منابع نسخه‌های بدون تغییر را به میزان قابل توجهی کاهش داد.

در مدیریت حافظه مجازی[ویرایش]

اصلی‌ترین کاربرد کپی-در-نوشتن در به اشتراک گذاری حافظه مجازی برای فرایند‌های سیستم عامل، در اجرای فراخوانی سیستم است. فرایندها معمولاً بدون هیچ تغییری در حافظه بلافاصله یک فرایند جدید را اجرا می‌کنند و فضای آدرس را به‌طور کامل جایگزین می‌کند؛ بنابراین، کپی کردن تمام حافظه فرایند در طول یک فراخوانی سیستمی بیهوده خواهد بود و در عوض از تکنیک کپی-در-نوشتن استفاده می‌شود.

با استفاده از جدول صفحه و تعیین صفحاتی از حافظه به عنوان صفحات فقط خواندنی و شمارش تعداد ارجاعات به صفحه، می‌توان تکنینک کپی-در-نوشتن را به‌طور مؤثری پیاده‌سازی کرد. هنگامی که داده‌ها در این صفحات نوشته می‌شود، هسته سیستم عامل این کار را متوقف می‌کند و یک صفحه فیزیکی جدید را که با داده‌های کپی-در-نوشتن مقداردهی اولیه می‌شود، اختصاص می‌دهد. اگرچه اگر تنها یک ارجاع وجود داشته باشد، می‌توان از تخصیص صرف نظر کرد. سپس هسته، جدول صفحه را با صفحه جدید (قابل نوشتن) به روز می‌کند، تعداد ارجاع‌ها را کاهش می‌دهد و نوشتن را انجام می‌دهد. تخصیص صفحهٔ جدید تضمین می‌کند که تغییر در حافظه یک فرایند در فرایند دیگر قابل مشاهده نیست.

تکنیک کپی-در-نوشتن را می‌توان برای پشتیبانی از تخصیص حافظه کارآمد با داشتن صفحه ای از حافظه فیزیکی پر از صفر گسترش داد. هنگامی که حافظه جدید تخصیص داده می‌شود، تمام این صفحات تخصیص داده شده به همان صفحهٔ پر از صفر اشاره می‌کنند و همه به صورت کپی-در-نوشتن علامت گذاری می‌شوند. به این ترتیب، تا زمانی که داده‌ها نوشته نشده باشند، حافظه فیزیکی برای فرایند تخصیص داده نمی‌شود، و به فرایندها اجازه می‌دهد تا حافظه مجازی بیشتری نسبت به حافظه فیزیکی ذخیره کنند و در خطر تمام شدن فضای آدرس مجازی، از حافظه به‌صورت پراکنده استفاده کنند. این الگوریتم ترکیبی، مشابه صفحه‌بندی تقاضا است.[۴]

صفحات کپی-در-نوشتن نیز در ویژگی ادغام همان صفحه هسته لینوکس استفاده می‌شود.[۵]

در نرم‌افزار[ویرایش]

کپی-در-نوشتن همچنین در کتابخانه، برنامه و کد سیستم استفاده می‌شود.

مثال‌ها[ویرایش]

کلاس رشتهای که توسط کتابخانه استاندارد C++ در استاندارد اولیه C++98 ارائه شده بود به‌طور خاصی طراحی شده بود تا امکان پیاده‌سازی کپی-در-نوشتن را فراهم کند،[۶] اما در استاندارد جدیدتر C++11 این‌طور نیست:[۷]

std::string x("Hello");

std::string y = x;  // x and y use the same buffer.

y += ", World!";    // Now y uses a different buffer; x still uses the same old buffer.

در زبان برنامه‌نویسی PHP، همه typeها به جز ارجاع‌ها به صورت کپی-در-نوشتن پیاده‌سازی می‌شوند. به عنوان مثال، رشته‌ها و آرایه‌ها با مرجع ارسال می‌شوند، اما در صورت تغییر، اگر تعداد ارجاع آن‌ها صفر نباشد، کپی می‌شوند. این به آن‌ها اجازه می‌دهد تا به‌عنوان انواع ارزش‌ها بدون مشکلات عملکردی کپی در مقدار دهی یا تغییرناپذیر کردن آن‌ها عمل کنند.[۸]

در فریم ورک کیوت بسیار از typeها کپی-در-نوشتن هستند(«به‌طور ضمنی به اشتراک گذاشته شده» در کیوت). کیوت از عملیات مقایسه و تعویض اتمی برای افزایش یا کاهش شمارنده مرجع داخلی استفاده می‌کند. از آنجایی که کپی‌ها ارزان هستند،typeهای کیوت اغلب می‌توانند با خیال راحت توسط چندین رشته بدون نیاز به مکانیسم‌های قفل مانند انحصار متقابل استفاده شوند؛ بنابراین، مزایای کپی-در-نوشتن در هم در سیستم‌های تک نخی و هم در سیستم‌های چند رشته‌ای معتبر است.[۹]

در ذخیره‌سازی کامپیوتر[ویرایش]

کپی-در-نوشتن می‌تواند به عنوان روش اساسی برای برگرفت (snapshot)ها استفاده شود، مانند مواردی که توسط مدیریت حجم منطقی، سیستم‌های فایل مانند Btrfs و ZFS ,[۱۰] و سرورهای پایگاه داده مانند Microsoft SQL Server ارائه می‌شوند. برگرفت‌ها معمولاً فقط داده‌های اصلاح‌شده را ذخیره می‌کنند و نزدیک به نسخه اصلی ذخیره می‌شوند، بنابراین آنها فقط یک شکل ضعیف از پشتیبان‌گیری افزایشی هستند و نمی‌توانند جایگزین یک نسخه پشتیبان کامل شوند.[۱۱]

جستارهای وابسته[ویرایش]

منابع[ویرایش]

  1. "Implicit Sharing". Qt Project. Retrieved 4 August 2016.
  2. Rodeh, Ohad (1 February 2008). "B-Trees, Shadowing, and Clones" (PDF). ACM Transactions on Storage. 3 (4): 1. CiteSeerX 10.1.1.161.6863. doi:10.1145/1326542.1326544. S2CID 207166167. Archived from the original (PDF) on 2 January 2017. Retrieved 4 August 2016.
  3. Bovet, Daniel Pierre; Cesati, Marco (2002-01-01). Understanding the Linux Kernel. O'Reilly Media. p. 295. ISBN 978-0-596-00213-8.
  4. Bovet, Daniel Pierre; Cesati, Marco (2002-01-01). Understanding the Linux Kernel. O'Reilly Media. p. 295. ISBN 978-0-596-00213-8.
  5. Abbas, Ali. "The Kernel Samepage Merging Process". alouche.net. Archived from the original on 8 August 2016. Retrieved 4 August 2016.
  6. Meyers, Scott (2012). Effective STL. Addison-Wesley. pp. 64–65. ISBN 978-0-13-297918-4.
  7. "Concurrency Modifications to Basic String". Open Standards. Retrieved 13 February 2015.
  8. Pauli, Julien; Ferrara, Anthony; Popov, Nikita (2013). "Memory management". PhpInternalsBook.com. Retrieved 4 August 2016.
  9. "Threads and Implicitly Shared Classes". Qt Project. Retrieved 4 August 2016.
  10. Kasampalis, Sakis (2010). "Copy-on-Write Based File Systems Performance Analysis and Implementation" (PDF). p. 19. Retrieved 11 January 2013.
  11. Chien, Tim. "Snapshots Are NOT Backups". Oracle.com. Oracle. Retrieved 4 August 2016.