Signals
2014년 2학기 시스템 프로그래밍 시험 공부

시스템 프로그래밍 시험 공부하면서 정리한 내용이다. 내용 갱신은 앞으로 없다.

Signals

Signals

Signal

  • 프로세스에 이벤트를 알릴때 보내는 것
  • 프로세스나 프로세스 그룹에 간단한 메세지를 보낼때 사용하는 IPC
    • number : 시그널 번호
    • Remember, No payload. 인자는 지원하지 않는다.
    • 간단하고 효율적이라서 널리 쓰임
  • 일반적으로 프로세서는 시그널에 반응할때 user-space 함수(signal handler)를 호출
  • 인터럽트 <=> 커널 … 시스널 <=> 프로세스

목적

  • 특정한 이벤트가 발생했다는 것을 프로세스에 알려준다.
  • 프로세스가 시그널 핸들러를 실행하도록 강요할때 사용.

시그널의 종류

  • signal number -> SIGxxx macro
  • “real-time” signal은 POSIX 표준에 정의

프로레스가 시그널을 처리하는 방법

  • 커널 기본을 사용. (시그널별로 기본 행동이 정의되어 있다. Terminate, Dump, …)
  • 시그널 무시
  • 시그널 Block (나중에 unblock할때까지 미룬다)
  • 별도의 시그널 핸들러

시그널의 특징

  • 시그널은 프로세스에 언제든지 보낼 수 있다
  • non-running 상태의 프로세스에도 보낼 수 있다.
    • blocked도 시그널을 받을 수 있다
    • 프로세스가 실행 상태로 돌아올때까지 커널이 저장해둔다.
    • Running 상태로 돌아오면 받은 시그널 처리
  • 현재 실행중인 프로세스(current process)에서 시그널 생성 가능
  • 타입별 시그널은 1개씩만 저장 가능
    • bitmap을 이용해서 시그널 저장하기때문
  • 시그널은 프로세스에 의해서 선택적으로 blocked 가능
    • 블럭한거 처리하기전까지 프로세스는 해당 시그널을 받지 않는다
  • 시그널 핸들러 함수가 실행되면 함수가 끝날때까지 시그널 블럭
    • 시그널 핸들러는 다른 시그널에 의해 interrupt 되지 않는다.

Signal Handling

  • 시그널 핸들링에 필요한 자료구조
    • 시그널 핸들러 배열
    • 대기중인(pending) 시그널 목록
    • 블럭된(blocked) 시그널 마스크 (bitmask)
  • 대기중인 시그널 (pending signal)
    • 받았지만 아직 처리할수 없는 시그널은 pending 된다
    • 시그널이 언제 처리되는가?
      • 인터럽트나 예외에서 돌아올때 (시스템콜 포함)
    • 시그널은 타입별로 1개만 대기 목록에 들어갈 수 있다.
    • 시그널이 언제 처리될지는 보장 못한다
  • 커널의 시그널 구현
    1. 각각의 프로세스에서 어떤 시그널을 블럭했는지 기억
    2. 커널모드에서 유저모드로 넘어갈때 도착한 시그널이 있는지 확인하기
      • timer interrupt를 이용해서 대략 1ms마다 계속 확인
    3. 시그널을 무시해도 되는지 결정
    4. 시그널 처리
      • 프로세스 실행 도중에 시그널 핸들러로 전환
      • 이전 실행 상태는 저장해놨다가 시그널 핸들러 처리 후 복구

Date Structures for Signal Handling

task_struct에는 lightweight process용 시그널 자료구조와 thread group용 시그널 자료구조가 같이 들어있다. 내부 구조는 서로 비슷하다. thread-group용 시그널은 shared signal이라고도 부른다

  • struct task_struct
    • struct sigpending pending : 프로세스용 pending 시그널 목록
    • struct signal_struct *signal : thread-group용 시그널 디스크립터
    • sturct sighand_struct *sighand : 시그널 핸들러
    • sigset_t blocked : blocked signal bitmassk
  • struct sighand_struct
    • struct k_sigaction action[64]
  • signal handler : task_struct
    • task->sighand->action[x].sa_handler
  • struct sigpending:
    • struct list_head list : linked list. sigqueue로 연결
    • sigset_t signal : bitmask
  • struct sigqueue
    • struct sigqueue *next : linked list
    • siginfo_t info : pending 시그널의 정보
  • struct siginfo_t
    • si_signo : signal number
    • si_code : 누가 시그널을 발생시켰는가 (유저? 커널? timer?)

Signal Transmission

  1. 시그널 생성 (Signal Generation)
    • 커널은 목적 프로세스의 디스크립터를 갱신해서 새로운 시그널이 왔다는 것을 저장한다
  2. 시그널 보내기 (Signal Action)
    • 커널은 목적 프로세스가 시그널에 반응하도록 강요한다. 2가지 작업 중 하나, 또는 둘다 수행.
    • 목적 프로세스의 실행 상태를 바꾼다. (예를 들면 프로세스 죽이기)
    • 시그널 핸들러를 실행한다.

Signal Generation

  • 시그널 보내는 프로세스 디스크립터 갱신
  • 시그널의 종류와 프로세스의 상태에 따라서 시그널 함수는 프로세스를 깨우고 시그널 처리를 강요한다.
  • 대상에 따라 2종류로 분류
    • 프로세스로 시스널 보내는 함수
    • 쓰레드 그룹으로 시그널 보내는 함수
  • specific_send_sig_info()
    • 시그널 액션을 무시할수 있는지 확인
    • 시그널을 프로세스에 보내기. send_signal() 호출
    • 시그널이 블럭되지 않았으면 signal_wake_up() 호출
    • SIGKILL, SIGSTOP, 등등은 특별한 처리
  • send_signal()
    • 시그널을 목적 프로세스의 pending list에 추가하는 함수
    • 새로운 list 요소용 메모리를 할당
    • 시그널 정보를 채우고 목록에 추가
    • pending 시그널 목록 갱신
  • signal_wake_up()
    • 프로세스에 새로운 pending singal이 등록되었다는 것을 알려주는 함수
    • TIF_SIGPENDING 플래그 설정 (Signal Action에서 이용)

Signal Action

  • 프로세스가 interrupt, exception에서 돌아올때
    • ret_from_intr(), syscall_exit 는 유저모드로 돌아오기 전에 블럭되지 않은 pending 시그널이 있는지 확인 (TIF_SIGPENDING의 존재를 확인)
    • 플래그가 있으면 do_signal()
  • do_signal()
    • pending list에서 시그널 빼내기 (blocked 제외)
    • 시그널을 적절히 처리 (3가지중 한가지 행동 선택)
    • nonblocked pending signal이 없을때까지 do_signal()을 반복
  • 시그널 처리하는 행동
    1. 시그널 무시
    2. 시그널의 기본 행동 실행
      • Terminate : 프로세스 끝내기 (kill)
      • Dump : 프로세스 끝내고 core file 생성
      • Ignore : 시그널 무시
      • Stop : TASK_STOPPED
      • Continue : 프로세스가 멈춰있으면 TASK_RUNNING 상태로 변경
    3. signal handler 호출. handle_signal()
  • SIGKILL, SIGSTOP는 무조건 기본 행동을 수행
    • 무시, blocked, signal handler 불가능
  • handle_signal()
    • 시그널 핸들러를 실행하는 것은 유저모드와 커널 모드를 넘나드는 복잡한 작업이다.
    • 시그널 처리의 시작인 do_signal()은 커널모드인데 시그널 핸들러는 유저모드이다.
    • 커널모드에서 유저모드 함수를 호출해야 한다.
  • 리눅스의 방식
    • 현재 프로세스의 커널모드 스택의 Hardware context를 유저모드 스택으로 복사
    • 시그널 핸들러가 끝날때 sigreturn() 자동으로 호출해서 hardware context를 커널스택으로 복사. 유저모드 스택을 원래도 되돌림

Real-time Signals in Linux

  • POSIX 표준에 정의되어 있다.
    • 32~63번
    • queue되는 시그널
  • 리눅스는 편법으로 real-time signal을 지원
    • 진정한 real-time signal이 아니다
    • real-time signal은 pending signal list에 같은 타입의 시그널을 1개 이상 추가하는 것을 허용

comments powered by Disqus