실시간 시스템 업데이트는 특히 임베디드 시스템에서 중요한 역할을 한다. 이러한 업데이트 사례를 통해 Yocto 프로젝트 기반의 시스템이 어떻게 효과적으로 유지되고 있으며, 상황에 따라 대응하고 업데이트할 수 있는지 설명하겠다.

예제: Over-the-Air (OTA) 업데이트

OTA 업데이트는 일반적으로 원격에서 시스템 소프트웨어를 업데이트하는 방법이다. 이 사례에서는 Yocto 프로젝트를 사용하여 OTA 시스템을 설정하고 실시간으로 업데이트를 배포하는 과정을 살펴보겠다.

시스템 구성

OTA 업데이트를 지원하기 위해, 다음과 같은 시스템 구성 요소가 필요하다:

서버 설정

업데이트 서버는 클라이언트가 최신 소프트웨어를 다운로드할 수 있도록 준비해야 한다. 이를 위해 기본적으로 웹 서버를 사용하며, 업데이트 파일 및 메타데이터를 저장하는 디렉터리를 설정한다.

mkdir -p /var/www/ota-updates
cp update-file.img /var/www/ota-updates/

Apache 또는 Nginx와 같은 웹 서버를 설정하여 이 디렉터리를 서비스한다.

클라이언트 설정

클라이언트 장치는 업데이트 서버와 연결하고 업데이트 파일을 다운로드 및 설치할 준비가 되어 있어야 한다. 이를 위해 Yocto 레시피를 작성하여 필요한 도구와 스크립트를 포함한다.

Yocto 레시피 추가

DESCRIPTION = "OTA Update client"
LICENSE = "CLOSED"

SRC_URI = "file://updater-script.sh"
S = "${WORKDIR}"

do_install() {
    install -d ${D}${bindir}
    install -m 0755 ${S}/updater-script.sh${D}${bindir}/updater
}

업데이터 스크립트 작성

updater-script.sh는 서버에서 업데이트 파일을 다운로드하고 이를 시스템에 적용하는 역할을 한다.

#!/bin/sh

SERVER_URL="http://yourserver.com/ota-updates"
UPDATE_FILE="update-file.img"

wget ${SERVER_URL}/${UPDATE_FILE} -O /tmp/${UPDATE_FILE}


dd if=/tmp/${UPDATE_FILE} of=/dev/mmcblk0p1

reboot

업데이트 적용

업데이트 과정은 아래와 같다:

  1. 업데이트 확인: 주기적으로 서버에서 새로운 업데이트가 있는지 확인한다.
  2. 파일 다운로드: 새로운 업데이트가 발견되면 클라이언트에서 해당 파일을 다운로드한다.
  3. 업데이트 적용: 다운로드한 파일을 통해 시스템을 업데이트한다.
  4. 시스템 다시 시작: 업데이트가 적용되도록 시스템을 재부팅한다.

주기적 업데이트 확인

crontab -e

크론 작업에 다음 명령을 추가한다:

0 * * * * /usr/bin/updater &>/dev/null

이를 통해 클라이언트 장치는 매 시간마다 업데이트를 확인하고 다운로드 및 적용할 수 있다.

무중단 업데이트 (A/B 시스템)

OTA 업데이트의 형식 중 하나는 A/B 시스템을 활용하는 것이다. 이 시스템은 현재 실행 중인 소프트웨어를 중단하지 않고도 안전하게 업데이트할 수 있다. A/B 시스템에서는 두 개의 파티션이 사용되며, 한 파티션에서 시스템이 실행되면서 다른 파티션에서 업데이트를 수행한다.

시스템 구성

A/B 시스템은 두 개의 루트 파일 시스템 파티션과 하나의 부트로더 파티션을 사용한다. 이를 통해 다음과 같은 방식으로 업데이트를 수행할 수 있다:

부트로더 설정

일반적으로 U-Boot와 같은 부트로더는 A/B 시스템을 지원한다. 첫 번째 단계는 U-Boot를 구성하여 둘 이상의 루트 파일 시스템 파티션을 인식하게 만드는 것이다.

bootcmd_a=load mmc 0:1 $kernel_addr_r Image; load mmc 0:1$fdt_addr_r my-device-tree.dtb; booti $kernel_addr_r -$fdt_addr_r
bootcmd_b=load mmc 0:2 $kernel_addr_r Image; load mmc 0:2$fdt_addr_r my-device-tree.dtb; booti $kernel_addr_r -$fdt_addr_r
bootcmd=${bootcmd_a}

partA=1
partB=2
current_part=1  # Default to partition A

업데이트 절차

업데이트는 다음의 단계로 진행된다:

  1. 업데이트 준비: 업데이트 파일을 "B" 파티션에 다운로드.
  2. 파티션 전환: 부트로더 설정을 변경하여 다음 부팅 시 "B" 파티션을 사용하도록 설정.
  3. 검증 및 복구: 업데이트 후 시스템이 정상적으로 부팅되지 않으면 "A" 파티션으로 복귀.

업데이트 스크립트

#!/bin/sh

UPDATE_URL="http://yourserver.com/ota-updates/new-update.img"
UPDATE_PARTITION="/dev/mmcblk0p2"
ACTIVE_PARTITION=$(fw_printenv current_part | cut -d= -f2)

if [ "$ACTIVE_PARTITION" = "1" ]; then
    INACTIVE_PARTITION="/dev/mmcblk0p2"
    NEW_PART=2
else
    INACTIVE_PARTITION="/dev/mmcblk0p1"
    NEW_PART=1
fi

wget $UPDATE_URL -O /tmp/new-update.img

dd if=/tmp/new-update.img of=$INACTIVE_PARTITION

fw_setenv bootcmd "bootcmd${NEW_PART}"
fw_setenv current_part $NEW_PART

reboot

검증 및 복구

업데이트 후 시스템이 정상적으로 부팅되지 않는 경우, 부트로더에 의해 이전 파티션으로 복귀할 수 있도록 설정하는 것이 중요하다. 이를 위해 watchdog 타이머나 보안 부팅 절차를 활용할 수 있다.

bootcmd=run bootcmd_a || run bootcmd_b || reset

정상적으로 부팅되었을 때만 성공적으로 업데이트를 완료했다고 리포트할 수 있도록 한다.

#!/bin/sh

# After a successful boot, ensure the watchdog is reset
touch /var/run/update-success

# Add heartbeat function to ensure the watchdog doesn't reset
while true; do
    sleep 60
    touch /var/run/update-success
done

부팅 후 시스템이 정상적으로 작동하면 완료 성공을 기록하고 다음 업데이트를 위해 시스템을 모니터링한다.