فراخوانی سیستمی
امروزه قابلیتهای بسیار متنوعی از سمت سیستمهای عامل در اختیار برنامههای سیستمی است و برنامههای بزرگ که کاربران زیادی از آنها استفاده میکنند برای پیشرفت و افزایش کارایی خود باید این قابلیتها را در نظر بگیرند. به عنوان مثال ۲ برنامه را تصور کنید: یک برنامه وظیفهاش خواندن یک پرونده از جنس فیلم و نمایش آن است و برنامه دیگر وظیفهاش آن است که پخش زندهای که دادههایش از یک دوربین دریافت میشود را در اینترنت بارگزاری کند و نمایش دهد.
در سیستم عامل لینوکس یک فراخوانی سیستمی تحت عنوان madvise(2)
وجود دارد که به سیستم عامل رهنمودهایی دربارهٔ الگوی ارجاع برنامه به بخشهای مختلف حافظه میدهد.[۱] در برنامهٔ اول برنامهنویس میتواند با این فراخوانی سیستمی اعلام کند که ارجاع به حافظه به صورت پشت سر هم و به ترتیب است، بنابراین سیستم عامل میتواند بخشهای مختلف پروندهٔ فرد را قبل از دسترسی به آن در حافظه آورده تا در آیندهٔ نزدیک برنامه به آن دسترسی پیدا کند که به این عمل جلوخوانی میگویند. برخلاف برنامهٔ اول، در برنامهٔ دوم عملاً نمیدانیم که دسترسی به حافظه چگونه است، زیرا به صورت زنده دادهها دریافت میشود و جلوخوانی در دسترسی به حافظه کمکی به برنامه نمیکند. حال فرض کنید که بخواهیم در سیستم عامل این امکان را فراهم کنیم که یک پردازه بتواند این سیاستها را برای پردازهای دیگر مشخص کند.
در نسخهٔ ۵٫۱۰ لینوکس یک فراخوانی سیستمی با عنوان process_madvise(2)
به مجموعه فراخوانیهای سیستمی اضافه شدهاست که این نیاز را برای کاربر برطرف میکند.[۲]
ساختار
[ویرایش]این فراخوانی سیستمی ساختاری به صورت زیر دارد[۳]
#include <sys/uio.h>
ssize_t process_madvise(int pidfd, const struct iovec *iovec,
size_t vlen, int advice,
unsigned int flags);
برای آن که متوجه شویم این فراخوانی سیستمی چه کاری انجام میدهد ابتدا باید کمی با مفهوم توصیف کنندهٔ فایل شناسه پردازه (process id file descriptor) یا [./https://en.wikipedia.org/wiki/Pidfd pidfd] آشنا شویم.
میدانیم که در سیستمهای عامل از جمله لینوکس، پردازهها با یک شناسهٔ عددی مشخص میشوند. همچنین این شناسهها بازهٔ محدودی دارند؛ مثلاً در هستهٔ لینوکس مقدار پیشفرض برای تعداد پردازهها ۳۲۷۶۸ است.[۴]
این موضوع باعث میشود که سیستم عامل هنگامی که یک پردازه با شناسه پردازهای خاص به اتمام رسید، شناسهٔ آن را برای پردازههای بعدی استفاده کند.
این یعنی ممکن است پردازه A
، پردازه ای دیگر مانند B
را با شناسه اش که id_b
است در نظر بگیرد و پردازهٔ B
به اتمام برسد و بعد از مدتی پردازهای جدید مانند C
با همان شناسه پردازه یعنی id_b
ایجاد شود. در این حالت پردازه A
فقط id_b
را دارد و فکر میکند که این شناسه متناظر با B
است، حال آن که id_b
اکنون C
را مشخص میکند؛ بنابراین اگر A
هدفش ارتباط با B
بوده ممکن است به اشتباه با C
ارتباط برقرار کند. این موضوع ممکن است باعث بروز خطاهایی شود و گاهی امنیت را به خطر بیندازد.[۵]
مفهوم pidfd برای حل این مشکل ایجاد شده و هر پردازه بهطور یکتا با pidfd متناظر خود شناخته میشود.[۵]بنابراین ورودی اصلی process_madvise
یک pidfd است که پردازهٔ هدف را بهطور یکتا مشخص میکند.
فایده
[ویرایش]فرض کنید که در سیستم عامل تعدادی برنامه وجود دارد که خودشان اطلاعی از الگوهای استفادهشان از حافظه ندارند، ولی پردازهٔ دیگری وجود دارد که در نقش مدیر میتواند این الگوها را به دست بیاورد (چنین عملکردی بهطور خاص در سیستم عامل اندروید وجود دارد[۶]). در چنین شرایطی میتوان با استفاده از این فراخوانی سیستمی عملکرد پردازههای مختلف و همچنین کل سامانه را بهبود داد تا با بهترین سیاست از حافظه استفاده کنند.[۶]
عملکرد
[ویرایش]در حال حاضر این فراخوانی سیستمی تنها ۲ پرچم به عنوان راهنمای پردازهٔ هدف (advise
) دارد:[۳]
MADV_COLD
: این پرچم احتمال بازپسگیری بازه حافظهای که باiovec
[۷] مشخص شده را افزایش میدهد.[۱]MADV-PAGEOUT
: این پرچم سعی میکند که بخشهایی از حافظه که باiovec
مشخص شده را از حافظه خارج کند، مثلاً اگر بخشی مربوط به دادههای یک پرونده بود آن را به دیسک منتقل میکند و اگر امکان خارج کردن آن بخش از حافظه نبود، سیاست اعلامی را برای آن بخش نادیده میگیرد.[۱]
منابع
[ویرایش]- ↑ ۱٫۰ ۱٫۱ ۱٫۲ «madvise(2) - Linux manual page». man7.org. دریافتشده در ۲۰۲۱-۰۵-۱۴.
- ↑ «syscall_64.tbl - arch/x86/entry/syscalls/syscall_64.tbl - Linux source code (v5.10) - Bootlin». elixir.bootlin.com. دریافتشده در ۲۰۲۱-۰۵-۱۴.
- ↑ ۳٫۰ ۳٫۱ «process_madvise(2) - Linux manual page». man7.org. دریافتشده در ۲۰۲۱-۰۵-۱۴.
- ↑ «proc(5) - Linux manual page». man7.org. دریافتشده در ۲۰۲۱-۰۵-۱۴.
- ↑ ۵٫۰ ۵٫۱ «Toward race-free process signaling [LWN.net]». lwn.net. دریافتشده در ۲۰۲۱-۰۵-۱۴.
- ↑ ۶٫۰ ۶٫۱ «process_madvise(), pidfd capabilities, and the revenge of the PIDs [LWN.net]». lwn.net. دریافتشده در ۲۰۲۱-۰۵-۱۴.
- ↑ «Scatter-Gather (The GNU C Library)». www.gnu.org. دریافتشده در ۲۰۲۱-۰۵-۱۴.