본문 바로가기

개발자/Linux

리눅스 IPC 프로그래밍(IPC종류) [1]

반응형

IPC(Inter Process Communication) - 프로세스 간 통신에 대하여 종류와 특징들에 대하여 살펴보겠습니다.

 

[리눅스 커널 구조]

- 위 그림처럼 Process 완전히 독립된 실행객체입니다. 서로 독립되어 있다는 것은 다른 프로세스의 영향을 받지 않는다는 장점이 있습니다. 그러나 독립되어 있는 만큼 별도의 설비가 없이는 서로간에 통신이 어렵다는 문제가 있게 됩니다. 이를 위해서 커널 영역에서 IPC라는 내부 프로세스간 통신 - Inter Process Communication 제공하게 되고, 프로세스는 커널이 제공하는 IPC설비를 이용해서 프로세스간 통신   있게 됩니다.


0. 시그널 (Signal)

예전에 상훈이가 스터디때 강조했던 시그널은 임의의 프로세스에세 특정 이벤트가 발생했다는 사실을 알려주는 매커니즘이지요.

(예를들어, 리눅스에서 Ctrl + C 가 눌리면 SIGINT시그널이 프로세스에 전달되어 중단되는 것처럼)
이것은 이벤트 발생 -> 시그널 전달 -> 시그널 처리 의 순으로 진행됩니다.

시그널의 종류는 운영체제에서 미리 정의하며, 그러므로 운영체제에 따라서 다르겠지요.

근데 엄밀히 말해서 시그널은 신호를 발생시키는 매커니즘이고, 데이터를 전달하는 매커니즘은 아닙니다.

시그널 전달이 이뤄지는 과정은 다음과 같습니다.

일단 PCB(Process Control Block ; 리눅스에서 task_struct 같은~ )에 시그널 개수만큼 미리 확보된 시그널 벡터가 있습니다.

시그널 개수만큼 확보되어있기 때문에, 평소에는 0으로 clear되어 있다가 해당 시그널이 발생하면 그 bit만 1로 set 해주면 되는것이지요.

즉, 3번 시그널이 전달되면 3번 시그널벡터가 1로 set되는 것입니다.

시그널이 발생하면, 프로세스는 기존의 수행 흐름에서 벗어나, 해당 시그널 핸들러를 수행합니다.

시그널 핸들러는 커널이 지정해놓을 수도 있고(예를들어 프로세스 종료, 시그널 무시, 프로세스 중지, 실행 재개 등등) 사용자가 특정 기능을 수행하는 코드도 등록해 놓을 수 있습니다.

시그널 핸들러는 시그널 공간 할당 후에 함수포인터를 만들어서 시그널을 처리할 함수의 주소를 가리키도록 해놓는 방식으로 구현하게 됩니다.

그렇다면 이제 데이터를 통신하는 IPC 매커니즘에 대해 알아봅시다.

 

출처: https://sugerent.tistory.com/163 [MISTERY]
출처: https://jwprogramming.tistory.com/54 [개발자를 꿈꾸는 프로그래머]

1. IPC의 종류 

  1) PIPE

  2) Named PIPE

  3) Message Queue

  4) Shared Memory

  5) Memory Map

  6) socket

 

2. IPC 별 사용 시기 및 특징

IPC 종류

 PIPE

Named PIPE 

Mesage Queue 

Shared Memory 

Memory Map 

Socket 

사용

시기

 부모 자식 간

단 방향 통신 시

다른 프로세스와 

단 방향 통신 시 

다른 프로세스와

 단 방향 통신 시  

다른 프로세스와

양 방향 통신 시 

다른 프로세으와 

양 방향 통신 시 

 다른 시스템간 

양 방향 통신 시

 공유

매개체

파일 

파일 

메모리 

메모리 

파일+메모리 

소켓 

통신

단위

 Stream

Stream

구조체

구조체 

페이지

Stream 

 통신

 방향

 단 방향

당 방향 

단 방향 

양 방향 

양 방향 

양 방향 

 

3. IPC별 세부 설명

  1) PIPE

    (1) 정의

      - 익명의 PIPE를 통해서 동일한 PPID를 가진 프로세스들 간에 단방향 통신을 지원

    (2) 구조

      -  FIFO 구조

      - 생성된 PIPE에 대하여 Write 또는 Read만 가능

    (3) 사용 시기

      - 부모 자식 프로세스간 통신 할때 사용

    (4) 유의사항

      - 쌍방 통신을 위해서는 Write용 PIPE하나 Read PIPE하나 씩 만들어야 한다.

      - read()와 write()가 기본적으로 block 모드로 작동하기 때문으로 프로세스가 read대기중이라면

        read가 끝나기 전에는 write를 할수가 없게 된다.

    (5) 도식화

    (6) 예제 코드 링크 

      - [IPC] pipe 예제 코드

 

  2) Named PIPE

    (1) 정의

      - 이름을 가진 PIPE를 통해서 프로세스들 간에 단방향 통신을 지원

      - 서로 다른 프로세스들이 PIPE의 이름만 알면 통신이 가능하다.

    (2) 구조

      - FIFO 구조

      - 생성된 PIPE에 대하여 Write 또는 Read만 가능

    (3) 사용 시기

      - 연관이 전혀 없는 프로세스간에 통신을 할때

    (4) 유의사항

      - 쌍방 통신을 위해서는 Write용 PIPE하나 Read PIPE하나 씩 만들어야 한다.

      - read()와 write()가 기본적으로 block 모드로 작동하기 때문으로 프로세스가 read대기중이라면

        read가 끝나기 전에는 write를 할수가 없게 된다.

    (5) 도식화

    (6) 예제 코드 링크 

      - [IPC] name pipe 예제 코드

 

  3) Message Queue

    (1) 졍의

      - 메모리를 사용한 PIPE이다.

      - 구조체 기반으로 통신을 한다.

    (2) 구조

      - FIFO 구조

      - msgtype에 따라 다른 구조체를 가져올수 있다.

    (3) 사용시기

      - 프로세스간 다양한 통신을 할 때 사용 할수 있다.

    (4) 유의사항

      - 커널에서 제공하는 Message queue이기에 EnQueue 하는데 제한이 존재 한다.

    (5) 도식화

 

    (6) 예제 코드 링크 

      - [IPC] message queue 예제 코드

 

  4) Shared Memory

    (1) 졍의

      - 시스템 상의 공유 메모리를 통해 통신한다.

    (2) 구조

      - 일정한 크기의 메모리를 프로세스간에 공유하는 구조

      - 공유 메모리는 커널에서 관리 된다,

      * 자세한 정보 : [메모리] share memory 사용법

    (3) 사용시기

      - 프로세스간 Read, Write를 모두 필요로 할때

    (4) 유의사항 

      - 프로세스간의 상요할려면 메모리 크키가 동일 해야 한다.

    (5) 도식화

    (6) 예제 코드 링크 

      - [IPC] shared memory 예제 코드

  

  5) Memory Map

    (1) 정의

      - 파일을 프로세스의 메모리에 일정 부분 맵핑 키셔 사용한다.

    (2) 구조 (위키 설명 : 메모리 맵 파일 )

      - 위키보다 더 잘 설명할 자신이 없기에 위키 내용으로 대체합니다.

메모리 맵 파일을 사용하면 디스크에 있는 파일의 블록들과 프로세스의 페이지가 연결된다. 이 상태에서는 가상 메모리에 사상만 되어 있을 뿐이며, 실제 메모리에 파일을 불러오는 시기는 해당 주소에 읽거나 쓰기 작업을 시도할 때 이루어진다. 이 작업은 운영 체제에서 가상 메모리를 다루는 데 사용하는 페이징 기법과 같이 페이지 부재를 일으키는 방식을 이용한다. 일반적으로 파일에서 불러오는 자료는 페이지 크기와 같은 4KiB이지만, 몇몇 운영 체제에서는 하드디스크의 낮은 임의 접근 시간을 고려해 4KiB보다 많은 자료를 페이지로 올릴 수도 있다.

이 때문에 메모리 맵 파일로 작업 중인 데이터가 실제 파일로 바로 반영되지는 않으며, 페이지 교체 알고리즘에 따라 해당 페이지가 메모리에서 내려갈 경우, 또는 메모리 맵 파일을 닫는 과정에서 반영된다. 이것은 메모리 맵 파일과 파일 입출력 API를 동시에 사용할 때 문제가 되는데, 메모리 맵 파일을 통해 변경된 자료는 즉시 반영되지 않으므로 그 지점에 해당하는 자료를 파일 입출력 API를 사용하여 읽어오려 할 때 동기화 문제가 발생하게 된다. 따라서 메모리 맵 파일을 사용할 때에는 읽기 전용으로만 사용하는 목적이 아닌 이상 파일 입출력 API를 사용하지 않는 것이 좋다.

오른쪽 위의 예제 그림은 메모리 맵 파일을 사용할 때 프로세스의 가상 주소와 물리 주소, 그리고 파일들의 관계를 알 수 있다. 각 블록은 페이지 단위로 나타낸 것이다. 예제에서는 프로세스 2개와 파일 2개가 나오며, 이중 b2는 메모리 맵 파일의 공유를, b3는 사상이 되었으나 아직 메모리에 적재되지 않은 것을 나타낸다.

    (3) 사용시기

      - 파일로 대용량 데이터를 공유 할 때 사용한다.

      - FILE IO가 느릴때 사용하면좋다.

      - 대부분 운영 체제에서는 프로세스를 실행할 때 실행 파일의 각 세그먼트를 메모리에 사상하기 위해 

        메모리 맵 파일을 이용한다.

    (4) 유의 사항

      - write시기는  프로세스의 페이지가 메모리에에서 내려갈 때만 Write된다. 

        이렇게 때문에 메모리와 file Sync가 안맞을수 도있다.

      - IA-32 기반 시스템에서 하나의 프로세스에서 PAE 기술을 사용하지 않고 사용 가능한 최대 크기는

        4GB로 제한된다

      - 메모리 맵 파일은 파일의 크기를 바꿀 수는 없으며 메모리 맵 파일을 사용하기 이전, 또는 이후에만 

        파일의 크기를 바꿀 수 있다.

    (5) 도식화

    (6) 예제 코드 링크 

      - [IPC] 메모리 맵 mmap() 예제 코드

 

  6) Socket

    (1) 정의

      - 네트워크 소켓통신을 시용한 데이터 공유

    (2) 구조

      - 네트워크 소켓을 이용하여 Client - Server 구조로 데이터 통신

    (3) 사용시기

      - 원격에서 프로세스간 데이터를 공유 할 때 사용

    (4) 유의 사항

      - 네크워크 프로그래밍이 가능해야 한다.

      - 데이터 세그먼트 처리를 잘해야한다.

    (5) 도식화


7) Semaphore

- Semaphore는 Named PIPE, PIPE, Message Queue와 같은 다른 IPC설비들이 대부분 프로세스간 메시지 전송을 목적으로 하는데 반해, Semaphore는 프로세스 간 데이터를 동기화 하고 보호하는데 그 목적을 두게 됩니다. 프로세스간 메시지 전송을 하거나, 혹은 Shared Memory를 통해서 특정 데이타를 공유하게 될 경우 발생하는 문제가 공유된 자원에 여러개의 프로세스가 동시에 접근하면 안되며, 단지 한번에 하나의 프로세스만 접근 가능하도록 만들어줘야 할 것이며, 이 때 사용되는 것이 Semaphore입니다. 자세한 부분은 이전에 포스팅했던 Semaphore와 Mutex 부분에서 다루고 있으므로 생략하도록 하겠습니다.



출처: https://jwprogramming.tistory.com/54 [개발자를 꿈꾸는 프로그래머]
출처: https://doitnow-man.tistory.com/110 [즐거운인생 (실패 또하나의 성공)]

반응형