System Calls

nerdprogrammer بدون دسته بندی

پروسس ها برای در خواست یک سری خدمات همانند دریافت Resource بیشتر،ساختن پروسس جدید، و موارد بسیار دیگر،از system call ها استفاده می کنند.در واقع این نیاز تنها به دلیل این است که پروسس در user space می باشد و برای دریافت بعضی موارد نیازمند درخواست هایی به سمت کرنل است.برای دیدن لیستی از سیستم کال ها می توانید از دستور زیر استفاده کنید :

$ man 2 syscalls

Trap چیست؟

در مفهوم محاسباتی و کامپیوتر معمولا Trap به error هایی همانند تقسیم عددی بر 0 یا دسترسی نامعتبر به حافظه تفسیر می شود.اما در مفاهیم مربوط به syscall ها trap سبب می شود که پروسس بتواند به kernel mode سوییچ کند.Trap هنگام تغییر mode یک وقفه (Interrupt) ایجاد می کند و پروسس فعلی suspend می شود که دلیل آن خارج شدن از منطقه user space و منتقل شدن به kernel space است و همچنین دسترسی به حافظه ایست که پروسس در حالت عادی به آن دسترسی نداشته است.برای دریافت اطلاعات بیشتر به اینجا مراجعه کنید.

قبل از آن که در مورد جزئیات کار syscall ها صحبت کنیم چند نکته کلی را باید در مورد system call ها بدانیم :

  • سیستم کال ها state پردازنده را از user mode به kernel mode تغییر می دهند و این سبب می شود که پردازنده به مموری کرنل دسترسی پیدا کند.
  • هر سیستم کال با یک عدد unique و ثابت شناخته می شود.در برنامه ها معمولا با این اعداد کاری نخواهید داشت و اسم syscall را صدا می زنید.این نام ها در هدر unistd.h تعریف شده اند.
  • هر سیستم کالی می تواند یک سری آرگومان دریافت کند که شامل اطلاعات خاصی است.سیستم کال این آرگومان را از user space به kernel space پاس می دهد.

در این ۳ نکته دیدی کلی از syscall ها پیدا کردیم اما از دید یک برنامه نویس،syscall ها قالبی مشابه با فراخوانی تابع در زبان C دارند.سیستم کال ها برای انجام کارشان چندین مرحله را طی می کنند:

  1. ابتدا،نرم افزار syscall را با قالب تابع در سی ایجاد میکند.این تابع به نوعی یک wrapper برای syscall می باشد.
  2. این تابع ایجاد شده باید تمامی آرگومان های syscall را به trap-handler پاس دهد.این آرگومان ها با استفاده از stack منتقل می شوند.اما کرنل نیازمند آن است که این آرگومان ها در رجیستر های خاصی از CPU قرار گیرند.تابع wrapper این کار را انجام می دهد.
  3. از آن جایی که تمامی syscall ها از یک روش برای ورود به kernel space استفاده می کنند کرنل نیازمند یک شناسه برای syscall های مختلف است.اتفاقی که در این مرحله رخ می دهد این است که تابعی که یک wrapper برای syscall بود مقدار و عدد حقیقی syscall را در یکی از رجیستر CPU کپی می کند. (در ۶۴ بیت : rax ، در ۳۲ بیت eax و …)
  4. تابع wrapper اینستراکشن مربوط به trap را اجرا می نماید. (INT 0x80)،که سبب می شود پردازنده از User Mode به Kernel mode سوییچ کند و کدی که در آدرس 0x80 به آن اشاره شده است (trap vector) را اجرا نماید که البته در معماری های x86-32 اینستراکشنی تحت عنوان sysenter ایجاد شده است که راه سریع تری برای سوییچ کردن از User mode به Kernel Mode است به نسبت trap.
  5. در پاسخ trap به آدرس 0x80 کرنل تابع system_call را که در فایل اسمبلی entry.S داخل سورس کرنل تعریف شده است برای handle کردن trap فراخوانی می کند.این handler چندین وظیفه دارد:
    • مقدار داخل رجیستر ها را در kernel stack نگهداری کند.
    • عدد syscall را اعتبار سنجی کند.
    • syscall service routine را فراخوانی کند که با استفاده از عدد مربوط به syscall پیدا می شود(متغیر sys_call_table در کرنل).اگر syscall service routine آرگومان خاصی نیاز داشته باشد ابتدا اعتبار آن ها را می سنجد و سپس فرآیند ترنسفر شدن داده ها بین kernel space و user space صورت می گیرد.در نهایت service routine نتیجه را به تابع system_call بر می گرداند.
    • بازگرداندن مقدار Register ها از کرنل استک و قرار دادن return value سیستم کال در stack.
    • بازگشت به تابع wrapper و یا به عبارتی بازگشت به user space.
  6. اگر return value سیستم کال به منظور error بود،تابع wrapper متغیر گلوبال errno را با آن مقدار دهی می کند.در غیر این صورت،فعالیت syscall تمام می شود.
مراحل اجرای یک سیستم کال

پاسخی بگذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *