설명

sigaction() 함수는 signal() 보다 향상된 기능을 제공하는 시그널 처리를 결정하는 함수입니다. signal()에서는 처리할 행동 정보로 시그널이 발생하면 호출이될 함수 포인터를 넘겨 주었습니다. 그러나 sigaction()에서는 struct sigaction 구조체 값을 사용하기 때문에 좀더 다양한 지정이 가능합니다.

struct sigaction {
    void (*sa_handler)(int);    // 시그널을 처리하기 위한 핸들러. SIG_DFL, SIG_IGN 또는 핸들러 함수
    void (*sa_sigaction)(int, siginfo_t *, void *); // 밑의 sa_flags가 SA_SIGINFO일때 
// sa_handler 대신에 동작하는 핸들러
sigset_t sa_mask; // 시그널을 처리하는 동안 블록화할 시그널 집합의 마스크 int sa_flags; // 아래 설명을 참고하세요. void (*sa_restorer)(void); // 사용해서는 안됩니다. }

ss_flgs는 아래와 같은 값이 사용되며, OR 연산자로 여러 개를 동시에 지정하여 사용할 수 있습니다.

옵션 의미
SA_NOCLDSTOP signum이 SIGCHILD일 경우, 자식 프로세스가 멈추었을 때, 부모 프로세스에 SIGCHILD가 전달되지 않는다.
SA_ONESHOT
또는 SA_RESETHAND
시그널을 받으면 설정된 행도을 취하고 시스템 기본 설정인 SIG_DFL 로 재설정된다.
SA_RESTART 시그널 처리에 의해 방해 받은 시스템 호출은 시그널 처리가 끝나면 재시작한다.
SA_NOMASK
또는 SA_NODEFER
시그널을 처리하는 동안에 전달되는 시그널은 블록되지 않는다.
SA_SIGINFO

이 옵션이 사용되면 sa_handler대신에 sa_sigaction이 동작되며, sa_handler 보다 더 다양한 인수를 받을 수 있습니다. sa_sigaction이 받는 인수에는 시그널 번호, 시그널이 만들어진 이유, 시그널을 받는 프로세스의 정보입니다.

 

헤더 signal.h
형태 int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
인수
int signum 시그널 번호
struct sigaction *act 설정할 행동. 즉, 새롭게 지정할 처리 행동
struct sigaction *oldact 이전 행동, 이 함수를 호출하기 전에 지정된 행동 정보가 입력됩니다.
반환
0 성공
-1 실패

예제 1

이번 예제도 signal()에서 처럼 Ctrl-C 를 누르면 사용자 핸들러가 실행되었다가 두 번째 Ctrl-C 키를 누르면 기존 방법대로 프로그램이 종료되도록 해 보겠습니다.

#include <stdio.h>
#include <signal.h>

struct sigaction act_new;
struct sigaction act_old;

void sigint_handler( int signo)
{
   printf( "Ctrl-C 키를 눌루셨죠!!\n");
   printf( "또 누르시면 종료됩니다.\n");
   sigaction( SIGINT, &act_old, NULL);
}

int main( void)
{
   
   act_new.sa_handler = sigint_handler; // 시그널 핸들러 지정
   sigemptyset( &act_new.sa_mask);      // 시그널 처리 중 블록될 시그널은 없음
                                           
   // SIGINT를 지정하면서 act_old에 이전 정보를 구합니다.                                           
   sigaction( SIGINT, &act_new, &act_old); 
   while(1 )
   {
      printf( "forum.falinux.com\n");
      sleep( 1);
   }
}
]$ ./a.out
forum.falinux.com
forum.falinux.com
Ctrl-C 키를 눌루셨죠!!
또 누르시면 종료됩니다.
forum.falinux.com
forum.falinux.com

]$

예제 2

sigaction() 에서는 시그널 발생하여 처리 중일 때에는 다른 시그널이 발생하더라도 블록이 되도록 지정할 수 있습니다. Ctrl-C 키를 누르면 3초간 대기하도록 하는데, 이때 프로그램을 종료시키는 또다른 키인 Ctyrl-Z를 누르면 어떻게 되는지 보겠습니다.

#include <stdio.h>
#include <signal.h>

void sigint_handler( int signo)
{
   int   ndx;

   printf( "Ctrl-C 키를 눌루셨죠.\n");
   printf( "3초간 대기하겠습니다. 이때 Ctrl-Z키를 눌러 주세요.\n");

   for ( ndx = 3; 0 < ndx; ndx--){
      printf( "%d 초 남았습니다.\n", ndx);
      sleep( 1);
   }
}

int main( void)
{
   struct sigaction act;

   act.sa_handler = sigint_handler;  // 시그널 핸들러 지정
   sigfillset( &act.sa_mask);        // 모든 시그널을 블록

   sigaction( SIGINT, &act, NULL);
   while(1 )
   {
      printf( "forum.falinux.com\n");
      sleep( 1);
   }
}
]$ ./a.out
forum.falinux.com
forum.falinux.com
Ctrl-C 키를 눌루셨죠.
3초간 대기하겠습니다. 이때 Ctrl-Z키를 눌러 주세요.
3 초 남았습니다.
2 초 남았습니다.              <- Ctrl-Z 키를 누름
1 초 남았습니다.

[1]+  Stopped                 ./a.out
]$ 

3초간 대기 중에 프로그램을 종료하기 위해 Ctrl-Z 키를 눌러도 모든 시그널에 대해 블록 처리가 되어 바로 Ctrl-Z 처리가 안됩니다. 그러다가 시그널 처리가 완료되어 핸들러에서 복귀되면 그때서야 Ctrl-Z 가 처리되어 프로그램이 종료됩니다.