42 Seoul

[42Seoul/minitalk] mandatory 및 개념 1편

jaewpark 2021. 9. 24. 21:37

Mandatory Part

  • 여러분께서는 클라이언트와 서버가 서로 통신하는 프로그램을 작성하셔야 합니다.
  • 서버와 클라이언트 중 서버가 먼저 실행되어야 하며, 클라이언트가 런치가 될 때에 PID를 표시해야 합니다.
  • 클라이언트가 실행될 때 다음의 매개변수를 받습니다 :
    • 서버 PID
    • 전송할 문자열
  • 클라이언트는 매개변수로 전달한 문자열을 서버로 통신해야 합니다. 서버는 문자열이 수신되면 해당 문자열을 표시해야 합니다.
  • 여러분이 작성하신 서버와 클라이언트의 통신은 오직 UNIX signal을 이용하여야만 합니다.
  • 서버는 문자열을 매우 빠른 속도로 표시할 수 있어야 합니다. 즉, 표시되는 시간이 너무 길다고 생각된다면, 그건 너무 길다고 여겨야 합니다. (힌트 : 100개의 문자로 이루어진 문자열을 표시하는 데 1초가 걸린다면 그건 어마어마하게 긴 것입니다.)
  • 서버가 재시작할 필요없이 여러 클라이언트로부터 문자열을 연속으로 수신할 수 있어야 합니다.
  • SIGUSR1 SIGUSR2 두 신호만 사용할 수 있습니다.
PID : 프로세스 식별자, 유닉스, 맥 OS 또는 윈도우 등의 운영 체제 커널(시스템의 모든 것을 완전히 통제)이 사용되는 번호. 프로세스의 우선순위를 조정하거나 종료하는 등의 다양한 함수 호출에 사용

 

사용할 수 있는 함수

  • write
  • signal
  • sigemptyset
  • sigaddset
  • sigaction
  • kill
  • getpid
  • malloc
  • free
  • pause
  • sleep
  • usleep
  • exit

signal()

: Software interrupt로 process에 무엇인가 발생했음을 알리는 간단한 메시지를 비동기적으로 보내는 것

  • 헤더 : signal.h
  • 형태 : void(*signal(int signum, void (*handler)(int)))(int)
  • 인수 : int signum 시그널 번호, void(*handler)(int)시그널을 처리할 핸들
  • 오류 : SIG_ERR 반환
  • 반환 : void*()(int) 이전에 설정된 시그널 핸들러
    • SIG_DFL : 어떤 시그널이 발생하면 기존 방법으로 처리할지
    • SIG_IGN : 무시할지
    • 함수 이름 : 프로그램에서 직접 처리할지를 설정

 


 

 

  • Signal은 어떤 Event가 발생했음을 알리기 위해 Process에게 전달되는 소프트웨어 인터럽트
    • Hardware Exception (나누기 0 등)
    • Software condition (alarm 시간, expire 등).
    • 단말기에서 발생하는 사용자 입력 (^c, ^z 등).
    • kill 등과 같은 시스템 콜.
  • Process에게 Signal 전달
    • 기본 설정 실행(ignore, terminate, terminate+core).
    • Signal Handler에 의한 Catch 후 로직 수행.
    • 무시
signal 처리 방식 참고 사이트 : 여기 

 

signal 종류

man signal / kill -l (종류 확인)

SIGINT : signum == 2, ctrl + C 실행 중지, 프로세스를 종료

SIGQUIT : signum == 3, ctrl + \ 아무 것도 저장하지 않고 가능한 한 빨리 종료하도록 지시하는 종료 신호 (프로세스가 종료 신호로 인해 사망했음을 문자로 알림)

SIGTERM : signum == 15, ctrl + d EOF(End-Of-File)로 stdin 파이프를 닫습니다. 입력을 하지 않겠다는 의미로 프로세스를 종료하고 Terminal도 종료

SIGSTP : signum == 18, ctrl + z

 

signal 함수 동작 예시▽▼

더보기

두번째 인자 값으로 수행

주의 사항은 SIGKILL(9), SIGSTOP(시스템에 따라 다름)는 시그널 핸들러를 사용자가 임의로 지정할 수 없으며 해당 Signal은 무시할 수도 없다. 

즉 signal 함수로 두가지 SIGNAL은 catch or ignore 할 수 없습니다. 

또한 해당 Signal들에 대해 핸들러를 등록할 때 컴파일 및 런타임 에러가 발생하지는 않습니다.

단지 기본동작(SIGKILL-Terminate, SIGSTOP-Stop Process)으로만 동작

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<signal.h>
#include<unistd.h>
 
void sig_handler_usr1(int signo)
{
   printf("catched sigusr1\n");
}
    
int main()
{
   if(signal(SIGUSR1, sig_handler_usr1) == SIG_ERR)
   {
      perror("SIGUSR1 ERROR");
   }
   while(1) sleep(1);
   return 1;
}
cs

 

Kill()

  • 헤더 : sys/types.h, signal.h
  • 형태 : int kill(pid_t pid, int sig)
  • pid : 시그널을 받을 프로세스의 id
  • sig : pid로 지정된 프로세스에 보내려는 시그널
  • pid > 0 , pid로 지정한 프로세스에게 시그널을 보냄
  • pid == 0 , 호출한 프로세스와 같은 그룹의 ID를 가진 모든 프로세스에 시그널 전달
  • pid < 0 , pid의 절대값에 해당하는 프로세스와 같은 그룹의 ID를 가진 모든 프로세스에 시그널 전달

 

getpid()

  • 헤더 : unistd.h
  • 형태 : pid_t getpid(void)
  • 호출 프로세스의 프로세스 ID(PID)를 반환

 


 

부족한 내용은 다음 포스트에 정리

2021.09.25 - [42 Seoul] - [42Seoul/minitalk] 개념 및 구현 2편