سی‌گروپس
cgroups (مخفف control groups به معنی گروه‌های کنترلی) یک قابلیت هستهٔ لینوکس است که منابع مجموعه‌ای از فرایندها را مدیریت و مجزاسازی می‌کند.
نسخه‌ی دوم سی‌گروپس در سال ۲۰۱۶ به همراه کرنل نسخه ۴.۵ منتشر شد. Tejun Heo مسئول طراحی و بازنویسی مجدد سی‌گروپس بوده است.
cgroup مکانیسمی برای سازمان‌دهی سلسله‌مراتبی پردازه‌ها و اختصاص منابع سیستم در طول این سلسله‌مراتب است. این ویژگی از دو قسمت اصلی تشکیل شده است: هسته و کنترل‌کننده‌ها . وظیفه‌ی اصلی هسته سازمان‌دهی پردازه‌ها در یک ساختار سلسله‌مراتبی است. کنترل‌کننده‌ها نیز وظیفه‌ی توزیع یک منبع خاص سیستم در طول این سلسله‌مراتب را دارند.
این سلسله‌مراتب تشکیل یک درخت را می‌دهد. یعنی یک cgroup می‌تواند فرزند یک cgroup دیگر باشد. هر پردازه درون دقیقا یک cgroup قرار می‌گیرد. هنگام ساخت پردازه‌ی جدید این پردازه درون cgroup پدر خود قرار می‌گیرد ولی می‌تواند به cgroup های دیگر مهاجرت کند. کنترل‌کننده‌ها نیز می‌توانند روی یک cgroup فعال یا غیرفعال شوند. در صورت فعال شدن یک کنترل‌کننده روی یک گروه، تمامی فرزندان این گروه که می‌تواند شامل cgroup های دیگر باشد تحت تاثیر قرار می‌گیرند.
هر cgroup یک پوشه مربوط به خود دارد که در آن فایل‌هایی که اطلاعات گروه را نگه می‌دارند ذخیره می‌شود. در زیر تعدادی از این فایل‌ها به اختصار ذکر شده است:از بین کنترل‌کننده‌هایی که برای cgroup ها وجود دارند می‌توان به کنترل‌کننده‌های CPU ،Memory ،IO ، Writeback و PID اشاره کرد. با فعال‌کردن هر کدام از کنترل‌کننده‌ها فایل‌هایی با پیشوند کنترل‌کننده به پوشه‌ی فرزندان cgroup اضافه می‌شوند و در آن‌ها می‌توان تنظیمات مربوط به منابع را انجام داد.
برای توزیع منابع بین گروه‌ها چهار روش وجود دارد که به دوتا از آن‌ها اشاره می‌کنیم: یکی از آن‌ها با استفاده از وزن است؛ یعنی به هر گروه فرزند یک عدد نسبت داده می‌شود و منبع بر اساس نسبت این اعداد به مجموع توزیع می‌شود. این روش در توزیع CPU کاربرد دارد. روش دیگر محدود کردن منبع است؛ یعنی برای هر گروه یک مقدار بیشینه تعیین شود که مقدار استفاده‌ی آن از منبع از آن مقدار بیشتر نشود. به طور مثال برای توزیع IO می‌توان از این نوع تخصیص استفاده کرد. با استفاده از این ویژگی می‌توان تمام تسک‌های موجود در یک سی‌گروپس را به طور موقت متوقف کرد. این ویژگی برای cgroup v2 در هسته‌ی لینوکس نسخه 5.2 اضافه شده است.
قابلیت فریزر cgroup در که در آن‌ها مدیر یک سیستم می‌خواهد مجموعه‌ای از کارها رو هم‌زمان شروع یا متوقف کند کاربرد دارد. این گونه برنامه‌ها به خصوص در خوشه‌های استفاده می‌شوند که در آن‌ها تعداد زیادی گره مختلف به صورت توزیع شده وجود دارند.
از سیگنال‌های کنترلی SIGSTOP و SIGCONT نیز می‌توان برای توقف یا ادامه دادن یک پردازه استفاده کرد. اما مشکل این سیگنال‌ها این است که می‌توانند توسط پردازه‌ی پدر مشاهده شوند و برنامه‌هایی مثل یا در صورت استفاده از این سیگنال‌ها برای متوقف کردن و ادامه دادن برنامه دچار مشکل می‌شوند.
این قابلیت هم‌چنین می‌تواند برای حالت‌برداری از برنامه‌ها استفاده شود. با فریز کردن یک cgroup می‌توان پردازه‌های آن را به یک حالت غیرفعال برد و از آن‌ها یک تصویر ذخیره کرد و/یا با استفاده از رابط‌های کرنل اطلاعات مورد نظر درباره‌ی آن‌ها را ذخیره کرد و پس از آن با درآوردن cgroup از حالت فریز شده آن‌ها را دوباره فعال کرد.
برای پیاده‌سازی این قابلیت داده ساختار زیر به cgroups-defs.h اضافه شده است: struct cgroup_freezer_state {
این داده ساختار به داده ساختار cgroup با عنوان freezer اضافه شده است. هم چنین در پرچم‌های cgroup دو بیت به codice_1 و codice_2 اختصاص داده شده است که به ترتیب نشان‌دهنده‌ی این هستند که cgroup باید فریز شود یا خیر و آیا cgroup فریز شده است یا خیر. به داده ساختار codice_3 نیز یک پرچم frozen اضافه شده که مشخص می‌کند تسک فریز شده است یا خیر.
در JOBCTL یک تله برای فریز کردن یک تسک در نظر گرفته شده است. تابع codice_4 مسئول رسیدگی به این تله است. در این تابع پس از اطمینان از این که سیگنال یا تله‌ی پراهمیت دیگری که به آن‌ها رسیدگی نشده باشد وجود نداشته باشد تابع codice_5 را صدا می‌زند که در ادامه توضیح داده خواهد شد. پس از آن نیز تابع codice_6 صدا زده می‌شود که پرچمی را در تسک ست می‌کند که در زمان‌بندی شرکت داده نشود و سپس تسک بعدی را زمان‌بندی می‌کند.
تابع codice_6 پیش از پیاده‌سازی فریزر cgroup نیز وجود داشته است و به طور مثال برای خوابیدن برای مدت زمان خاص در تابع codice_8 یا خوابیدن در صف در تابع codice_9 استفاده شده است. در نتیجه برای این که تسک‌های فریز شده در زمان‌بند زمان‌بندی نشوند نیازی به تغییرات در زمان‌بند وجود ندارد.
در تابع codice_5 پرچم frozen تسک در صورتی که یک نباشد یک می‌شود و بعد از زیاد کردن تعداد تسک‌های فریز شده‌ی cgroup تسک، تابع codice_11 برای cgroup صدا زده می‌شود: void cgroup_update_frozen(struct cgroup *cgrp)
در این تابع بررسی می‌شود که آیا یک cgroup باید به حالت frozen دربیاید یا خیر. یک cgroup باید فریز شود اگر پرچم codice_1 آن یک باشد و تعداد تسک‌های فریز شده‌ی آن با تعداد کل تسک‌های زیردرختش برابر باشد. در صورتی که وضعیت یک cgroup از فریز شده به نشده یا بلعکس تغییر کرده باشد این تغییر در فایل مربوط به رخدادهای آن نوشته می‌شود و هم چنین یک تابع به نام codice_13 صدا زده می‌شود که وظیفه‌ی آن انتشار وضعیت cgroup به اجداد آن است تا تعداد تسک‌های فریز شده‌ی آن‌ها نیز تغییر کند و در صورت لزوم وضعیت فریز بودن یا نبودن آن‌ها در فایل رخدادهایشان به‌روزرسانی شود.
هنگامی که تغییری در فایل cgroup.freeze که در قسمت اول ذکر شد صورت بگیرد تابع codice_14 اجرا می‌شود. این تابع در صورتی که مقدار نوشته شده در فایل معتبر، یعنی صفر یا یک باشد تابع  cgroup_freeze(cgrp, freeze) را صدا می‌زند. در این تابع به ازای هر کدام از گروه‌ها در زیردرخت cgrp مقدار codice_15 که در واقع تعداد فریزهای انجام شده روی یک گروه است بسته به یک یا صفر بودن freeze یکی زیاد یا کم می‌شود. در صورتی که این مقدار قبلا بزرگ‌تر از صفر بوده باشد و اکنون نیز بزرگ‌تر از بماند یعنی cgroup پیش از این نیز در حالت فریز قرار داشته است و لازم نیست کاری انجام شود. در غیر این صورت تابع cgroup_do_freeze(cgrp, freeze) صدا زده می‌شود که در این تابع پرچم codice_1 مقداردهی می‌شود و پس از آن به ازای هر تسک داخل cgroup تابع codice_17 اجرا می‌شود.
لازم به ذکر است که پردازه‌های کرنل (kthreads) قابلیت فریز شدن ندارند و هر جایی که بخواهد تغییری در وضعیت تسک صورت بگیرد این نکته چک می‌شود و این پردازه‌ها کنار گذاشته می‌شود.
در تابع codice_17 در صورتی که که تسک در حال فریز شدن باشد پرچم codice_19 مربوط به jobctl را یک می‌کند و با استفاده از codice_20 به پردازه اعلام می‌کند که یک سیگنال برای رسیدگی دارد. هنگامی که پردازه شروع به اجرا کند به سیگنال گفته شده با استفاده از تابع codice_4 که در بالا توضیح داده شد رسیدگی می‌کند و به حالت خواب می‌رود. در صورتی که تسک در حال بیرون آمدن از حالت فریز شدن باشد پرچم ذکر شده صفر می‌شود و با استفاده از تابع codice_22 تسک بیدار می‌شود.
هنگامی که یک تسک بیدار می‌شود اگر پرچم frozen آن یک بوده باشد یعنی به تازگی از حالت فریز بیرون آمده است که در این صورت تابع codice_23 صدا زده می‌شود. در این تابع پس از کاهش تعداد بچه‌های فریزشده‌ی cgroup تابع codice_11 صدا زده می‌شود که پیش‌تر توضیح داده شد و هم چنین پرچم frozen تسک را نیز صفر می‌کند.
نکته‌ی آخر فرایند مهاجرت یک تسک از یک cgroup به دیگری است. هنگامی که یک تسک به cgroup ای برود که فریز شده است متوقف می‌شود. هم چنین اگر یک تسک از یک cgroup فریز شده به گروه غیر فریز برود از حالت فریز بیرون می‌آید. برای پیاده‌سازی این قسمت در تابع codice_25 که برای مهاجرت تسک‌ها استفاده می‌شود تابع codice_26 صدا زده می‌شود. در این تابع پس از کاهش و افزایش تعداد تسک‌های فریز شده‌ی cgroup مبدا و مقصد، تابع codice_11 برای هر دوی مبدا و مقصد صدا زده می‌شود. در نهایت نیز cgroup_freeze_task(task, test_bit(CGRP_FREEZE, &dst->flags)); صدا زده می‌شود که باعث می‌شود تسک با توجه به وضعیت cgroup مقصد (dst) به حالت مناسب برود.