Linux v6.18.37 · 개념과 코드 읽기

참조 하나를 내려놓고 마지막 사용자인지 확인합니다

이 코드는 어떤 문제를 푸나요?

공유 객체를 한 사용자가 다 썼다고 바로 해제하면 다른 사용자가 해제된 메모리에 접근할 수 있습니다. refcount는 남은 사용자를 세며, 0으로 바뀐 실행 흐름이 마지막 참조 해제를 맡도록 돕습니다. 포인터를 안전하게 얻는 방법까지 자동으로 해결해 주는 것은 아닙니다.

읽을 범위: v6.18.37 · include/linux/refcount.h · __refcount_dec_and_test 430–433행입니다. 아래에 이 범위의 원문과 각 줄의 설명을 실었습니다. 주제 전체의 흐름과 다른 경로는 기존 분석에서 함께 읽으실 수 있습니다.

먼저 알아둘 개념

원자적 갱신

다른 CPU의 갱신과 중간 단계가 뒤섞이지 않도록 참조 수를 바꿉니다.

마지막 참조

이전 값이 1이고 하나 감소해 0이 되는 경계가 객체 회수 여부를 결정합니다.

해제 전 메모리 순서

호출되는 공통 구현은 감소에 release 순서를, 정상적으로 마지막 참조가 된 경로에 acquire 순서를 제공합니다. 이는 참조 수 원자성뿐 아니라 기존 사용을 마친 뒤 회수하도록 하는 순서와 관련됩니다.

잘못된 감소와 포화

참조 수가 잘못 감소하면 공통 구현은 경고·포화 처리로 잘못된 객체 해제를 피하려 합니다. true가 아니라고 임의로 다시 감소시키거나 포화값을 정상 사용자 수로 읽으면 안 됩니다.

처음 읽을 때

유효한 참조 두 개가 있을 때 첫 감소는 false, 마지막 감소는 true가 되는 예를 따라가세요. 여기서 본 네 줄은 감소 연산 자체가 아니라 공통 구현을 호출하는 래퍼입니다.

더 깊이 살펴볼 때

__refcount_sub_and_test의 atomic_fetch_sub_release와 성공 분기의 smp_acquire__after_ctrl_dep를 직접 이어 읽으세요. 이 짧은 래퍼만으로 객체 포인터의 획득 안전성이나 모든 참조 경쟁이 설명되지는 않습니다.

그림으로 보는 변화

참조 하나를 내려놓고 마지막 사용자인지 확인합니다의 단계별 개념 그림
각 단계에 화살표 의미와 생략 범위를 표시했습니다. 주소·숫자 예제는 실제 장치 값을 뜻하지 않습니다.
1단계 설명

1단계 고정

GIF 원본 열기

1. 유효한 참조 보유

호출자는 수명이 보장된 객체의 참조를 가지고 있어야 합니다.

화살표는 참조 해제 절차입니다.

2. 참조 하나 감소

공통 감소·검사 함수에 감소량 1을 전달합니다.

그림의 1은 실제 감소량이며 주소 값은 아닙니다.

3. 마지막 여부 반환

0으로 내려갔는지에 따라 호출자가 회수를 판단합니다.

이 함수 자체가 객체 free를 직접 호출하지 않습니다.

__refcount_dec_and_test를 한 줄씩 읽기

줄 번호는 v6.18.37 원문 기준입니다. 주석·빈 줄을 포함한 함수 전체를 먼저 보고, 그 아래에서 각 줄을 설명합니다.

static inline __must_check bool __refcount_dec_and_test(refcount_t *r, int *oldp)
{
	return __refcount_sub_and_test(1, r, oldp);
}
static inline __must_check bool __refcount_dec_and_test(refcount_t *r, int *oldp)

r의 참조를 하나 내려놓고 마지막 참조인지 bool로 반환하는 얇은 래퍼입니다. __must_check는 반환값을 무시한 호출에 컴파일러가 경고하도록 하며 oldp가 NULL이 아니면 공통 구현이 이전 값을 기록합니다.

	return __refcount_sub_and_test(1, r, oldp);

감소량 1, 대상 r와 선택적 이전값 출력 oldp를 공통 구현에 넘깁니다. 정상적으로 1에서 0이 된 경우 true를 돌려주며, 객체를 직접 해제하지는 않습니다. release 순서와 성공 시 acquire 순서는 이 하위 함수가 담당합니다.

함께 생각해 볼 질문

반환값 true면 무슨 뜻인가요?

참조 수가 0이 되는 조건을 공통 함수가 확인했다는 뜻입니다.

포인터만 읽고 refcount를 늘리면 항상 안전한가요?

포인터를 읽은 시점에 이미 해제됐을 수 있으므로 수명 보호 규칙이 먼저 필요합니다.

oldp는 객체 본문인가요?

공통 구현에서 이전 참조 값 기록에 사용할 수 있는 인자입니다.

출처와 읽은 범위

Linux stable v6.18.37 · include/linux/refcount.h

해당 버전 원본 파일 · 기존 코드 분석 · 설명 원고

맨 위로 ↑