[42Seoul/minitalk] mandatory 및 개념 1편
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 종류
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편