0. Minitalk subject!
Mandatory Part
•
서로 의사 소통 가능한 client, server 프로그램을 만든다.
•
server가 먼저 켜지고, 실행되면 PID 를 먼저 출력해야한다.
•
클라이언트가 받아야하는 파라미터
◦
서버 PID
◦
전송할 문자열
•
클라이언트는 서버한테 넘겨받은 문자열을 보내준다. 서버가 문자열을 받으면 서버는 표시해야한다.
•
통신은 UNIX 시그널을 통해서만 이뤄져야한다.
•
서버는 꽤 빠르게 문자열을 출력해야한다...? 1초에 100개 문자열은 엄청 느린것이다...?
•
서버는 여러개의 클라이언트한테 한번에 문자열을 받을 수 있어야한다.
•
시그널 SIGUSR1 과 SIGUSR2 만 써야한다.
Bonus
•
reception acknowledgment system
•
유니코드 지원
1. 개념
시그널이란?
시그널 집합이란?
•
그냥 시그널을 한번에 여러개를 표현하기 위한 sigset_t 구조체 참고
•
비트 마스크를 활용한다.
•
실제 구조체는 아래와같이 생겼다.
typedef struct {
unsigned int __sigbits[4];
} sigset_t;
C
복사
•
sigaction 구조체에서 쓰인다.
2. 함수 정리하기
이미 아는 함수
•
write, malloc, free, exit
getpid
function
#include <unistd.h>
pid_t getpid(void)
C
복사
return value
프로세스의 ID 를 반환 합니다.
example
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("PID = %d\n", getpid());
return 0;
}
C
복사
sigemptyset
시그널 집합 비우기
function
#include <signal.h>
int sigemptyset(sigset_t *set);
C
복사
patameters
•
비워질 sigset_t 구조체
return value
•
성공하면 0
•
실패하면 -1
example
#include <signal.h>
int main()
{
sigset_t set;
sigemptyset(&set);
}
C
복사
sigaddset
function
#include <signal.h>
int sigaddset(sigset_t *set, int signo);
C
복사
patameters
•
추가될 sigset_t 구조체
•
추가할 시그널
return value
•
성공하면 0
•
실패하면 -1
example
#include <signal.h>
int main()
{
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGINT);
}
C
복사
sigaction
signal 함수의 업그레이드 된 버전 참고
function
#include <signal.h>
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
C
복사
patameters
•
signum : 시그널 번호
•
act : NULL또는 처리할 방법을 담은 sigaction 구조체의 주소
•
oldact : NULL또는 기존에 시그널을 처리하던 방법을 저장할 sigaction 구조체의 주소
•
sigaction 구조체
struct sigaction
{
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
}
C
복사
•
sa_handler : 시그널 발생했을떄 처리할 함수
•
sa_mask : sa_handler 에 등록된 시그널 핸들러 함수가 실행되는 동안 블럭 되어야하는 시그널의 마스크
•
sa_flag : 처리 프로세스 플래그
return value
성고하면 0
실패하면 1
example
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
void sig_int(int signo);
void sig_usr(int signo);
int main()
{
int i = 0;
struct sigaction intsig, usrsig;
usrsig.sa_handler = sig_usr;
sigemptyset(&usrsig.sa_mask);
usrsig.sa_flags = 0;
intsig.sa_handler = sig_int;
sigemptyset(&intsig.sa_mask);
intsig.sa_flags = 0;
// SIGINT에 대해서 sig_int를 등록한다.
if (sigaction(SIGINT, &intsig, 0) == -1)
{
printf ("signal(SIGINT) error");
return -1;
}
// SIGUSR2에 대해서 usrsig를 등록한다.
if (sigaction(SIGUSR2, &usrsig, 0) == -1)
{
printf ("signal(SIGUSR2) error");
return -1;
}
while(1)
{
printf("%d\n", i);
i++;
sleep(1);
}
}
void sig_int(int signo)
{
printf("sig_int\n");
}
void sig_usr(int signo)
{
printf("sig_usr2\n");
}
C
복사
pause
함수가 호출되면 시그널을 수신할 떄까지 대기 상태로 빠진다. 참고
funciton
#include <unistd.h>
int pause(void)
C
복사
return value
무조건 -1
example
#include <unistd.h>
#include <stdio.h>
int main(void)
{
printf("시그널 기다리는중!\n");
pause();
printf("시그널 받았다!");
}
C
복사
sleep
함수가 호출되면 지정된 초만큼 대기상태로 빠진다.
funciton
#include <unistd.h>
unsigned int sleep(unsigned int seconds);
C
복사
return value
정상 종료 : 0
시그널 받아서 중간에 멈추면 : 남은 시간
example
#include <unistd.h>
#include <stdio.h>
int main(void)
{
printf("시작\n");
sleep(3);
printf("3초 지났다!");
}
C
복사
usleep
함수가 호출되면 지정된 마이크로 초만큼 대기상태로 빠진다.
funciton
#include <unistd.h>
int usleep(useconds_t usec)
C
복사
parameters
The type useconds_t is an unsigned integer type capable of holding integers in the range
[0,1000000].
0 ~ 1000000 사이의 값
return value
성공 : 0
실패 : -1
example
#include <unistd.h>
#include <stdio.h>
int main(void)
{
printf("시작\n");
sleep(1000 * 1000);
printf("1초 지났다!");
}
C
복사
3. 구현
•
프로세스 사이에서 signal 을 주고 받는것에 대해서 이해가 되었을 것이다.
•
그럼 이제 client 에서 server 로 문자열을 보내보자
•
근데 어떻게 문자열을 시그널을 통해서 보낼 수 있을까?
•
정답 : bit 단위로 잘라서 순차적으로 보낸다!
•
이때, SIGUSR1 로 시그널을 보내면 1, SIGUSR2 로 시그널을 보내면 0 으로 인식한다.
•
예시
•
A 라는 문자 하나를 보낸다고 생각해보자
•
A 를 bit 로 표현하면 01000001 이다.
•
client
◦
100 마이크로 초 마다 server 로 시그널을 보낼건데,
◦
A 의 첫번째 bit 가 1 이므로 SIGUSR1 을 보내고
◦
A 의 두번째 bit 가 0 이므로 SIGUSR0 을 보내고
◦
A 의 세번째 bit 가 0 이므로 SIGUSR0 을 보내고
◦
...
◦
A 의 여덟번째 bit 가 0 이므로 SIGUSR0 을 보낸다.
•
server
◦
시그널을 받을때마다
◦
SIGUSR1 이면 bit의 오른쪽 끝에 1을 추가하고
◦
SIGUSR0 이면 bit 의 오른쪽 끝에 0을 추가한다.
◦
최종적으로 문자 A 가 완성된다.
◦
문자 A 를 출력한다.
4. 평가표
•
서버가 pid 를 띄우는지
•
./client PID STRING 했을때 전송이 잘 되는지
•
time 써서 시간 잴떄 문자열 10, 100 는 1초 미만, 1000개는 2초 미만으로
•
SIGUSR1 이랑 SIGUSR2 를 썼는지
•
8bit 씩 잘라서 보냈는지
•
전역변수를 1개 이하로 썼는지