36940db938a8f4a1e919496793ed439850a221c2다. 이 글의 IPC는 서로 다른 도메인 또는 CPU 사이의 서비스 API를 뜻한다. 기존 IPC / Synchronization 글의 semaphore·mutex·k_msgq는 같은 커널 이미지 안의 객체다. 여기의 도식은 Zephyr 원본 그림을 복사하지 않고 소스의 책임 경계를 다시 그렸다.1. instance는 물리적 길, endpoint는 애플리케이션의 연결점
ipc_service_open_instance()가 받는 device는 backend가 만든 통신 instance다. instance의 물리 경로와 내부 구조는 backend에 달려 있다. 애플리케이션은 그 instance에 ipc_service_register_endpoint()로 endpoint를 등록하고, 등록된 struct ipc_ept로 송신한다. 두 이미지의 객체 주소를 공유한다는 뜻이 아니다. 반대로 k_msgq는 한 Zephyr 커널의 큐 객체에 고정 크기 항목을 복사한다.
↔ 좁은 화면에서는 왼쪽 이미지에서 오른쪽 이미지까지 가로로 이동해 보세요.
이미지 A · 로컬 도메인
ipc_ept로 send, received callback으로 수신공유 RAM ↔알림
MBOX ↔
이미지 B · 원격 도메인
| 질문 | k_msgq | IPC Service endpoint |
|---|---|---|
| 어디를 연결하나? | 같은 커널 이미지의 thread·ISR | 두 도메인/CPU의 각 이미지 |
| 호출자가 쥐는 객체 | 커널 큐 객체 주소 | instance device와 등록된 endpoint |
| 전송의 구현 | 큐의 고정 크기 항목 복사 | 선택한 backend의 전송·알림 방식 |
| 수신 준비의 신호 | 큐 초기화와 항목 유무 | 양쪽 endpoint 결합을 알리는 bound callback |
근거: IPC Service instance·endpoint 정의, v3.7.0 k_msgq 객체와 복사, ICMsg 공유 메모리·MBOX.
2. 등록에 성공했다고 원격 결합이 완료된 것은 아니다
애플리케이션은 instance를 먼저 연 뒤 endpoint 설정과 객체를 등록한다. ipc_ept_cfg가 가리키는 설정은 endpoint를 사용하는 동안 살아 있어야 한다. register_endpoint()의 반환 0은 로컬 등록 성공이며, 원격 endpoint까지 결합됐다는 확인은 bound callback에서 온다. 그래서 callback은 결합 신호를 기록하고, 실제 송신 흐름에서는 첫 send의 반환값까지 확인한다.
↔ 좁은 화면에서는 ①부터 ⑤까지 오른쪽으로 이동하세요. 주황 칸이 결합 경계입니다.
DEVICE_DT_GET(DT_NODELABEL(ipc0))device와 backend 구성이 이 보드 이미지에 있는지 확인
open_instance → register_endpoint각 반환값 확인. 설정 객체의 수명 유지
peer endpoint + transport반대쪽 이미지도 같은 통신 관계로 준비
cfg.cb.bound(priv)callback은 결합 신호 기록. 깨어난 thread의 첫 송신도 결과 확인
send → received바이트 수 또는 음수 오류와 수신 버퍼 수명 확인
v3.7.0 ICMsg의 작은 순서 차이. ICMsg 라이브러리는 결합 패킷을 읽은 뒤 bound callback을 호출하고 이어서 내부 상태를 READY로 바꾼다. callback 본문이나 그 신호로 곧바로 깨어난 thread가 상태 변경보다 먼저 ipc_service_send()를 실행하면 -EBUSY가 나올 수 있다. callback 안에서 바로 송신하지 말고 별도 실행 흐름에서 첫 송신 오류를 검사해 제한된 재시도·오류 처리를 둔다.
근거: endpoint 설정 수명·API, open·register 위임, ICMsg callback과 READY 설정 순서, READY 전 송신 결과.
3. 한 API라도 backend가 endpoint 수와 기능을 정한다
IPC Service는 앱을 backend 세부 구현에서 떼어 놓는 인터페이스지만 기능을 자동으로 같게 만들지는 않는다. v3.7.0의 ICMsg는 인스턴스마다 endpoint 하나를 열고 공유 RAM의 packet buffer와 MBOX를 쓴다. ICBMsg는 ICMsg 위의 블록 할당을 사용해 여러 endpoint와 no-copy 버퍼 API를 제공한다. 양쪽 이미지는 각자의 TX/RX region과 MBOX 방향을 맞춰야 한다.
| v3.7.0 backend | endpoint | 전송 구성 | 이 글에서 주의할 API |
|---|---|---|---|
| ICMsg | instance당 1개 | 공유 RAM packet buffer + MBOX | send는 있으나 no-copy hook 없음. 추가 채널은 별도 instance 필요 |
| ICBMsg | 여러 개, 설정된 개수 한도 | 공유 RAM 블록 + ICMsg 제어 경로 + MBOX | get_tx_buffer·send_nocopy·RX hold/release hook 제공. 이 버전의 backend에는 close/deregister hook 없음 |
공통 wrapper는 해당 backend의 함수 포인터로 위임한다. 예컨대 v3.7.0의 ipc_service_get_tx_buffer()는 backend에 관련 hook이 없으면 -EIO를 반환한다. API 문서의 선택적 no-copy 설명만 보고 ICMsg에서 no-copy가 가능하다고 판단할 수 없다. ICBMsg의 여러 endpoint도 무한 개가 아니며 메모리와 설정 한도를 따른다.
근거: ICMsg 1 endpoint·region/MBOX 구성, ICBMsg 다중 endpoint·블록 할당, ICMsg backend ops, ICBMsg backend ops, no-copy hook 검사.
4. received 포인터와 no-copy TX 포인터의 소유권을 분리한다
기본 ipc_service_send()는 호출자 버퍼와 길이를 backend에 넘기고 전송 결과로 보낸 바이트 수 또는 음수 오류를 받는다. no-copy 지원 backend에서는 get_tx_buffer()로 얻은 TX 공간을 채우고 send_nocopy()로 넘긴다. 성공적으로 넘긴 뒤 송신자는 그 포인터를 더는 만지면 안 된다. 전송하지 않는 버퍼는 drop_tx_buffer()로 반납한다. 실패하면 API 계약과 backend의 실제 반환을 확인한 뒤 반납 경로를 처리한다. 수신 포인터를 callback 뒤에도 직접 쓰려면 received callback이 반환되기 전에 지원 backend의 hold_rx_buffer()가 성공해야 한다.
↔ 좁은 화면에서는 왼쪽의 확보부터 오른쪽의 해제까지 이동하세요.
지원 backend만
get_tx_buffer()빈 전송 버퍼 획득
send_nocopy() 성공 후 송신자 접근 중지drop_tx_buffer(). 송신 오류 때는 backend의 해제 상태 확인수신 측
received(data,len)backend가 제공
hold_rx_buffer() 성공해야 밖에서 직접 사용 가능release_rx_buffer(); 보유하지 않았다면 callback 반환 후 사용 금지| 경로 | 안전한 기본 규칙 | 특히 피할 오해 |
|---|---|---|
일반 send | 전송 결과를 바이트 수와 음수 오류로 검사 | 반환 0을 모든 데이터 전송 성공으로 취급 |
| no-copy TX | 지원 여부, 획득 크기, backend별 반환과 성공 뒤 소유권 이전을 확인 | 반환 양수를 항상 payload 길이로 해석하거나, 보낸 뒤 같은 포인터를 수정 |
received | callback 안에서 소비·복사; 밖에서 직접 쓰려면 callback 반환 전 hold 성공 후 release | callback의 data를 영구 버퍼처럼 저장 |
근거: v3.7.0 no-copy 사용 예시, TX 확보·전송·반납·RX hold/release 계약, received callback 버퍼 수명, ICBMsg 버퍼 hook.
ICBMsg v3.7.0의 no-copy 반환은 별도로 읽는다. 일반 send()는 성공 시 payload 길이를 반환하지만, 이 버전의 send_nocopy()는 send_block()을 거쳐 내부 ICMsg 제어 메시지의 송신 결과를 그대로 반환한다. 따라서 양수 반환을 payload 길이와 비교해 전송 실패로 처리하면 안 된다. 또한 일부 오류 경로는 TX 블록을 이미 해제하므로 오류마다 무조건 다시 drop_tx_buffer()를 호출하지 않는다. 이는 공통 API 문구만으로 알 수 없는 고정 backend의 예외다. 근거: 제어 메시지 반환·블록 해제, no-copy 위임.
5. 실패는 등록, 결합, 전송, 버퍼 단계에서 따로 관찰한다
하나의 “IPC 실패”로 뭉뚱그리면 조치가 달라진다. 로컬 등록 반환과 원격 결합 신호, 송신 반환, 버퍼 할당 결과를 순서대로 기록한다. 아래 오류는 가능한 예시이며 backend가 더 구체적인 errno를 돌려줄 수 있다.
| 관찰 지점 | 가능한 신호 | 바로 확인할 것 |
|---|---|---|
| instance open | -EINVAL, -EIO, backend별 errno | DT node·device 준비·backend 연결 |
| endpoint register | -EINVAL, -EBUSY, backend별 errno | cfg/object 수명과 instance·endpoint 수 한도 |
| 결합 대기 | 등록은 0이나 bound 미도착 | 원격 이미지 기동, region과 MBOX 방향, 양쪽 endpoint 구성 |
send | -ENOENT, -EBUSY, -EBADMSG, 메모리/버퍼 오류 | 등록 상태, 결합 시점, 길이와 가용 공간; 실제 backend errno |
| no-copy API | 지원 hook 부재 또는 버퍼 부족 | 선택 backend ops, 요청 길이, 획득·반납 균형 |
반환값은 전송 보증서가 아니다. ipc_service_send()의 양수 바이트 수는 로컬 backend가 그만큼 송신 처리했음을 나타낸다. 원격 애플리케이션이 처리했는지까지 확인하려면 상위 프로토콜에서 응답·타임아웃·재시도 정책을 별도로 설계해야 한다. 이 부분은 서비스 API의 제공 범위를 바탕으로 한 설계상 추론이다.
근거: open·register·send 반환 계약, backend send 위임, ICMsg READY·길이·MBOX 오류.
6. 실제 보드 검증은 두 이미지의 배치도부터 시작한다
서로 다른 보드·SoC에 모든 backend가 똑같이 붙는다고 가정할 수 없다. 예를 들어 ICMsg라면 두 이미지의 tx-region과 rx-region이 반대로 대응하고, 공유 가능한 물리 RAM과 송수신 MBOX 채널이 맞아야 한다. cache를 쓰는 쪽이 있다면 양쪽의 정렬·cache 운용도 함께 확인한다. 애플리케이션 로그는 등록 성공과 결합 완료를 별도 timestamp로 남긴다.
각 이미지의 zephyr.dts·.config에서 backend compatible, 두 region, MBOX, endpoint 수 설정을 대조한다.
양쪽 open/register 반환, bound callback, 첫 send의 시각과 반환값을 따로 기록한다.
최대 길이 근처와 빈 메시지, 버퍼 부족을 넣어 backend별 errno와 원격 수신 길이를 확인한다.
callback 밖으로 넘기는 payload는 복사하거나 지원 backend에서 hold/release 성공을 추적한다.
이 글은 v3.7.0 API·backend 소스를 읽어 만든 설계 지도다. 특정 보드의 양쪽 이미지를 빌드하거나 실제 MBOX·공유 RAM 전송을 수행한 측정 결과는 포함하지 않는다.
7. 고정 버전 근거와 이어 읽기
문서와 구현 기준을 모두 Zephyr v3.7.0에 고정했다. 최신 개발판의 backend 기능·callback 구성·오류 반환을 이 글에 소급하지 않았다.
| 고정 근거 | 이 글에서 확인한 범위 |
|---|---|
| IPC Service 공식 문서 | instance/endpoint 정의, 등록 순서, buffer API 계약 |
| ipc_service.h · ipc_service.c | callback 수명과 wrapper의 backend 위임·hook 검사 |
| ipc_icmsg.c · icmsg.c | endpoint 한 개, READY 설정 순서, 송신 errno |
| ipc_icbmsg.c · ICBMsg 문서 | 다중 endpoint·블록·no-copy hook |