임베디드 스터디 - OS 전원관리
임베디드 스터디 - OS 전원관리
OS 전원관리 개요
- 전원관리는 크게 두 가지 레벨로 나뉨
- 시스템 전체 절전 : 시스템 전체를 Sleep 상태로 전환
- 개별 디바이스 절전 : 사용하지 않는 디바이스만 선택적으로 절전
- Linux는 이 두 가지를 PM Core(
kernel/power/)를 통해 통합 관리함
전원 관리 기술 발전
전원 관리 기술은 제어 주체와 제어 범위에 따라 APM → ACPI → DVFS 순으로 발전했다.
1
2
APM → ACPI → DVFS
(BIOS 제어) (OS 제어) (동작 중 전압·주파수 동적 조절)
APM과 apmd
- APM(Advanced Power Management): BIOS가 전원을 제어하는 구형 전원 관리 표준
- 장치가 동작 중일 때 소비전력을 줄이지 못하는 한계 존재
- apmd: 리눅스에서 APM 이벤트를 처리하는 전원 관리 데몬
1
2
3
4
5
6
7
8
9
10
하드웨어 BIOS/APM 이벤트
↓
APM 커널 드라이버 (/dev/apm_bios)
↓
apmd (유저스페이스 데몬)
↓
이벤트에 따라 처리:
- 배터리 부족 → 경고 발생 / 임계값 이하 시 강제 Suspend
- 덮개 닫힘 → Suspend/Sleep 진입
- AC 연결 → 충전 상태 업데이트
ACPI
- ACPI(Advanced Configuration and Power Interface): OS가 직접 전원 관리를 제어하는 현재 표준
- APM의 한계(BIOS 제어)를 극복하여 OS가 각 장치의 전원 상태(D0~D3)를 직접 제어
| APM | ACPI | |
|---|---|---|
| 제어 주체 | BIOS (하드웨어) | OS (소프트웨어) |
| 장치별 제어 | ❌ 불가 | ✅ 가능 |
| 동작 중 전력 감소 | ❌ | ❌ (DVFS로 보완) |
| 현재 사용 | 구형 시스템 | 현재 표준 |
DVFS (Dynamic Voltage Frequency Scaling)
- ACPI의 한계(장치 동작 중 소비전력 미감소)를 극복하기 위해 등장
- CPU 부하에 따라 동작 전압과 클럭 주파수를 동적으로 조절하여 소비전력을 최소화
- 전력이 $V^2$에 비례 → 전압을 조금만 낮춰도 전력이 크게 감소
- 전압을 낮추면 트랜지스터 스위칭 속도도 느려지므로 전압·주파수를 항상 쌍으로 조절
| 부하 상태 | 전압·주파수 | 소비전력 | 처리 명령어 수 |
|---|---|---|---|
| 고부하 | ↑ 높임 | 증가 | 증가 |
| 저부하 | ↓낮춤 | 감소 | 감소 |
[시험 함정] 저전압·저주파수 인가 시 처리 명령어 수는 감소 — “증가”로 출제되는 선택지 주의
[시험 포인트] 동작 주파수와 전력소모는 비선형 관계 ($V^2$에 비례)
시스템 Sleep 상태
/sys/power/state파일에 값을 써서 Sleep 상태를 제어함 ```bash현재 지원되는 상태 확인
cat /sys/power/state freeze standby mem disk
Suspend-to-RAM 진입
echo mem > /sys/power/state
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
* Linux가 지원하는 Sleep 상태는 다음과 같음
* 단, 시스템에 따라 지원되는 상태는 또 다름
| 상태 | 키워드 | 설명 |
|------|--------|------|
| S0 | `freeze` | CPU 정지, 장치 유지 |
| S1 | `standby` | 일부 하드웨어 정지 |
| S3 | `mem` | Suspend-to-RAM |
| S4 | `disk` | Suspend-to-Disk |
| 시스템 | 지원 상태 |
|--------|-----------|
| 라즈베리파이 (ARM) | `freeze mem` |
| x86 데스크톱 | `freeze mem disk` |
| x86 노트북 (ACPI 완전 지원) | `freeze standby mem disk` |
| 저전력 MCU 기반 | 커널 없이 레지스터 직접 제어 |
### Suspend-to-RAM (S3)
* 시스템 상태를 RAM에 저장하고 절전 상태로 진입
* RAM 전원은 유지해야 하므로 전원 완전 차단 불가
* 복구 속도가 빠름 (수 초)
* 소량의 전력 소비 (RAM refresh 유지)
* 별칭 : Sleep
### Suspend-to-Disk (S4)
* 시스템 상태를 디스크(swap 영역)에 저장하고 절전 상태로 진입
* 전원 완전 차단 가능
* 복구 속도가 느림 (수십 초)
* 소비 전력 0
* 별칭 : Hibernate (hibernation)
| | Suspend-to-RAM (S3) | Suspend-to-Disk (S4) |
|--|---------------------|----------------------|
| 상태 저장 위치 | RAM | 디스크 (swap 영역) |
| 복구 속도 | 빠름 (수 초) | 느림 (수십 초) |
| 전원 완전 차단 | ❌ RAM 유지 필요 | ✅ 가능 |
| 소비 전력 | 소량 (RAM refresh) | 0 |
| 별칭 | Sleep | Hibernate |
## Runtime PM
* 시스템이 깨어 있는 상태에서 사용하지 않는 개별 디바이스만 절전하는 메커니즘
* Linux 드라이버는 `dev_pm_ops` 구조체의 콜백으로 Runtime PM을 구현함
```c
struct dev_pm_ops {
int (*runtime_suspend)(struct device *dev); // 장치 끄기
int (*runtime_resume)(struct device *dev); // 장치 켜기
int (*runtime_idle)(struct device *dev); // 유휴 판단
};
Usage Count 기반 동작
- Linux PM Core는 usage count로 디바이스 사용 여부를 추적함
1 2 3
pm_runtime_get(dev); // 사용 시작 → count++ pm_runtime_put(dev); // 사용 끝 → count-- // count == 0 이 되는 순간 runtime_idle 호출
- Runtime PM 동작 흐름
1 2 3 4 5 6 7 8 9
usage count == 0 ↓ runtime_idle 호출 → suspend 가능 여부 최종 확인 ↓ (DMA 진행 중, 타임아웃 대기 등 추가 조건 검사) runtime_suspend 호출 → 클럭 차단, 레지스터 저장, 전원 OFF ↓ (디바이스 접근 요청 발생) ↓ runtime_resume 호출 → 전원 ON, 레지스터 복구, 클럭 재개 runtime_idle이 별도로 존재하는 이유 : count가 0이 되더라도 드라이버가 추가 조건을 확인하고 suspend를 거부할 수 있는 훅을 제공하기 위함
Linux PM 프레임워크 구조
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
사용자 공간
echo mem > /sys/power/state ← 시스템 Sleep 요청
↓
PM Core (kernel/power/)
↓
┌──────────────────────────┐
│ System Sleep │ ← S3/S4 등
│ - suspend-to-RAM │
│ - suspend-to-disk │
└──────────────────────────┘
┌──────────────────────────┐
│ Runtime PM │ ← 개별 디바이스
│ - runtime_idle │
│ - runtime_suspend │
│ - runtime_resume │
└──────────────────────────┘
↓
디바이스 드라이버 (dev_pm_ops 콜백)
↓
하드웨어 (PMIC, 클럭, 레지스터)
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.