IPC
프로세스간 통신은 서로 다른 프로세스가 데이터를 교환할 수 있도록 하는 통신 메커니즘이다.
pipe
부모 프로세스와 자식 프로세스 사이에서 간단하게 데이터를 주고 받기 위해 사용되는 단방향 통신 방법이다. 한쪽 프로세스가 쓰고 다른 쪽 프로세스가 읽는 방식으로 작동하며 기본적으로 데이터를 한방향으로만 전달한다.
socket
네트워크 통신을 위한 양방향 통신 방법으로 동일한 시스템 뿐만 아니라 네트워크를 통해 다른 시스템과도 통신할 수 있다. TCP/IP 와 같은 프로토콜을 사용하며 클라이언트와 서버간의 통신을 설정하고 데이터를 주고 받을 수 있다.
named pipe
naemd pipe는 이름이 붙어있어 부모-자식 관계가 아닌 프로세스 간에도 사용할 수 있는 통신 방식이다.
named pipe는 다음과 같은 특징이 있다.
- 단방향 통신
- 일반 파이프와 마찬가지로 데이터를 보내는 쪽과 받는 쪽이 미리 정해져야 한다.
- 데이터를 양방향으로 주고 받으려면 두개의 파이프가 필요하다.
- 주로 FIFO 방식으로 통신
mkfifo 명령어로 네임드 파이프 생성할 수 있다.
#!/bin/bash
mkfifo -m 0600 fifo # FIFO 파일 생성
wc -l < fifo & # FIFO에서 읽은 내용을 wc 명령으로 처리
cat /etc/passwd > fifo # /etc/passwd 파일을 fifo로 보냄
cat < fifo # 다른쪽 터미널에서 확인
rm fifo # 작업 완료 후 FIFO 파일 삭제
shared memory
가장 빠른 IPC 방식 중 하나로 여러 프로세스가 동일한 메모리 영역을 공유하여 데이터를 주고 받는 방식이다. 복사 과정 없이 직접 메모리를 참조할 수 있기 때문에 성능이 매우 빠르다.
프로세스들이 shm_open, mmap 등의 시스템 콜을 통해 동일한 물리적 메모리 영역을 매핑하고 그 메모리에서 데이터를 읽거나 쓸 수 있다. 동시 접근 제어가 필요하며 semaphore나 mutex 같은 동기화 기법이 필수적이다.
- mmap(start, length, prot, flags, fd, offset) : 메모리 매핑 함수
- fd가 실제 파일이면 파일의 일부를 메모리에 매핑
- 파일로의 접근을 read / write 호출 없이 일반적인 메모리 접근 이랑 동일하게 사용가능
- shm_open 으로 얻어진 경우는 특정 물리 메모리를 매핑: 공유 메모리로 사용
- start 는 NULL, flag는 MAP_SHARED 를 일반적으로 사용, prot 은 읽기/쓰기 가능 여부 지정
- fd가 실제 파일이면 파일의 일부를 메모리에 매핑
- shm_open(name, flags, mode): name의 이름으로 공유메모리를 오픈
- 실제 파일은 아니지만 일반적으로 name 은 "/"로 시작하는 것을 추천
- 맨처음에는 O_CREATE 로 생성해야함(/dev/shm 밑에 생성되며 재부팅하면 사라짐)
- ftruncate(fd, size): 파일 크기를 설정(공유 메모리는 메모리의 크기 설정)
Named Semaphore
동시에 여러 프로세스가 접근하면 안되는 자원을 보호하기 위한 기법으로 세마포어는 여러 프로세스 간 동시 접근을 조율하며 특정 자원의 접근을 제한하는 데 사용된다. named semaphore는 이름이 있는 세마포어로 서로 다른 프로세스에서 공통의 세마포어에 접근할 수 있도록 지원한다.
Futex(Fast user-space Mutex) 라는 기법도 많이 사용된다.
semaphore와 mutex의 차이
- mutex는 해당 자원의 접근은 모두 상호 배제, 즉 한번에 하나
- semaphore 는 해당 자원에 동시 접근 가능한 수 제한, 즉 한번에 하나 이상
semaphore는 특정 서버 자원에 대한 최대 동시 연결 수를 제한할 때 유용하다. named semaphore는 이를 여러 프로세스에서 공유할 수 있도록 해주기 때문에 공통의 리소스에 대한 접근 제어에 사용된다.
- sem_open(name, flags, mode, value):
- 지정한 이름의 네임드 세마포어를 생성하거나 연다.
- value는 동시에 접근 가능한 프로세스 수를 나타낸다. 예를 들어, value가 3이면 최대 3개의 프로세스가 동시에 자원에 접근할 수 있다.
- O_CREAT 플래그를 사용하면 세마포어가 존재하지 않을 때 새로 생성합니다. /dev/shm 아래에 sem.* 형태로 생성됩니다.
- sem_wait(sem):
- 해당 세마포어에 대한 제어권을 얻다. 세마포어의 카운터를 감소시키고, 만약 카운터가 0이면 다른 프로세스가 제어권을 내려놓을 때까지 대기한다.
- sem_post(sem):
- 세마포어의 제어권을 내려놓다. 세마포어의 카운터를 증가시켜, 대기 중인 다른 프로세스가 자원에 접근할 수 있게 한다.
Signal
프로세스에게 뭔가
Systemd
서비스 데몬의 목적은 어플리케이션으로부터 요청을 받아서 그 요청을 서비스 데몬이 대신 수행하기 위함이다.
따라서 server-client 구조로 동작하면 좋은데 이 구조로 동작하는 대표적인 IPC가 Socket이다.
systemd 데몬의 가장 기본적인 동작은 소켓을 열고 listen하고 있다가 요청이 오면 요청을 accept해서 쿼리하고 listen을 계속하는 것이다.
동작 순서
- Systemd가 소켓을 열어 listen 상태로 둔다.
- 소켓에 접속 요청이 발생하면, Systemd는 서비스를 실행한다.
- 서비스 데몬은 실행된 후 accept 처리를 시작한다.
- 처리가 완료되면 서비스는 종료되고 대기 상태로 돌아간다.
- 이후 요청이 들어올 때마다 2~4의 과정이 반복된다.
sd_listen_fds(0): systemd로부터 현재 서비스 데몬에서 사용할 수 있는 소켓을 획득한다.
- systemd가 관리하는 파일 디스크립터(FD)들을 반환하며, 기본적으로 SD_LISTEN_FDS_START부터 시작된다.
- 반환값에 따라 여러 소켓을 사용할 수 있다.
소켓을 사용할 때 옵션:
- accept 옵션을 사용하지 않은 소켓이 하나 있을 경우, 반환된 값은 1개이다.
- accept=yes를 사용하면 systemd가 accept도 대신 처리해주지만, 성능 상의 이유로 추천되지 않는다.
빌드 시 systemd/sd-daemon.h를 포함해야 하며, libsystemd.so를 링크하여 사용할 수 있다.
Buildroot 환경에서는 --sysroot=<빌드루트 디렉토리>를 사용하여 systemd 라이브러리 경로를 지정해줘야 한다.
동작 순서:
- systemd가 소켓을 열고 listen 상태로 유지한다.
- 클라이언트로부터 소켓 접속 요청이 들어오면 systemd가 해당 요청을 서비스 데몬으로 전달하고 데몬을 실행한다.
- 이후 데몬은 시스템이 종료되거나 더 이상 처리할 것이 없으면 종료된다.
SDK
'System Programming > Linux Device Driver' 카테고리의 다른 글
Netlink Sockets #1 내부 아키텍쳐, 메세지 포맷 (0) | 2024.10.27 |
---|---|
Linux Device Driver 기초 #5 문자 드라이버 (0) | 2024.10.27 |
Linux Device Driver 기초 #3 Linux Device Driver 추가하기 (0) | 2024.10.13 |
Linux Inside #1 Booting: Bootloader에서 Kernel까지 (0) | 2024.10.01 |
BuildRoot 사용법 요약 (1) | 2024.09.20 |