8.6 Nonlocal Jumps (비지역 점프)
C 언어에서 제공하는 비지역 점프(nonlocal jump)라는 고급 제어 흐름 기능을 설명한다.
이는 함수 호출과 반환의 일반적인 흐름을 무시하고, 한 함수에서 다른 함수의 실행 지점으로 직접 점프하는 기능이다.
핵심 함수: setjmp와 longjmp
#include <setjmp.h>
int setjmp(jmp_buf env);
void longjmp(jmp_buf env, int val);
- setjmp는 현재 호출 환경(PC, SP, 레지스터 등)을 저장하고 0을 반환
- longjmp는 setjmp로 저장된 위치로 되돌아감. 이때 setjmp는 val 값을 반환하게 됨
- 즉, setjmp는 한 번 호출되지만 여러 번 반환될 수 있음
주요 활용: 에러 복구
- 함수 호출이 깊이 중첩된 상황에서, 특정 지점으로 빠르게 돌아가고 싶은 경우 유용
- 예제:
jmp_buf buf;
void foo() {
if (error)
longjmp(buf, 1);
}
int main() {
if (setjmp(buf) == 0) {
foo();
} else {
printf("Error handled\n");
}
}
→ foo에서 에러 감지 시, main의 setjmp로 복귀하여 중앙에서 처리
주의사항
- 중간 함수들에서 동적 할당 메모리를 해제하는 코드가 있다면 그 코드를 건너뛰게 되어 메모리 누수 발생 가능
- 이로 인해 자원 관리에 부주의하면 부작용 발생
시그널 핸들러와의 연동: sigsetjmp와 siglongjmp
#include <setjmp.h>
int sigsetjmp(sigjmp_buf env, int savesigs);
void siglongjmp(sigjmp_buf env, int val);
- sigsetjmp는 시그널 마스크 상태까지 저장할 수 있는 버전
- 시그널 핸들러에서 안전하게 제어 흐름을 이동시키는 데 사용됨
예제: Ctrl+C 눌렀을 때 재시작
sigjmp_buf buf;
void handler(int sig) {
siglongjmp(buf, 1);
}
int main() {
if (!sigsetjmp(buf, 1)) {
signal(SIGINT, handler);
printf("starting\n");
} else {
printf("restarting\n");
}
while (1) {
sleep(1);
printf("processing...\n");
}
}
→ 사용자 Ctrl+C 입력 시 SIGINT 발생 → 핸들러에서 siglongjmp 호출로 메인으로 점프 → “restarting” 출력 후 루프 재시작.
요약
함수 | 용도 |
setjmp, longjmp | 일반 함수 간 비지역 점프 |
sigsetjmp, siglongjmp | 시그널 처리 포함한 비지역 점프 |
장점 | 에러 복구, 신속한 흐름 제어 |
단점 | 메모리 누수, 제어 흐름 복잡성 증가 |
8.7 Tools for Manipulating Processes (프로세스를 조작하기 위한 도구들)
리눅스 시스템에서 프로세스를 모니터링하고 제어하는 데 유용한 명령어 도구들을 소개한다. 이 도구들은 프로세스의 상태, 메모리 사용량, 시스템 콜 활동 등을 분석하는 데 매우 유용하다.
주요 도구 목록
strace
- 실행 중인 프로그램 및 그 자식 프로세스들이 수행하는 모든 시스템 콜을 추적
- 시스템 콜의 입력과 반환값까지 상세히 출력
- 예: 파일 열기, 읽기, 쓰기, 포크, 종료 등 모든 시스템 호출
- 정적 링크(static linking)로 컴파일하면, 불필요한 공유 라이브러리 관련 출력 없이 깔끔한 추적 가능
ps
- 현재 시스템에서 실행 중인 프로세스 목록을 출력
- 좀비 프로세스를 포함해 상태, PID, CPU 사용량, 메모리 사용량 등 다양한 정보 확인 가능
top
- 실시간으로 시스템의 리소스 사용 현황을 보여줌
- CPU, 메모리, 각 프로세스의 리소스 점유율 등 모니터링 가능
pmap
- 특정 프로세스의 메모리 맵을 출력
- 각 영역의 주소, 크기, 속성, 맵핑된 파일 경로 등을 확인할 수 있음\
/proc 파일 시스템
- 가상 파일 시스템으로, 커널 데이터 구조를 텍스트 형태로 노출
- /proc/<pid>/ 디렉터리를 통해 개별 프로세스의 상태, 명령행, 파일 디스크립터 등 접근 가능
- 예: cat /proc/loadavg → 현재 시스템의 평균 부하(load average) 확인 가능
요약
도구 | 기능 요약 |
strace | 시스템 콜 추적 |
ps | 현재 프로세스 목록 |
top | 실시간 리소스 모니터링 |
pmap | 메모리 맵 조회 |
/proc | 프로세스 및 시스템 정보 접근 가상 파일 시스템 |
이러한 도구들은 시스템 프로그래머가 디버깅, 성능 분석, 자원 추적에 있어 강력한 무기를 제공하며, 프로세스의 내부 동작을 눈으로 확인할 수 있는 수단을 마련해 준다.
8.8 Summary (요약)
Chapter 8에서는 컴퓨터 시스템 전반에 걸쳐 발생하는 예외적 제어 흐름(ECF, Exceptional Control Flow)에 대해 다루었다. 이 개념은 단순히 프로그램 흐름을 제어하는 것을 넘어서, 동시성(concurrency)을 실현하고 시스템 수준의 상호작용을 가능하게 하는 기반 메커니즘이다.
하드웨어 수준의 ECF
- 예외(exception)는 프로세서에서 발생하는 제어 흐름의 갑작스러운 변화다.
- 유형:
- 인터럽트(interrupt): 외부 장치가 CPU에 이벤트 발생을 알릴 때 (비동기)
- 폴트(fault): 복구 가능한 오류 (예: 페이지 폴트)
- 어보트(abort): 복구 불가능한 오류
- 트랩(trap): 시스템 콜 같은 의도적 예외 (동기)
운영체제 수준의 ECF
- 운영체제는 ECF를 이용해 프로세스라는 추상 개념을 제공한다.
- 각 프로세스는:
- 논리적 제어 흐름(logical control flow)을 가지고, CPU를 독점하는 것처럼 행동
- 개인 주소 공간(private address space)을 가지며, 메모리 고립 보장
사용자 수준의 ECF
- 프로그램은 시스템 콜을 통해 프로세스를 생성, 기다림(wait), 종료, 다른 프로그램 실행, 시그널 처리 등을 수행한다.
- 시그널 핸들링은 시스템마다 동작이 다를 수 있으므로 주의 깊은 구현이 필요
애플리케이션 수준의 ECF
- C 언어의 setjmp, longjmp 함수는 함수 호출의 일반적인 규칙을 무시하고, 다른 함수로 직접 점프할 수 있게 해 줌
- 예외 처리, 오류 복구 등에 사용 가능
핵심 개념 요약
계층 | 주요 ECF 메커니즘 |
하드웨어 | 인터럽트, 폴트, 어보트, 트랩 |
OS | 프로세스 생성/전환, 시스템 콜 |
애플리케이션 | 시그널, 비지역 점프 |
'크래프톤 정글 (컴퓨터 시스템: CSAPP) > 8장 예외적 제어 흐름' 카테고리의 다른 글
컴퓨터 시스템 : CSAPP 8장 정리 - 8.5 Signals Part.2 8.5.7 까지 (1) | 2025.04.19 |
---|---|
컴퓨터 시스템 : CSAPP 8장 정리 - 8.5 Signals Part.1 8.5.4 까지 (0) | 2025.04.19 |
컴퓨터 시스템 : CSAPP 8장 정리 - 8.4 Process Control (0) | 2025.04.19 |
컴퓨터 시스템 : CSAPP 8장 정리 - 8.3 System Call Error Handling (1) | 2025.04.19 |
컴퓨터 시스템 : CSAPP 8장 정리 - 8.2 Processes (0) | 2025.04.19 |