[minitalk] 전체 코드 흐름, feedback

퐁퐁이·2022년 2월 16일
0

42SEOUL

목록 보기
11/12
  • unix 신호를 주고 받는 작은 데이터 교환 프로그램 코딩
  • 글자를 이진법으로 바꾸고 → 8비트 만큼 쪼개서 보냄 → 이를 받는 곳에서 다시 8bit를 1byte로 바꿔야함(복원)

client

client는 server의 pid와 송신할 문자열을 입력 인자로 받는다

  • PID, 인자 개수 예외처리
    - ./client <pid> "String" 형태의 인자 3개
    - 100 이하는 시스템 프로세스, 99999 초과는 맥 환경에서 존재할 수 없는 pid이므로 예외처리
  • 문자열을 받아서 비트 단위로 신호 송신하는 함수
    - unsigned char로 형변환하여 128~255까지 처리한다.
    - 문자열에서 char형 하나하나 체크
    1) 맨 앞자리부터 보내기 위해 7-bit index만큼 비트 시프트
    2) 비트연산자 AND 연산, 둘 중 하나라도 0이면 결과가 0
    3) kill(SIGUSR1) or kill(SIGUSR2)
    - bit 8개를 송신하면 서버 측에서는 write 함수를 호출한다. 이 write 함수를 호출할 때 걸리는 시간을 감안하여 usleep()을 해준다.

server

본인의 PID 정보 출력, 문자열이 수신되면 해당 문자열 표시

  • PID 정보 받아오기
    - 실행 중인 프로세스 ID를 구하고 본인의 PID 정보 출력
    - sa_sigaction 핸들러를 사용하기 위해 SA_SIGINFO를 넣음
    - sigaction SIGUSR1, SIGUSR2
    - signal이 들어올 때까지 무한대기 상태
  • 신호는 비트 단위로 하나 씩 수신, 수신된 비트를 char 형태로 변환
    - 내부 정적 변수로 선언 (함수가 여러 번 실행되어도 변수의 선언 및 초기화가 한 번만 이루어짐, 그 값을 지우지 않고 계속 기억하고 있는 것)
    - sig를 SIGUSR1, SIGUSR2 파악, 받은 순서대로 1 비트씩 기록한다.
    - 1을 만나면 SIGUSR1, 0을 만나면 SIGUSR2
    - bit가 8 미만이면 왼쪽으로 1만큼 시프트, 8비트가 되어지면 출력
    - bit 8개를 모두 수신 받으면 문자열의 끝을 알려주는 널 문자를 보내준다.

feedback

  • ft_atoi 함수 주의 (pid=ft_atoi(argv[1]))
    • 문자열로 들어온 pid를 int형으로 저장하기 위해 atoi 함수를 사용하게 된다. 이때, ft_atoi 함수의 오버플로우, 언더플로우 처리를 주의해야 한다. man atoi를 보면 다음과 같이 manual이 적혀있다.
      strtol 함수와 동일한 함수라면 strtol의 오버플로우, 언더플로우 처리와 동일해야 할 것이다. strtol은 언더플로우가 발생했을 경우에는 LONG_MIN을 반환하고 오버플로우가 발생했을 때는 LONG_MAX를 반환한다. 그러므로 ft_atoi도 이 반환값들로 처리를 해줘야한다.
      사실, libft 과제를 할 때 진작 처리를 해놓아야 했을 부분인데 나도 평가자도 아무도 캐치하지 못했었다. 나처럼 사람들이 이 부분을 놓치고 다음 과제를 진행하는 경우가 대다수인 것 같다. 다행히도 이번 minitalk 과제를 평가 받으면서 ft_atoi의 제대로 된 처리를 배우게 되었다. (jaham님 감사합니당)
  • unicode 작동 원리
    • unsigned char로 형변환 해서 128~255까지 처리 (char는 첫 번째 bit를 부호비트로 사용하지만 unsigned char는 부호를 고려하지 않는 1바이트 메모리. 즉, unsigned char는 8개 비트를 모두 데이터 비트로 생각하고 작업 진행)
    • UTF-8을 이해 할 필요가 있음. UTF-8은 1~4바이트로 인코딩 될 수 있으며 ASCII 문자와 호환이 된다.
    • 클러스터 맥기준 UTF-8를 사용하는데 UTF-8은 가변 인코딩 방식으로 되어있음
  • flag에 SA_SIGINFO를 사용해야 하는 이유
    • 이 과제에서는 SIGUSR1, SIGUSR2만 사용하는데 이 둘은 default로 지정된 동작은 프로세스의 종료
    • sa_flag에서 SIGINFO를 사용하지 않을 경우, sa_handler로 신호를 다루고, SIGINFO를 대입하면 sa_sigaction으로 신호를 다룬다.
    • sa_handlersa_sigaction 둘 다 handler인데, sa_handler는 인자 1개, sigaction은 인자 3개 필요함. 두 개를 동시에 사용할 수 없고, 둘 중에 하나만 사용해야 함. 어떤 거 사용할지를 sa_flags 옵션에서 알 수 있음
  • signalsigaction 차이
    • sigaction 함수를 사용하기 위해서는 sigaction구조체를 프로그램 코드 내부에 선언. signal 함수는 핸들러 함수를 등록하기 위해 사용하지만, sigaction 함수는 sigaction 구조체를 선언하고 내부에 핸들러를 등록한 뒤 그 구조체를 사용하기 때문
    • signal 함수와 sigaction 사이에 가장 큰 차이점은 sa_flag를 이용한 다양한 기능의 지원
    • 기본적으로 signal함수를 사용해서 신호를 컨트롤 할 수 있지만, sigaction함수는 sigaction 구조체를 사용해서 좀 더 다양한 정보를 가지고 신호를 다룰 수 있다
  • client 함수에서 usleep을 사용해야 하는 이유
    • 비트 8개를 송신하면 서버 측에서 출력 함수를 호출하므로 출력 함수 호출 시에 걸리는 시간을 감안하여 micro sec만큼 실행을 늦춘다. (씹힘 방지)
profile
코딩하는 에디

0개의 댓글