9.시그널

2018. 11. 27. 15:53임베디드sw공학

1, Signal Concepts

 1) 프로그램이 예측하지 못한 이벤트가 발생했을 때, 반응을 해야 한다.

- floating point error

- power failure

 

 2) Signal 는 software interruot이고 그에 맞는 handle을 시행한다.

 

 3) signal은 몇가지 이벤트로 발생된다. signal은 process에게 전달된다. 그리고 proceess는 그 signal에 맞는 응답(some action)을 한다.

 

 4) process의 반응

  - ignore it. : signal을 무시

  - Catch it : 특정 signal을 개발자가 만들어 놓은 signal handler을 수행한다.

  - accept the default : 다른 명시적 행동을 만들지 않고도 default로 하는 행동들이 있다.

 

 5) Signal Concepts

  - 신호를 무시

  - process를 종료(term)

  - "core dump"를 생성하고 process를 종료.

core dump :

  - process를 중지.

  - 제외되어있던 process를 재수행.

 

2, Linux signals

각 signal은 고유한 integer으로 명시되어져 있다. (defined in signal.h)

 

 1) 대표적인 defined signal man signal(2)/signal(7)

 

- SIGALAM : 일정 시간 뒤에 signal을 보내는 타이머,알람 설정. 신호를 받았을때 설정한 어떤 행동을 할 수 있고 default는 term.

- SIGCHLD : Child process가 종료 되었을 때 parent process에게. default 는 ignore.

- SIGCONT : 중지되었던 process를 다시 수행.

- SIGKILL : 반드시 process를 죽이고 싶을 떄, 막을 수 없는 신호

- SIGPWR : "시스템이 곧 power off가 될 것이다." 라고 모든 process에게 준비하라고 알려주는 신호

- SIGSEGC :  잘못된 메모리를 접근하려 할 때, default는 core. core dump파일 생성.

- SIGSTOP : 수행되고있는 process를 중단시킬 때. (예로 ctrl+z.)

- SIGTERM : process를 종료시킬 때. 이는 SIGKILL과 다르게 어떠한 hendler를 수행가능 하다.

 

 

3, Dipstching Signals : kill(2) , raise(3)

#inclue <sys/types.h>

#include <signal.h>

 

int kill(pid_t pid, int signo); <- pid에게 지정한 signo (SIGTERM) 을 보내는 것.

int raise(int signo)

 

 - kill(2) <- 특정 process에게 시그널을 보내고 싶을 때 사용.

pid > 0 : ex)

pid = 0 : signal을 보내는 process와 같은 process group ID를 갖는 모든 process에게 SIGNAL을 보냄.

pid < -1, pid = -1 : kill(2) 메뉴얼 페이지 참조

 

- raise(3) : 자기 자신(process)에게 signal을 보내는 것.

 

4, Setting up a Signal Handler ; signal(2)

 

#include <signal.h>

typedef void (*sighandler_t) (int); <- 지정한 handler의 포인터

sighandler_t signal (int signum, signhandler_t handler);

 

return 이전에 등록한 signal handler의 값 또는 에러라면 SIG_ERR

 

- signal(2) 는 새로운 signal handler에 signum (signal number)를 배정하는 것.

 

- handler을 할수 있는 것.

  > SIG_IGN : 지정한 Signal을 받으면 무시하는 것.

  > SIG_DFL : Default를 실행하는 것.

  > 함수를 등록하는 것.

 

- UNIX이 개발되었을 때는 signal(2)로써 처리하였지만, 이전에는 없었던 개념 thread와 같은 개념이 생겨서, 이를 sigaction(2)를 사용하여 처리한다.

 

 

 

 

 

5, sigaction(2)

#include <signal.h>

int sigaction(int signum, const struct sigaction *acf, struct sigaction *oldact); // oldact는 예전에 등록해둔 것이 있다면 그것을 return해주는 것.

struct sigaction{

void (*sa_handler)(int);     /* Address of handler : handler 함수의 포인터 */

sigset_t sa_mask;            /* Signals blocked during handler invocation : 이것은 handler를 동작하는 중간에 막아버리는 것*/

 

int    sa_flag;                /* Flags controlling handler invocation */

void    (*sa_restorer) (void);    /* Not for application use */

}

 

- signal(2) 보다 sigaction(2)를 사용하는 것이 좋다.

 

 

6, Signal Sets

#include <signal.h>

int sigemptyset (sigset_t *set); <-  지정된 set을 공집합으로 만들어 줌.

int sigfillset (sigset_t *set);  <- 지정된 set을 1로 만들어 줌.

int sigaddset (sigset_t *set, int signum); <- set에 signal number를 포함시키는 것,

int sigdelset (sigset_t *set, int signum); <- set에 signal number를 제외시키는 것.

int sigismember (const sigset_t *set, int signum); <- set에 signum가 있는지 확인시켜 주는 것.

 

- signal들을 하나하나 지정해주는 것이 아닌 set으로 모아서 처리하는 것.

 

7, Signal Mask <- 오는 signal을 막아주는 것.

#include <signal.h>

int sigprocmask (int how, const sigset_t *set, sigset_t oldset);  //

int sigpending (sigset_t *set);

 

1) sigprocmask()의 how 부분에 적어주는 것.

- SIG_BLOCK : 지금까지 block된 old signal set에 signal set을 더해주는 것.

- SIG_UNBLOCK : 막혀있는 signal set을 다시 받을 수 있도록

- SIG_SETMASK : 두번쨰에 지정한 signal set을 MASK로 Block하도록 지정해주는 것.

 

2) sigpending(2) 는 현재 pending (대기하고 있는 상태) 되어있는 signal이 무엇있는 지를 보여주는 것.

+) signal이 pending되어있는 상태라면 여러번 눌러도  signal은 Queing되지 않음.

8, Timer 와 Sleeping

#include <unistd.h>

unsigned int alarm(unsigned int seconds);

 

- 지정한 시간이 지나면 SIGALRM을 보내주는 것.

- seconds = 0 이라면, 기존에 세팅한 알람을 clear해주는 것.

- 이 timer는 딱 하나만 설정할 수 있다.

- 그래서 나온 것이 POSIX interval timer로 여러 timer를 사용할 수 있다.

9, sleep(3), nanosleep(2) <- milli, nano second

#include <unistd.h>

unsigned int sleep(unsigned int seconds);

 

#define _POSIX_C SOURCE 199309

#include <time.h>

int nanosleep(const struct timespec *req, struct timespec *rem); <- rem은 sleep상태인데, 갑자기 어떤 interrupt를 받게 된다면, 그 interrupt를 한 뒤에 얼마나 남았는지가 저장된다. 

 

struct timespec {

time_t     tv_sec;    // 초

long       tv_nsec;    // nano second

}

 

'임베디드sw공학' 카테고리의 다른 글

12 - (3) fork(), execve(), exit(), wait()  (0) 2018.11.20
12 -(2) process create  (0) 2018.11.20
12-(1) Process 의 개요.  (0) 2018.11.20
7. 리눅스시스템 프로그래밍: File I/O  (0) 2018.11.06