Search
🎤

minitalk

Created
2022/01/24 08:10
Updated
2022/01/24 08:26
Tags
Circle 02
Signal
Chat
Author
Created
Updated
mcha(Min-jae Cha)
2022. 01. 18
2022. 01. 21
UNIX signal을 이용한 소규모 데이터 교환 프로그램 작성

 Summary

본 과제는 커뮤니케이션 프로그램을 작성하는 것이다.
클라이언트는 서버를 향해 메시지를 보내고 서버는 메시지를 받은 후 완료 신호를 클라이언트에 전송한다.

 Kit

이번 과제에서는 사용할 수 있는 함수들이 추가되었다.
펼쳐 보기

 Progress

핵심은 클라이언트가 문자 또는 문자열을 어떻게 서버로 보내고,
서버는 받은 문자 또는 문자열을 어떻게 터미널에 표시하는지의 방법이다.
Introductions에 나와 있는 바와 같이 사용할 수 있는 시그널은 SIGUSR1SIGUSR2 였고, 이 두 시그널만을 이용하여 통신을 하는게 핵심이었다.
방법은 문자열을 한번에 서버로 보내는 것이 아닌 문자 하나하나를 이진수로 변환하여 전송하는 것이었다.

→ How to

예를 들어 “abcdef” 라는 문자열이 있다고 가정 했을 때 한 문자씩 끊어서 이진수로 변환하여 전송한다.
→ a : 0 1 1 0 0 0 0 1
→ b : 0 1 1 0 0 0 1 0
→ c : 0 1 1 0 0 0 1 1
→ d : 0 1 1 0 0 1 0 0
더해서 각 문자를 이진수로 변환 했을 때에도 한 번에 모든 비트를 전송 하는 것이 아닌,
각 비트를 1(00000001)과의 & 연산을 통해 1이면 SIGUSR1를, 0이면 SIGUSR2를 전송하게 하였다.
a
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
a
0
0
0
0
0
0
0
1
1
0
0
0
0
0
0
0
1
& 답
0
0
0
0
0
0
0
1
a
0
0
0
0
0
0
1
1
1
0
0
0
0
0
0
0
1
& 답
0
0
0
0
0
0
0
1
a
0
0
0
0
0
1
1
0
1
0
0
0
0
0
0
0
1
& 답
0
0
0
0
0
0
0
0
a
0
0
0
0
1
1
0
0
1
0
0
0
0
0
0
0
1
& 답
0
0
0
0
0
0
0
0
a
0
0
0
1
1
0
0
0
1
0
0
0
0
0
0
0
1
& 답
0
0
0
0
0
0
0
0
a
0
0
1
1
0
0
0
0
1
0
0
0
0
0
0
0
1
& 답
0
0
0
0
0
0
0
0
a
0
1
1
0
0
0
0
1
1
0
0
0
0
0
0
0
1
& 답
0
0
0
0
0
0
0
0
연산 결과 → 00000000 = 0
SIGUSR2 전송
서버 상태 → 0
연산 결과 → 00000001 = 1
SIGUSR1 전송
서버 상태 → 01
연산 결과 → 00000001 = 1
SIGUSR1 전송
서버 상태 → 011
연산 결과 → 00000000 = 0
SIGUSR2 전송
서버 상태 → 0110
연산 결과 → 00000000 = 0
SIGUSR2 전송
서버 상태 → 01100
연산 결과 → 00000000 = 0
SIGUSR2 전송
서버 상태 → 011000
연산 결과 → 00000000 = 0
SIGUSR2 전송
서버 상태 → 0110000
연산 결과 → 00000001 = 1
SIGUSR1 전송
서버 상태 → 01100001
문자당 비트의 연산을 모두 마치면 다음 문자를 연산 후 전송하는 과정을 반복한다.
서버는 받아온 문자를 unsigned char 변수에 마찬가지로 비트 연산 후 값을 저장하고 비트가 모두 채워지면 출력 후에 0으로 초기화한다.
→ Pseudocode
func client(pid, msg) { idx = 0; while (msg[idx]) 시그널전송(pid, msg[idx++]); if (msg[idx] == '\0') 널전송(pid); } func 시그널전송(pid, sig) { while() { if (sig & 1) kill(pid, SIGUSR1); else kill(pid, SIGUSR2); usleep(); } }
C
복사
func server(sig) { unsigned char msg; while(msg != '\0') { if (sig == SIGUSR1) msg |= 1; else if (sig == SIGUSR2) msg |= 0; msg <<= 1; if (end) { msg 출력 msg 초기화 } } }
C
복사
→ Additional pseudocode
func client(pid, msg) { idx = 0; while (msg[idx]) 시그널전송(pid, msg[idx++]); if (msg[idx] == '\0') 널전송(pid); } func 시그널전송(pid, sig) { while() { if (sig & 1) kill(pid, SIGUSR1); else kill(pid, SIGUSR2); usleep(); } 신호 대기... if (SIGUSR2 받았을 때) printf("성공적으로 보냄"); }
C
복사
func server(sig) { unsigned char msg; while(msg != '\0') { if (sig == SIGUSR1) msg |= 1; else if (sig == SIGUSR2) msg |= 0; msg <<= 1; if (end) { msg 출력 msg 초기화 } } kill(client, SIGUSR2); 신호 대기... }
C
복사
클라이언트가 서버에 모든 문자를 보낸 뒤, 서버는 받은 문자들을 모두 출력 후 클라이언트에게 다시 잘 받았다는 신호를 보내줄 필요가 있다.
따라서 클라이언트가 서버로 NULL 문자를 연산하여 보내면 서버는 이를 인식 후 클라이언트를 향해 SIGUSR2를 보내주도록 설계하였다.

 Note

15년형 Macbook Pro로 작업을 하면서 비트 밀림 현상이 굉장히 많이 일어났다.
따라서 다른 분들의 가이드를 보고 참고 했던 딜레이 시간을 늘릴 수 밖에 없었다.
100글자를 출력 할 때 1초 이상이 걸리면 굉장히 오래 걸리는 것이라는 Instructions 내용에 따라서 비트를 한 번 보낼 때마다 125 마이크로초정도 usleep 하게 설정을 했었으나 위에서 언급한 바와 같이 비트 밀림 현상이 심하게 일어나 1250 마이크로초로 딜레이를 설정하였다.
구조를 여러번 바꾸어 보았으나 같은 현상이 지속적으로 발생하여 평가지에서 시간 측정 항목이 사라졌다고 들어, 딜레이는 디펜스로 처리 하려고 했다.
과제는 대부분 집에서 하고 평가는 클러스터에서 받는 편이라 클러스터에 가서 마지막 테스트를 하던 중 PC사양, 인터넷 연결 환경이 집보다는 클러스터가 더 많이 좋다고 생각 되어 딜레이를 125로 다시 재수정 하고 테스트를 했더니 비트 밀림 현상이 현저하게 줄어들었다.
따라서 집에서 테스트 시 비트 밀림 현상이 일어난다고 하더라도 클러스터에서 평가를 받게 된다면 125 마이크로초로 한 번 테스트 하는 것을 권해본다.

 Test

→ 100자
LoremipsumdolorsitametLoremipsumdolorsitametLoremipsumdolorsitametLoremipsumdolorsitametLoremipsumdo
→ Unicode
∑∞☞★
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

 Reference