리눅스 커널의 이해 중에서 9장. 시그널 Database 실험실 안 병 규
목차 Part I : 시그널의 역할 Part II : 시그널 전송 Part III : 시그널 수신 Part IV : 실시간 시그널 Part V : 시그널 처리와 관련한 시스템 콜
Part I : 시그널의 역할
시그널의 역할 IPC(InterProcess Communication) 프로세스들은 상호간의 활동을 조정하기 위하여 프로세스간, 커널과 통신을 하기 위한 메커니즘 시그널 파이프 소켓 메시지 큐 세마포어 공유메모리
시그널의 역할 시그널 초기 UNIX 시스템에서 간단하게 프로세스간 통신을 하기위한 메커니즘 간단하고 효율적 프로세스나 프로세스 그룹에 보내는 짧은 메시지(식별번호) 커널도 시스템 이벤트를 프로세스에 알리기 위해 사용 SIG로 시작하는 이름의 macro 집합으로 시그널을 정의 몇몇 시그널은 하드웨어의 구조에 따라 다름
시그널의 역할 [표9-1] 리눅스/i386 내 처음 31개 시그널 # 시그널명 기본동작 설명 포직스 1 SIGHUP 중단 터미널이나 프로세스의 제어권을 끊는다. 예 2 SIGINT 키보드에서 오는 인터럽트 3 SIGQUIT 덤프 키보드에서 오는 중단 4 SIGILL 잘못된 명령 5 SIGTRAP 디버깅을 위한 중지점 아니오 6 SIGABRT 비정상적인 종료 SIGIOT SIGABRT와 같다 7 SIGBUS 버스 에러 8 SIGFPE 부동 소수점 예외 9 SIGKILL 강제적인 프로세스 종료 10 SIGUSR1 프로세스가 사용할 수 있다. 11 SIGSEGV 잘못된 메모리 참조 12 SIGUSR2 13 SIGPIPE 아무도 읽지 않는 파이프에 쓰기 14 SIGALRM 실시간 클록 : [표9-1] 리눅스/i386 내 처음 31개 시그널
시그널의 역할 시그널의 주요 기능 시그널과 관련된 시스템 콜 특정 이벤트를 프로세스에게 알림 프로세스가 자신의 코드에 들어있는 시그널 핸들러 함수를 실행 시그널과 관련된 시스템 콜 프로그래머는 시스템 콜을 이용하여 시그널을 보내거나 프로세스가 받은 시그널을 어떻게 처리할 지 결정
시그널의 역할 [표9-2] 시그널과 관련된 시스템 콜 시스템 콜 설 명 kill() sigaction() signal() 설 명 kill() sigaction() signal() sigpending() sigprocmask() sigsuspend() rt_sigaction() rt_sigpending() rt_sigprocmask() rt_sigqueueinfo() rt_sigsuspend() rt_sigtimedwait() 프로세스에 시그널을 보낸다. 시그널과 관련된 동작을 변경한다. sigaction()과 비슷하다. 대기 중인 시그널이 있는지 검사한다. 블록할 시그널 목록을 수정한다. 시그널을 기다린다. 실시간 시그널과 관련한 동작을 변경한다. 대기 중인 실시간 시그널이 있는지 검사한다. 블록할 실시간 시그널 목록을 수정한다. 프로세스에 실시간 시그널을 보낸다. 실시간 시그널을 기다린다. rt_sigsuspend()와 비슷하다. [표9-2] 시그널과 관련된 시스템 콜
시그널의 역할 커널의 시그널 처리 시그널 전송 시그널 수신 수신측 프로세스의 디스크립터를 갱신하여 시그널 도착을 알림 수신 프로세스가 시그널에 반응하도록 만듬 : 실행상태 변경, 핸들러 실행 수신 프로세스가 실행중이 아닌 경우, 프로세스가 다시 실행상태가 될 때까지 저장
시그널의 역할 대기중인 시그널(pending signal) 전송했지만 아직 수신하지 않은 시그널 같은 종류의 시그널이 하나의 프로세스에 대기상태로 있을 수 없음 추가로 도착하는 동일한 시그널은 큐에 넣지 않고 버림 프로세스는 한번에 하나의 시그널만 처리 가능 대기중인 시그널은 대기시간을 예측할 수 없음 : 비동기성
시그널의 역할 고려사항 시그널은 실행중인 프로세스만 수신 프로세스가 특정한 종류의 시그널을 블록하는 경우 커널은 블록이 해제될 때까지 시그널을 받지 않음 프로세스가 수신한 시그널의 핸들러 함수를 실행중인 경우 해당 시그널을 마스킹 해당 시그널이 발생하더라도 핸들러가 종료될 때까지 자동으로 블록 해당 시그널이 다시 발생해도 인터럽트 당하지 않음
시그널의 역할 커널 구현 각 프로세스가 어떤 시그널을 블록하고 있는지 기억 커널모드에서 사용자 모드로 전환시 모든 프로세스에 대해 도착한 시그널을 검사 무시할 수 있는 시그널인지 판단 시그널을 받을 프로세스를 다른 프로세스가 추적 프로세스가 해당 시그널을 블록 프로세스가 해당 시그널을 무시(명시적 지정, 기본동작) 시그널을 처리 프로세스 상태를 기억하고 핸들러 처리 후 복귀하는 문맥교환이 요구됨
시그널의 역할 시그널 수신시의 동작 명시적으로 시그널을 무시 해당 시그널의 기본동작을 수행 SIGKILL, SIGSTOP은 무시할 수 없음 해당 시그널의 기본동작을 수행 중단(abort) 덤프(dump) 무시(ignore) 멈춤(stop) 계속(continue) 해당 시그널 핸들러 함수를 호출(catch)
시그널의 역할 시그널과 관련한 자료구조 sigset_t 구조체 프로세스 디스크립터 내의 시그널 관련 필드 signal :수신한 시그널을 나타냄 blocked : 블록된 시그널 sigpending : 블록되지 않은 시그널의 존재 여부를 나타내는 플래그 Unsigned long 32bit
시그널의 역할 시그널과 관련한 자료구조 프로세스 디스크립터 내의 시그널 관련 필드(계속) gsig : 각 시그널 처리 방법을 기술한 signal_struct 자료구조의 포인터 공유 프로세스 수 64개 count action ‥ ‥ ‥ siglock sa_handler sa_flags sa_mask 동작 유형(핸들러,기본동작,무시) 시그널 처리방법 마스킹 시그널
시그널의 역할 시그널과 관련한 자료구조 [표9-3] 시그널 처리방법을 지정하는 플래그 플래그명 설 명 SA_NOCLDSTOP 설 명 SA_NOCLDSTOP SA_NODEFER, SA_NOMASK SA_RESETHAND, SA_ONESHOT SA_ONSTACK SA_RESTART SA_SIGINFO 프로세스가 멈췄을 때 부모에게 SIGCHILD를 보내지 않는다. 시그널 핸들러를 실행할 때 시그널을 마스킹하지 않는다. 시그널 핸들러를 실행한 후 기본 동작으로 초기화 한다. 시그널 핸들러용으로 다른 스택을 사용한다(뒤에 나오는 ‘시스템 잡기’ 참고). 인터럽트된 시스템 콜을 자동으로 재시작한다(뒤에 나오는 ‘시스템 콜 재실행’ 참고). 시그널 핸들러에 추가 정보를 제공한다(뒤에 나오는 ‘시그널 동작 바꾸기’ 참고). [표9-3] 시그널 처리방법을 지정하는 플래그
Part II : 시그널 전송
시그널 전송 전송에 사용되는 함수 send_sig_info() send_sig() 매개변수 sig : 시그널 번호 info : siginfo_t(실시간) 테이블 주소 or 보내는 프로세스의 권한(0:커널모드 1:사용자모드) t :시그널을 전달받을 프로세스의 디스크립터에 대한 포인터 send_sig() info 매개변수 대신 priv 플래그를 사용하는 특별한 경우 return send_siginfo(sig, (void*)(priv !=0), t); force_sig_info(), force_sig() 명시적으로 무시하거나 블록할 수 없는 시그널을 보내기위해 커널에서 사용
t->signal에 해당 bit를 설정 시그널 전송 N Y 매개변수검사 사용자 모드 sig=0 or Zombie? 즉시처리가능 블록상태 작업권한 필요시 다른 대기중인 시그널 제거 error 반환 t->signal에 해당 bit를 설정 t->sigpending을 설정 수신 종료
Part III : 시그널 수신
시그널 수신 시그널 처리 커널 프로세스를 사용자 모드로 되돌려 보내기 전에 대기중인 시그널 검사 블록되지 않은 대기 시그널이 있는 경우 do_signal()실행 do-signal() 매개변수 regs : 현재 프로세스의 사용자 모드 레지스터 내용을 저장한 스택 영역 주소 oldset : 블록된 시그널의 비트 마스크 배열을 저장할 변수 주소 대기중인 시그널이 소멸될 때까지 dequeue_signal()을 실행 k_sigaction 자료 구조 주소를 지역변수 ka에 설정 ka= ¤t->sig->action[signr-1]
시그널 수신 시그널 처리 처리할 시그널이 남았나? 다른 프로세스가 감시중인가 처리할 시그널의 k_sigaction조사 기본동작 핸들러 무시 감시 프로세스에 알림 종료 Y N
시그널 수신 무시 do_signal()의 루프를 계속하여 다른 시그널 처리 시그널이 SIGCHLD인 경우 종료한 자식 프로세스가 잡고 있던 메모리를 해제 SIGCHLD? 종료한 자식 프로세스가 잡고 있는 메모리 회수 Y N Return
시그널 수신 기본동작 수행 ka->sa.sa_handler가 SIG_DFL 이면 기본 동작을 수행 프로세스가 init 인경우 무시(예외) 시그널의 기본동작에 따라 처리 중지 : 현재 상태를 TASK_STOPPED로 바꾸고 schedule()실행 덤프 : 작업중인 디렉토리에 코어파일 생성후 프로세스 종료
시그널 수신 기본동작 수행 시그널 기본동작 확인 현재 디렉토리에 Core 파일 생성 Return EXIT 부모 프로세스에 SIGCHLD 시그널 전송 TASK_STOPPED 스케줄러 호출 멈춤 덤프 종료 무시
시그널 수신 시그널 잡기 시그널을 위한 별도 핸들러가 있다면 handle_signal()을 실행 문제점 해결 시그널 핸들러는 사용자 모드에서 실행 사용자 모드와 커널모드 사이의 전환시 커널 모드 스택을 지움 해결 커널모드에 저장한 하드웨어 컨텍스트를 사용자 모드 스택으로 복사 sigreturn()시스템 콜을 이용해 커널모드 스택으로 다시 복구
시그널 수신 시그널 잡기 사용자 모드 커널 모드 일반 프로그램 흐름 do_signal() Handle_signal() Setup_frame() system_call() sys_sigreturn() restroe_sigcontext 시그널 핸들러 스택에 있는 복귀 코드
시그널 수신 시그널 잡기 프레임 구성 사용자 모드의 스택을 설정하기 위해 setup_frame()함수를 호출 사용자 모드 스택 시그널 핸들러의 복귀 주소 pretcode sig sc fpstate extramask retcode 시그널 핸들러의 매개변수(시그널 번호) 프로세스 하드웨어 컨텍스트 부동 소수점 레지스터 블록된 실시간 시그널 Sigreturn() 호출 이전 스택 내용
Part IV : 실시간 시그널
실시간 시그널 실시간 시그널 포직스 규약에 따라 32~63번의 새로운 시그널 같은 종류의 실시간 시그널을 큐에 넣을 수 있음 리눅스에서는 커널에서 사용하지 않고 특별한 시스템 콜을 통해 지원 프로세스 디스크립터의 실시간 시그널 관련 필드 sigqueue : 수신한 실시간 시그널 큐의 첫번째 항목 sigqueue_tail : 마지막 항목의 next 필드
실시간 시그널 실시간 시그널의 처리 send_sig_info() dequeue_signal() 시그널 번호가 31을 초과할 경우 실시간 시그널 큐에 삽입 dequeue_signal() 시그널 번호가 31을 초과할 경우 큐에서 해당 시그널 항목을 처리 큐에 같은 종류의 시그널이 없으면 current->signal에서 해당 비트 지움
Part V : 시그널 처리와 관련한 시스템 콜
시그널 처리와 관련한 시스템 콜 Kill() 시스템 콜 kill(pid, sig) 시그널을 보내는데 사용 pid > 0 : pid와 같은 PID를 갖는 프로세스 pid = 0 : 호출한 프로세스와 같은 프로세스 그룹에 있는 모든 프로세스 pid = -1 : 스와퍼(PID 0), init (PID 1), current 프로세스 이외의 모든 프로세스 pid < -1 : -pid 프로세스 그룹에 있는 모든 프로세스
시그널 처리와 관련한 시스템 콜 표준 시그널 시스템 콜 sigaction() : 사용자가 시그널에 대한 동작을 지정 sigaction(sig, act, oact) oact 생략가능, 이전 act정보를 얻기 위해 사용 sigpending() : 대기중인 블록된 시그널 검사
시그널 처리와 관련한 시스템 콜 표준 시그널 시스템 콜 sigprocmask() : 블록된 시그널 집합 수정 sigprocmask(oset, set, how) SIG_BLOCK(추가) SIG_UNBLOCK(삭제) SIG_SETMASK대체) sigsuspend() : 프로세스 보류 Mask 매개변수가 가리키는 시그널을 블록 프로세스를 TASK_INTERRUPTED 상태로 전환 블록되지 않은 시그널을 받을 경우에만 깨어남
시그널 처리와 관련한 시스템 콜 실시간 시그널을 시스템 콜 rt_sigaction() rt_sigpending() rt_sigprocmask() rt_sigsuspend() rt_sigqueueinfo() 수신 프로세스의 실시간 시그널 큐에 추가하기 위해 실시간 시그널을 보냄 rt_sigtimewait() rt_sigsuspend()와 유사 일정 시간 동안만 보류된 상태 표준 시그널 시스템 콜과 동일하게 사용
Part VI : Q & A