در رایانش، sigaction تابعی است که در استاندارد پازیکس تعریف شدهاست و برنامهنویس میتواند به کمک آن تعیین کند که برنامه در هنگام دریافت کردن یک سیگنال از طرف سیستمعامل، چه عکسالعملی از خود در برابر آن سیگنال نشان دهد.[۱][۲] برنامهها معمولاً در هنگام دریافت کردن یک سیگنال، میتوانند تابعی خاص را اجرا کنند که به آن روال وقفهگیر میگویند.[۱][۲]
در سیستمعاملهای شبه یونیکس و سیستمعاملهای سازگار با استاندارد پازیکس، سیگنالها یکی از روشهای برقراری ارتباط بین فرایندی هستند. هنگامی که یک واحد اجرایی (فرایند یا ریسه) سیگنالی از طرف سیستمعامل دریافت میکند، باید با توجه به نوع سیگنال دریافتی، واکنش مناسبی از خود نشان دهد. (مثلاً از دادهها روبرداری کند، به اجرا خاتمه دهد، چیزی را همگام کند و ...)
فراخوان سیستمی sigaction() به منظور تعریف کردن رفتار برنامه در هنگام دریافت کردن یک سیگنال غیر رزرو شده در سیستم، استفاده میشود. برای انجام این کار، یک ساختار داده به فراخوان سیستمی sigaction() ارسال میشود که این ساختار داده، در کنار برخی چیزهای دیگر، حاوی یک اشارهگر به تابعی است که این تابع باید در هنگام دریافت سیگنال اجرا شود (همانطور که گفته شد، به این تابع روال وقفهگیر گفته میشود). برخی از سیگنالها از قبل در سیستم رزرو شدهاند و برنامه نمیتواند رفتار پیشفرض آنها را تغییر دهد و این سیگنالها مستقیما توسط سیستم اداره میشوند و برنامه در اداره کردن آنها نقشی ندارد. سیگنال SIGKILL از جمله سیگنالهای رزرو شدهاست.[۳]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#define NUMCHLDS 10
void sigchld_handler(int, siginfo_t*, void*);
sig_atomic_t nexitedchlds = 0;
int
main(int argc, char *argv[])
{
struct sigaction act;
memset(&act, 0, sizeof(struct sigaction));
sigemptyset(&act.sa_mask);
act.sa_sigaction = sigchld_handler;
act.sa_flags = SA_SIGINFO;
if (-1 == sigaction(SIGCHLD, &act, NULL))
{
perror("sigaction()");
exit(EXIT_FAILURE);
}
for (int i = 0; i < NUMCHLDS; i++)
{
switch(fork())
{
case 0:
return 0;
/* NOTREACHED */
case -1:
write(STDERR_FILENO, "fork ERROR!", 11);
exit(EXIT_FAILURE);
/* NOTREACHED */
default:
printf("Child created\n");
}
}
while(1)
{
if (nexitedchlds < NUMCHLDS)
pause();
else
exit(EXIT_SUCCESS);
}
return 0;
}
void
sigchld_handler(int signo, siginfo_t *sinfo, void *context)
{
pid_t proc;
while ((proc = waitpid(-1, NULL, WNOHANG)) > 0)
{
/* signal main thread */
nexitedchlds++;
/* note: printf() is not signal-safe!
* don't use it in a signal handler.
*/
printf("sinfo->si_pid = %ld\nproc = %ld\n",
(long)sinfo->si_pid, (long)proc);
}
}