[OS] 프로세스 간 통신(IPC)
IPC 방법
1. Pipe
- Pipe
- 기존 파이프는 단방향 통신
- fork()로 자식 프로세스 만들었을 때, 부모 자식간의 통신
- 예시
int main() { char buf[255]; int fd[2], pid, nbytes; if ( pipe(fd) < 0 ) // pipe(fd) 로 파이프 생성 exit(1); pid = fork(); // 이 함수 실행 다음 코드부터 부모/자식 프로세스로 나누어짐 if (pid > 0) { // 부모프로세스에는 pid가 0이 들어감 write(fd[1], msg, MSGSIZE); } else { nbyte = read(fd[0], buf, MSGSIZE); // fd[0] 로 읽음 printf("%d %s \n", nbytes, buf); exit(0); } return }
2. Message Queue
-
메시지 큐는 기본적으로 FIFO 정책으로 데이터 전송
- 메시지 큐 코드 예제
- A process
msqid = msgget(key, msgflag); // key = 1234, msgflag는 옵션 msgsnd(msgid, &sbuf, buf_length, IPC_NOWAIT);
- B process
msgid = msgget(key, msgflag); // key는 동일하게 1234로 해야 해당 큐의 msgid를 얻을 수 있음 msgrcv(msqid, &rbuf, MSGSZ, 1, 0);
2.1 Pipe vs Message Queue
- A process
- Message Queue
- 부모/자식이 아니라, 어느 Process 간에라도 데이터 송수신 가능
- 먼저 넣은 데이터가 먼저 읽힘(FIFO)
- Pipe
- 부모/자식 프로세스간 통신
- 단방향 or 양방향
- 둘 다 Kernel space의 메모리 사용
- 메모리 공간도 kernal/user 로 구분 됨
3. Shared Memory
- 직접적으로 Kernel space에 메모리 공간을 만들고, 해당 공간을 변수처럼 쓰는 방식
- Message Queue 처럼 FIFO가 아니라, 해당 메모리 주소를 마치 변수처럼 접근하는 방식
-
Shared Memory key를 가지고, 여러 프로세스가 접근 가능
- 예시
- 공유 메모리 생성
sshmid = shmget((key_t)1234, SIZE, IPC_CREAT|0666)); shmaddr = shmat(shmid, (void *)0, 0);
- 공유 메모리에 쓰기
strcpy((char *)shmaddr, "Linux programming");
- 공유 메모리에서 읽기
printf("%s\n", (char *)shmaddr);
4. Signal
- UNIX에서 30년 이상 사용된 전통적인 기법
- 커널 또는 프로세스에서 다른 프로세스에 어떤 이벤트가 발생되었는지를 알려주는 기법
- 주요 시그널
- SIGKILL : 프로세스 죽이기
- SIGALARM : 알람 발생
- SIGSTP : 프로세스 멈추기
- SIGCONT : 멈춘 프로세스 실행
- SIGINT : 프로세스에 인터럽트를 보내서 프로세스를 죽이기
- SIGSEG : 프로세스가 다른 메모리영역을 침범
- 동작
- 프로그램에서 특정 시그널의 기본 동작 대신 다른 동작을 하도록 구현 가능
- 각 프로세스에서 시그널 처리에 대해 다음과 같은 동작 설정 가능
- Signal ignore
- Signal block (block을 푸는 순간, 해당 프로세스에서 Signal 처리)
- 프로그램 안에 등록된 Signal handler로 재정의한 특정 동작 수행
- 등록된 Signal handler가 없다면, 커널에서 기본 동작 수행
- 예시
-
Signal handler 등록 및 handler 구현
static void signal_handler (int signo) { printf("Catch SIGINT!\n"); exit (EXIT_SUCCESS); } int main() { if (signal(SIGINT, signal_handler) == SIG_ERR) { printf("Can't catch SIGINT!\n"); exit(EXIT_FAILURE); } for (;;) pause(); return 0; }
-
Signal handler 무시
int main() { if (signal(SIGINT, SIG_IGN) == SIG_ERR) { printf("Can't catch SIGINT!\n"); exit(EXIT_FAILURE); } for (;;) pause(); return 0; }
-
4.1. Signal 과 Process
- PCB에서 해당 프로세스가 block 또는 처리해야 하는 Signal 관련 정보 관리
5. Socket
- 소켓은 네트워크 통신을 위한 기술
- 기본적으로 클라이언트와 서버 등 두개의 다른 컴퓨터간의 네트워크 기반 통신을 위한 기술
5.1.1 소켓과 IPC
- 소켓을 하나의 컴퓨터 안에서 두 개의 프로세스 간의 통신 기법으로 사용 가능
- 리눅스 커널 내부 네트워크 stack 예시
참고
This is personal diary for study documents.
Please comment if I'm wrong or missing something else 😄.
댓글남기기