기록

[GPT가 알려주는] service & system 구조 파악 (dds 포팅 시도 중) 본문

잡동사니/GPT가 알려주는

[GPT가 알려주는] service & system 구조 파악 (dds 포팅 시도 중)

heylo 2025. 12. 5. 09:19

좋아, 지금 보여준 이 작은 tree 구조만 두고 “얘네가 서로 무슨 관계인지”부터 딱 정리해볼게.
(실제로 뭐가 빠졌는지보다, 레이어 구조가 먼저 이해되면 나머지는 그냥 패턴 맞추기라 훨씬 쉬워짐.)


1. 제일 위: vendor/ivi/services/* = 안드로이드 서비스 레이어

vendor/ivi/services
├── canservice
│   ├── can
│   │   ├── aidl
│   │   ├── Android.bp
│   │   ├── lib
│   │   └── service
│   ├── can_service.mk
│   └── sepolicy/...
└── ddsservice
    ├── dds
    │   ├── aidl
    │   ├── Android.bp
    │   ├── lib
    │   └── service
    ├── dds_service.mk
    └── sepolicy/...

여기의 공통점

  • aidl/
    • 앱이 사용할 Binder 인터페이스 정의 (ICanService, IDdsService 같은 것들)
  • lib/
    • AIDL을 감싸는 Java 래퍼 (CanManager, DdsManager)
    • 앱이 직접 쓰는 클라이언트 라이브러리
  • service/
    • 실제로 돌아가는 프로세스 소스
    • 빌드되면 /vendor/bin/can_svc, /vendor/bin/dds_svc 같은 바이너리가 되는 애들
    • 여기 Android.bp 에 cc_binary { name: "can_svc" ... } 같은 게 있음
  • *_service.mk
    • “이 모듈들을 PRODUCT에 포함시켜라”라고 상위 빌드에 알려주는 make 스크립트
  • sepolicy/
    • can_svc, dds_svc에 대한 SELinux 설정

👉 한 줄로 말하면:

vendor/ivi/services/* = 앱 ↔ (밑단 엔진) 사이를 Binder(AIDL)로 이어주는 안드로이드 서비스 계층


2. 중간: vendor/ivi/system/ccs/{j1939, dds} = CCS 엔진(HAL/daemon) 레이어

vendor/ivi/system/ccs
├── j1939
│   ├── Android.bp
│   ├── build
│   ├── include
│   ├── ipc
│   ├── j1939_service.mk
│   ├── j1939_service.rc
│   ├── service.cpp
│   └── src
└── dds
    ├── Android.bp
    ├── build
    ├── dds_module.mk
    ├── dds_module.rc
    ├── include
    ├── ipc
    ├── lib
    ├── module.cpp
    └── src

여긴 CAN/dDS 자체가 아니라, **“CCS 내부에서 CAN + DDS 프로토콜을 관리하는 엔진”**이라고 보면 돼.

j1939 쪽

  • ipc/1.0/*.hal
    • HIDL HAL 인터페이스 (IJ1939.hal 등)
  • src/, service.cpp
    • J1939 메인 로직, HAL 구현
  • j1939_service.mk
    • 이 모듈(j1939 엔진)을 빌드 타깃에 올리는 make 파일
  • j1939_service.rc
    • init에 등록되는 서비스 정의
    • /vendor/etc/init/j1939_service.rc 로 가서
      service j1939_service /vendor/bin/j1939_service 이런 식으로 데몬 띄움

👉 즉:

system/ccs/j1939 = “J1939 전용 네이티브 데몬 + HAL”


dds 쪽

  • ipc/1.0/*.hal
    • IDDS.hal, IDDSCallback.hal = DDS용 HIDL 인터페이스
  • lib/
    • libfastdds.so, libfastcdr.so 같은 Fast-DDS 라이브러리
  • src/, module.cpp
    • DDSHal, DDSManager, Fast-DDS 연동 로직
  • dds_module.mk
    • DDS 모듈(엔진)을 빌드 타깃에 올리는 make 파일
  • dds_module.rc
    • init에서 DDS 네이티브 모듈을 띄우는 서비스 정의
    • /vendor/etc/init/dds_module.rc 로 가서
      service dds_module /vendor/bin/dds_module 같은 데몬 정의 예상

👉 즉:

system/ccs/dds = “DDS 전용 네이티브 엔진 + Fast-DDS 라이브러리 + HAL”

j1939와 DDS의 차이점은 이름만 다르고, 역할 구조는 거의 똑같다고 보면 된다.


3. 세 레이어를 한 번에 보면 이렇게 됨

CAN 쪽 흐름:

  1. 커널:
    • CONFIG_CAN=y, CONFIG_CAN_VCAN=y → vcan0 인터페이스 생김
  2. CCS 엔진 (vendor/ivi/system/ccs/j1939)
    • J1939 HAL + 서비스 데몬 (j1939_service.cpp, j1939_service.rc)
  3. 안드로이드 서비스 (vendor/ivi/services/canservice)
    • can_svc (Binder 서비스) + AIDL + Java CanManager

DDS 쪽 흐름:

  1. 커널:
    • DDS는 커널 모듈이 아니라 유저 공간에서 Fast-DDS 라이브러리를 쓰는 구조
  2. CCS 엔진 (vendor/ivi/system/ccs/dds)
    • Fast-DDS + DDSHal + DDSManager + dds_module.rc (네이티브 데몬)
  3. 안드로이드 서비스 (vendor/ivi/services/ddsservice)
    • dds_svc (Binder 서비스) + AIDL + Java DdsManager

4. “구조파악”만 놓고 보면 핵심 요약

  • services/*service
    • AIDL + Java 라이브러리 + Binder 서비스 프로세스
    • 앱이 직접 붙는 창구
  • system/ccs/{j1939, dds}
    • CCS 내부 엔진 (J1939/DDS 프로토콜 처리)
    • HIDL HAL + 네이티브 데몬 + Fast-DDS 같은 라이브러리
  • *_service.mk, *_module.mk, *.rc
    • *.mk → “이걸 빌드/PRODUCT에 넣어라”
    • *.rc → “부팅할 때 이 이름으로 데몬/서비스를 시작해라”

여기까지가 “디렉토리/파일이 어떤 층에 있는지” 구조 설명이고,
지금 보드에서 DDS가 안 보이는 이유는 이 구조 중에서:

  • DDS쪽 mk / bp / PRODUCT_PACKAGES / rc 가
    CAN / J1939처럼 상위 product에 아직 제대로 연결이 안 돼 있다
    (그래서 소스는 다 있는데, 빌드/이미지/부팅 경로에 안 올라오는 것)

이라는 걸 뒤에 이어서 맞추는 단계야.

일단 이 그림이 조금이라도 잡혔는지만 말해주면,
그 다음엔 “CAN이랑 1:1로 맞춰서 DDS도 어디에 뭐를 추가해야 하는지”를 딱 짚어서 diff 형식으로 정리해줄게.


오케이. joo가 헷갈리던 이유 = 3개의 레이어(계층)가 서로 겹쳐 보이기 때문이야.
이걸 완전 단순한 그림으로 다시 그려줄게.
Android 시스템은 항상 아래처럼 구성되어 있어:


🎯 전체 구조를 그림으로 보면 이렇게야

[1] 앱(App) 레벨

┌────────────────────────────┐
│   Android App (Java/Kotlin)│
│   ex) Cluster UI, Diagnostics│
└────────────────────────────┘
             │
             ▼  (AIDL / Binder IPC)

[2] Android Service 레벨 (vendor/ivi/services/*)**

┌────────────────────────────────────────┐
│   vendor/ivi/services/canservice       │
│   vendor/ivi/services/ddsservice       │
│                                        │
│  - AIDL (ICanService.aidl, IDds.aidl)  │
│  - 서비스 프로세스 (can_svc, dds_svc) │
│  - Java Manager (CanManager, DdsManager)│
└────────────────────────────────────────┘
             │
             ▼  (HAL IPC: HIDL/AIDL)

App ↔ HAL 사이의 브릿지 역할
➡ 앱이 서비스에 붙어서 “can 보내줘”, “dds publish 해줘” 같은 명령을 호출함.


[3] CCS Native Engine 레벨 (vendor/ivi/system/ccs/*)**

┌───────────────────────────────────────────────┐
│       vendor/ivi/system/ccs/j1939             │
│       vendor/ivi/system/ccs/dds               │
│                                               │
│   - HAL 구현체 (DDSHal.cpp, J1939Hal.cpp)     │
│   - Native Engine (DDSManager, J1939Manager)  │
│   - Fast-DDS 라이브러리                       │
│   - 데몬 실행 (dds_module, j1939_service)     │
│   - *.rc: init 시 자동 실행되는 네이티브 데몬 │
└───────────────────────────────────────────────┘
             │
             ▼  (Kernel API / Socket CAN / Fast-DDS Transport)

실제 로직이 돌아가는 엔진(진짜 뇌)
➡ DDS는 여기서 Fast-DDS를 사용해 subscribe/publish 처리함
➡ J1939도 여기서 CAN 프레임 파싱/조립/브로드캐스트 처리


[4] 커널 레벨(Linux Kernel)

┌────────────────────────────────────┐
│              Linux Kernel          │
│                                    │
│    - CAN 드라이버(vcan, mcan 등)   │
│    - 네트워크 소켓 API             │
│    - 시스템 콜 (select, epoll...)  │
└────────────────────────────────────┘

➡ DDS는 커널 모듈이 아님
➡ CAN은 커널 드라이버(vcan0 등)가 필요함


✨ 최종 전체 구조를 한눈에 보면…

┌─────────────────────────────────────────────────────────┐
│                       Android App                        │
│                (Java/Kotlin → DdsManager)                │
└─────────────────────────────────────────────────────────┘
                            │ AIDL
                            ▼
┌─────────────────────────────────────────────────────────┐
│             vendor/ivi/services/ddsservice               │
│       dds_svc (Binder Service, AIDL 인터페이스)         │
└─────────────────────────────────────────────────────────┘
                            │ HIDL/AIDL
                            ▼
┌─────────────────────────────────────────────────────────┐
│         vendor/ivi/system/ccs/dds (Native Engine)       │
│      DDSHal.cpp / DDSManager / Fast-DDS Library         │
│          dds_module.rc → dds_module 데몬 실행           │
└─────────────────────────────────────────────────────────┐
                            │
                            ▼
┌─────────────────────────────────────────────────────────┐
│               Linux Kernel (Socket, Netlink)            │
└─────────────────────────────────────────────────────────┘

CAN은 거의 동일한 구조인데, 엔진이 DDS 대신 J1939 엔진일 뿐이야.


📌 다시 정리해주면:

계층 역할 예시 폴더

App UI/비즈니스 로직 (앱 apk)
Android Service(services) 앱이 붙는 Binder 서비스 vendor/ivi/services/ddsservice
CCS Native Engine(system/ccs) DDS/J1939 실제 처리 로직 vendor/ivi/system/ccs/dds
Kernel CAN 드라이버, 소켓 제공 CONFIG_CAN=y

📷 이해를 돕는 직관적인 버전 (진짜 쉽게)

앱 입장에서 보면:

앱  →  ddsservice  →  DDSEngine  →  Fast-DDS 네트워크
앱  →  canservice  →  J1939Engine → CAN 드라이버(vcan0)

만약 이것도 헷갈린다면?

joo가 지금까지 본 tree는 그냥 위 그림의 디렉토리 버전일 뿐이야.

내가 원하면

  • 더 단순한 버전
  • 실제 실행 파일이 어디 떨어지는지
  • CAN과 DDS가 서로 어떻게 데이터가 움직이는지 "시퀀스 다이어그램"
    까지도 그림으로 만들어줄게.

원하는 방향이 뭐야?

  • 전체 구조를 더 단순하게 다시 그려줄까?
  • 아니면 DDS가 왜 지금 보드에 “전혀 안 올라왔는지” 분석부터 할까?