본문 바로가기
UNIX 프로그래밍

[7주차 개념] 시그널

by 서영선 2023. 11. 10.

 

🚩 signal

 

: software interrupt

  • kernel → process or process → process
  • 자료 전송보다는 비정상적인 상황을 알릴 때 사용
  • 예) program 수행 중 Ctrl + C ( Interrupt key )

         →  kernel이 문자 감지, 해당 session에 있는 모든 process 에게 "SIGINT"라는 signal을 보냄

         →  모든 process는 종료! 그러나, shell process는 무시! 

  • signal은 <signal.h>에 정의
  • signal의 기본 처리
1. 종료 (signal에 의한 정상 종료)
2. 코어 덤프 후 종료 (signal에 의한 비정상 종료) - core file (종료 직전의 memory의 상태) 생성 후 종료
3. 중지
4. 무시

 

 

 

 

🚩 child process의 종료 상태 확인

 

pid = wait(&status);
if(WIFEXITED(status)){             # 정상 종료
	printf("%d\n", WEXITSTATUS(status));
}
if(WIFSIGNALED(status)){           # signal을 받고 종료
    printf("%d\n", WTERMSIG(status));
}

 

 

 

 

🚩 signal 보내기

 

#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);

 

  • pid : signal을 받게 될 process 지정
-  pid > 0 : 해당 id의 process에게 signal 전달
-  pid = 0 : sender와 같은 process group에 속하는 모든 process에게 signal 전달, sender 자신 포함
-  pid = -1 : uid가 sender의 euid와 같은 모든 process에게 signal 전달, sender 자신 포함
-  pid < 0 & pid != -1 : process의 group id가 pid의 절대값과 같은 모든 process에게 signal 전달
다른 사용자의 process에게 signal을 보내면 -1 return
  • sig : 보낼 signal 지정

 

 

🚩 signal 보내기 (2)

 

#include <signal.h>
int raise(int sig);

 

: 호출 process에게 sig를 보낸다.

 

 

 

🚩 signal handling

  • default action ( 프로세스 종료 )
  • 무시
  • 정의된 action
  • sigaction 지정 : signal 수신 시 원하는 행동을 취할 수 있도록 한다.

       예외 ) SIGSTOP (process의 일시 중단), SIGKILL (process의 종료) 의 경우는 별도의 action을 취할 수 없다.

 

  • 지정 방법
#include <signal.h>
int sigaction (int signo, const struct sigaction * act, struct sigaction *oact);

 

  • sigaction 의 구조 
struct sigaction {
	
    void (*sa_handler) (int);
    sigset_t sa_mask;
    int sa_flags;
    void (*sa_sigaction) (int, siginfo_t *, void *);
    
};

   

 

   1. void (*sa_handler) (int);

   : signo를 수신하면 취할 행동 지정  ex) SIG_DFL (종료), SIG_IGN (무시), 정의된 함수 (signal을 받기 직전의 처리 문장으로 return)

 

 

    2. sigset_t sa_mask;

   : 여기 정의된 signal들은 sa_handler에 의해 지정된 함수가 수행되는 동안 blocking된다.

 

 

    3. int sa_flags;

  : SA_RESETHAND ( handler로부터 복귀 시, signal action을 SIG_DFL로 재설정), SA_SIGINFO (sa_handler 대신 sa_sigaction 사용)

 

 

 

 

🚩 signal 사용 예시

 

#include <signal.h>
main() {

	static struct sigaction act;
    void catchint(int);
    
    act.sa_handler = catchcint;
    sigaction(SIGINT, &act, NULL);
    
    printf("sleep call1\n");
    sleep(1);
    
    printf("sleep call2\n");
    sleep(1);
    
    printf("exciting\n");
    exit(0);

}
void catchint(int signo){
	printf("\n CATCHINT: signo=%d\n", signo);
}

 

 

 

🚩 signal 사용 예시 (2)

 

1. SIGINT를 무시

act.sa_handler = SIG_IGN;
sigaction(SIGINT, &act, NULL);

 

2. SIGINT시 종료

act.sa_handler = SIG_DFL;
sigaction(SIGINT, &act, NULL);

 

3. 여러 개의 signal을 무시하려면

act.sa_handler = SIG_IGN;
sigaction(SIGINT, &act, NULL);
sigaction(SIGQUIT, &act, NULL);

 

: 한 process 에서 무시되는 signal은 exec() 후 에도 계속 무시된다.

 

 

 

 

 

 

🚩 signal 집합 지정

  • signal 집합 지정:
sigemptyset  →  sigaddset         # 빈 시그널 세트 생성  →  특정 시그널을 번호로 추가
sigfillset   →  sigdelset                # 시그널을 모두 포함하는 세트 생성  →  특정 시그널을 번호로 삭제

       

  • 사용 방법:
#include <signal.h>
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signo);
int sigdelset(sigset_t *set, int signo);
int sigismember(sigset_t *set, int signo);

 

 

 

🚩 signal 집합 지정 (2)

sigset_t mask1, mask2;

sigemptyset(&mask1);
sigaddset(&mask1, SIGINT);
sigaddset(&mask1, SIGQUIT);

sigfillse(&mask2);
sigdelset(&mask2, SIGCHLD);

 

 

 

 

🚩 sa_sigaction( )에 의한 signal handling

int main(void){
	static struct sigaction act;
    act.sa_flags = SA_SIGINFO;
    act.sa_sigaction = handler;
    sigaction(SIGUSR1, &act, NULL);
    ....
}

void handler(int signo, siginfo_t *sf, ucontext_t *uc){
	psiginfo(sf, "...");
    printf("%d\n", sf->si_code);
}

 

 

 

 

🚩 이전의 설정 복원하기

sigaction(SIGTERM, NULL, &oact);  // 과거 설정 저장

act.sa_handler=SIG_IGN;
sigaction(SIGTERM, &act, NULL);

// do anything

sigaction(SIGTERM, &oact, NULL);

 

 

 

 

🚩 alarm signal 설정

  • timer 사용 
#include <signal.h>
unsigned int alarm(unsigned int secs);
  • secs : 초 단위의 시간; 시간 종료 후 SIGALRM을 보낸다.
  • alarm은 exec 후에도 계속 작동; but fork 후에는 자식 process에 대한 alarm은 작동하지 않는다.
  • alarm(0);  : alarm 끄기
  • alarm은 누적되지 않는다. 2번 사용되면, 두번째 alarm이 대체
  • 두번째 alarm의 return 값이 첫 alarm의 잔여 시간

 

 

 

 

🚩 signal blocking

#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oset)


 /* 봉쇄를 설정한다. */
 sigprocmask(SIG_SETMASK, &set1, NULL);

 /* 봉쇄를 제거한다. */
 sigprocmask(SIG_UNBLOCK, &set1, NULL);

 

how : signal mask를 어떻게 변경시킬지

set : 무엇을 변경시킬지

oset : old set을 save 해놓는 것

 

 

 

 

🚩 pause 시스템 호출

  • 사용법
#include <unistd.h>
int pause(void);
  • signal 도착까지 실행을 일시 중단 (CPU 사용 없이)
  • signal이 포착되면 처리 routine 수행하고 -1을 리턴한다

 

 

 

'UNIX 프로그래밍' 카테고리의 다른 글

[9주차 개념] 파이프  (0) 2023.11.14
[8주차 개념] 메모리 매핑  (0) 2023.11.10
[4주차 실습] UNIX 실습 문제  (0) 2023.10.22
[3주차 실습] UNIX 실습 문제  (0) 2023.10.22
[2주차 실습] UNIX 실습 문제  (1) 2023.10.22

댓글