Tích hợp ứng dụng người dùng vào Yocto Project
Tạo recipe mới để build ứng dụng C++ từ source code, đóng gói thành .deb/.ipk tùy môi trường, và thêm vào image rootfs.
Ứng dụng ví dụ: Một service C++ tên "pi-cm5-monitor" giám sát CPU/RAM, chạy dưới user "appuser" và giao tiếp qua Unix Socket.
Đường dẫn recipe: layers/meta-custom/recipes-support/pi-cm5-monitor/pi-cm5-monitor_1.0.bb
Nội dung file recipe hoàn chỉnh:
DESCRIPTION = "Custom C++ monitoring service for Raspberry Pi CM5"
SUMMARY = "High-performance system monitor with socket interface"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
SRC_URI = "git://github.com/your-org/pi-cm5-monitor.git;branch=main;protocol=https"
S = "${WORKDIR}/git"
inherit cmake pkgconfig useradd
# Tạo user và group cho ứng dụng
USERADD_PACKAGES = "${PN}"
USERADD_USER = "appuser"
USERADD_GROUP = "appgroup"
# Tùy chọn build
CMAKE_ARGS += "-DCMAKE_INSTALL_PREFIX=/usr"
CMAKE_ARGS += "-DENABLE_SOCKET=ON"
# Dependencies
RDEPENDS:${PN} = "libstdc++"
RRECOMMENDS:${PN} = "dbus-1"
# Package specific files
PACKAGES =+ "${PN}-daemon"
PACKAGES_SPLIT = "daemon"
FILES:${PN}-daemon = "/usr/bin/pi-cm5-monitor \
/usr/lib/pi-cm5-monitor/ \
/etc/pi-cm5-monitor/"
# Install init script (systemd)
SYSTEMD_SERVICE:${PN}-daemon = "pi-cm5-monitor.service"
SYSTEMD_PACKAGES = "${PN}-daemon"
do_install() {
install -d ${D}${systemd_unitdir}/system
install -m 0644 ${S}/pi-cm5-monitor.service ${D}${systemd_unitdir}/system/
}
Kết quả mong đợi: Recipe được Yocto nhận diện, build thành package .rpm/.ipk chứa binary, thư viện, và file service systemd.
Cấu hình quyền truy cập và Socket File
Định nghĩa quyền sở hữu socket file để ứng dụng chạy an toàn dưới user "appuser" thay vì root, tránh rủi ro bảo mật.
Socket file sẽ nằm tại /var/run/pi-cm5-monitor.sock, do user "appuser" tạo và chỉ user "appuser" hoặc nhóm "appgroup" có quyền đọc/ghi.
Chỉnh sửa file systemd service (nằm trong recipe hoặc file riêng layers/meta-custom/recipes-support/pi-cm5-monitor/pi-cm5-monitor.service):
[Unit]
Description=Pi CM5 Monitor Daemon
After=network.target
[Service]
Type=simple
User=appuser
Group=appgroup
ExecStart=/usr/bin/pi-cm5-monitor --socket /var/run/pi-cm5-monitor.sock
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
# Bảo vệ socket và runtime directory
RuntimeDirectory=pi-cm5-monitor
RuntimeDirectoryMode=0755
# Giới hạn tài nguyên (sẽ tối ưu hóa ở phần sau)
LimitNOFILE=65536
LimitNPROC=1024
[Install]
WantedBy=multi-user.target
Kết quả mong đợi: Khi service khởi động, systemd tự động tạo thư mục /var/run/pi-cm5-monitor/ với quyền đúng, socket file được tạo với owner "appuser:appgroup".
Tối ưu hóa hiệu năng cho Raspberry Pi CM5
Tối ưu hóa bộ nhớ RAM và CPU cho ứng dụng chạy trên CM5 (ARM Cortex-A76), giảm latency và tăng throughput.
CM5 có 4GB RAM, CPU 4-core 2.4GHz. Cần cấu hình scheduler và memory pressure để ưu tiên ứng dụng quan trọng.
Sử dụng cgroups v2 để giới hạn và ưu tiên tài nguyên cho service "pi-cm5-monitor".
Tạo file drop-in cho systemd: layers/meta-custom/recipes-support/pi-cm5-monitor/pi-cm5-monitor.service.d/override.conf
Nội dung file override.conf:
[Service]
# Giới hạn RAM tối đa 256MB để tránh OOM killer
MemoryMax=256M
MemorySwapMax=0
# Ưu tiên CPU cho service này
CPUQuota=50%
# Sử dụng scheduler FIFO cho các task quan trọng
# (Yêu cầu kernel hỗ trợ real-time)
# CPUAffinity=0-3
# Giới hạn số file descriptor mở đồng thời
LimitNOFILE=8192
# Giới hạn số process con
LimitNPROC=512
# Đặt priority nice value
Nice=10
Kết quả mong đợi: Ứng dụng không tiêu thụ quá 256MB RAM, không gây treo hệ thống, và được ưu tiên CPU khi hệ thống tải cao.
Tối ưu hóa Kernel và Runtime cho CM5
Cấu hình kernel parameter để giảm latency I/O và cải thiện throughput mạng cho ứng dụng socket.
Thêm vào file layers/meta-custom/recipes-core/images/custom-image.bbappend hoặc file config riêng trong image recipe.
Nội dung file /etc/sysctl.d/99-cm5-optimization.conf (sẽ được install vào rootfs):
# Network optimization for low latency
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.ipv4.tcp_rmem = 4096 87380 134217728
net.ipv4.tcp_wmem = 4096 65536 134217728
net.ipv4.tcp_congestion_control = bbr
# Memory optimization
vm.swappiness = 10
vm.vfs_cache_pressure = 50
# CPU scheduler tuning
kernel.sched_min_granularity_ns = 3000000
kernel.sched_latency_ns = 12000000
Kết quả mong đợi: Ứng dụng socket có độ trễ thấp hơn, bộ nhớ RAM được quản lý hiệu quả hơn, giảm thiểu swap.
Kiểm tra khả năng mở rộng và cập nhật runtime
Thiết lập cơ chế cập nhật ứng dụng không cần reboot toàn bộ hệ thống, sử dụng package manager (opkg/rpm) hoặc custom script.
Trên Yocto image, thường sử dụng opkg (cho embedded) hoặc dnf/rpm. Ở đây dùng opkg cho CM5.
Tạo recipe để build và install package update tool: layers/meta-custom/recipes-support/pi-cm5-update/pi-cm5-update.bb
Nội dung file recipe update tool:
DESCRIPTION = "Custom update tool for pi-cm5-monitor"
SUMMARY = "Non-reboot update mechanism for user applications"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
SRC_URI = "file:update-monitor.sh"
inherit update-rc.d
do_install() {
install -d ${D}${sbindir}
install -m 0755 ${WORKDIR}/update-monitor.sh ${D}${sbindir}/update-monitor
}
FILES:${PN} = "${sbindir}/update-monitor"
Nội dung script layers/meta-custom/recipes-support/pi-cm5-update/update-monitor.sh:
#!/bin/bash
# Script để cập nhật ứng dụng pi-cm5-monitor không cần reboot
APP_NAME="pi-cm5-monitor"
PACKAGE_NAME="pi-cm5-monitor"
echo "Starting update process for $APP_NAME..."
# 1. Stop service
systemctl stop $APP_NAME
sleep 2
# 2. Update package via opkg
opkg upgrade $PACKAGE_NAME
if [ $? -ne 0 ]; then
echo "Error: Package update failed. Rolling back..."
systemctl start $APP_NAME
exit 1
fi
# 3. Restart service
systemctl daemon-reload
systemctl start $APP_NAME
# 4. Verify status
if systemctl is-active --quiet $APP_NAME; then
echo "Update successful. Service is running."
systemctl status $APP_NAME
else
echo "Error: Service failed to start after update."
exit 1
fi
Kết quả mong đợi: Chạy update-monitor sẽ stop service, update package, restart service và verify trạng thái mà không cần reboot CM5.
Verify kết quả tổng thể
Thực hiện các lệnh sau trên CM5 sau khi flash image mới:
- Kiểm tra service đang chạy:
systemctl status pi-cm5-monitor
- Kiểm tra socket file:
ls -l /var/run/pi-cm5-monitor.sock (Owner phải là appuser:appgroup)
- Kiểm tra giới hạn tài nguyên:
systemctl show pi-cm5-monitor | grep -E "MemoryMax|CPUQuota"
- Test socket:
echo "test" | nc -U /var/run/pi-cm5-monitor.sock
- Test update:
update-monitor
Kết quả mong đợi: Tất cả lệnh chạy thành công, service hoạt động ổn định, socket có quyền đúng, update không cần reboot.
Điều hướng series:
Mục lục: Series: Xây dựng hệ điều hành Linux tùy biến từ source cho Raspberry Pi CM5
« Phần 5: Xây dựng Rootfs với Package Manager và dịch vụ hệ thống
Phần 7: Kiểm thử hệ thống, xử lý lỗi và các mẹo nâng cao »