سیگنالها وقفههایی (interrupt) هستند که از جانب سیستم عامل به یک پروسس (process) تحویل داده میشوند و میتوانند یک برنامه را به صورت دائمی پایان دهند. میتوان با فشردن کلید Ctrl+C در لینوکس، یونیکس، Mac OS X یا ویندوز یک وقفه ایجاد کرد.
سیگنالهایی وجود دارند که یک برنامه نمیتواند آنها را دریافت کند. اما لیستی از سیگنالها در زیر آمده است که برنامه توانایی دریافت آنها و ایجاد واکنش مناسب نسبت به آنها را دارد. این سیگنالها در هدرفایل <csignal> تعریف شدهاند.
ردیف |
سیگنال و توصیف آن |
1 |
SIGABRT خاتمه غیرعادی یک برنامه، مانند فراخوانی abort. |
2 |
SIGFPE یک عملیات ریاضی نادرست، مانند تقسیم بر صفر یا عملیات منجر به سرریزی (overflow). |
3 |
SIGILL شناسایی یک دستور غیرمجاز. |
4 |
SIGINT دریافت یک سیگنال interactive attention. |
5 |
SIGSEGV یک دسترسی غیرمجاز به حافظه. |
6 |
SIGTERM ارسال یک درخواست پایان برنامه به خود برنامه. |
تابع ()signal
کتابخانه مدیریت سیگنالها تابع signal را برای مدیریت رویدادهای غیرمنتظره فراهم کرده است. ساختار تابع signal در زیر آمده است.
void (*signal (int sig, void (*func)(int)))(int);
این تابع دو آرگومان دریافت میکند، اولین آرگومان، یک عدد صحیح بوده که شماره سیگنال را بیان میکند و آرگومان دوم یک اشارهگر به تابع مدیریت کننده سیگنال میباشد.
حال بیاید یک برنامه ساده ++C بنویسیم که با استفاده از تابع ()signal، سیگنال SIGINT را دریافت میکند. برای دریافت کردن هر سیگنالی، باید با استفاده از تابع signal خود سیگنال و تابع مدیریت کننده آن را ثبت کنید. مثال زیر این موضوع را روشن میکند.
#include <iostream> #include <csignal> using namespace std; void signalHandler( int signum ) { cout << "Interrupt signal (" << signum << ") received.\n"; // cleanup and close up stuff here // terminate program exit(signum); } int main () { // register signal SIGINT and signal handler signal(SIGINT, signalHandler); while(1) { cout << "Going to sleep...." << endl; sleep(1); } return 0; }
با اجرای این کد، خروجی زیر بدست میآید.
Going to sleep.... Going to sleep.... Going to sleep....
حال، کلید Ctrl+C را فشار داده تا در برنامه شما وقفه افتاده و نحوه دریافت سیگنال توسط برنامه و خروجی پس از آن را ملاحظه کنید.
Going to sleep.... Going to sleep.... Going to sleep.... Interrupt signal (2) received.
تابع ()raise
با استفاده از تابع ()raise میتوان یک سیگنال تولید کرد. این تابع یک آرگومان عدد صحیح به عنوان شماره سیگنال دریافت میکند. ساختار این تابع به صورت زیر است.
int raise (signal sig);
در این عبارت، sig میتواند شماره سیگنال یکی از این سیگنالهایی باشد که قصد تولید آن را داریم: SIGINT, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGTERM, SIGHUP.
در مثال زیر یک سیگنال را با استفاده از تابع ()raise ایجاد میکنیم.
#include <iostream> #include <csignal> using namespace std; void signalHandler( int signum ) { cout << "Interrupt signal (" << signum << ") received.\n"; // cleanup and close up stuff here // terminate program exit(signum); } int main () { int i = 0; // register signal SIGINT and signal handler signal(SIGINT, signalHandler); while(++i) { cout << "Going to sleep...." << endl; if( i == 3 ) { raise( SIGINT); } sleep(1); } return 0; }
با اجرای این کد، خروجی زیر حاصل شده و به صورت خودکار از برنامه خارج میشود.
Going to sleep.... Going to sleep.... Going to sleep.... Interrupt signal (2) received.
منبع: ترجمه از سایت tutorialspoint.com
امیدوارم آموزش مدیریت سیگنالها در ++C براتون مفید واقع شده باشه. اگر علاقمند بودید دیگر جلسات آموزش زبان ++C را هم مطالعه کنید.
اگر این نوشته برایتان مفید بود لطفا کامنت بنویسید.