# Signal frame과 user context 복원

v6.18.37 / arch/arm64/kernel/signal.c

시그널 처리기는 원래 프로그램의 실행을 잠깐 빌려 실행됩니다. 처리기가 끝난 뒤 돌아가려면 중단한 상태를 사용자 스택에 보존해야 합니다. arm64는 확장 context record, x86은 FP/xstate를 포함한 프레임, RISC-V는 해당 ABI의 레지스터와 벡터 상태를 사용합니다. 대표로 arm64 프레임 배치 초기화를 읽습니다.

## init_user_layout

```c

static void init_user_layout(struct rt_sigframe_user_layout *user)
{
	const size_t reserved_size =
		sizeof(user->sigframe->uc.uc_mcontext.__reserved);

	memset(user, 0, sizeof(*user));
	user->size = offsetof(struct rt_sigframe, uc.uc_mcontext.__reserved);

	user->limit = user->size + reserved_size;

	user->limit -= TERMINATOR_SIZE;
	user->limit -= EXTRA_CONTEXT_SIZE;
	/* Reserve space for extension and terminator ^ */
}

```

### 156행

```c

static void init_user_layout(struct rt_sigframe_user_layout *user)

```

시그널 프레임을 배치할 때 사용할 커널 측 계산 구조를 초기화합니다. 매개변수 이름 user가 곧 __user 메모리라는 뜻은 아닙니다.

### 158행

```c

	const size_t reserved_size =

```

고정 시그널 구조 안에 예약된 확장 공간의 크기를 계산할 상수를 선언합니다.

### 159행

```c

		sizeof(user->sigframe->uc.uc_mcontext.__reserved);

```

sizeof는 __reserved 필드의 타입 크기를 구합니다. 이 표현식은 user->sigframe의 주소를 실제로 역참조하여 사용자 데이터를 읽는 동작이 아닙니다.

### 161행

```c

	memset(user, 0, sizeof(*user));

```

레이아웃 관리 구조 자체를 0으로 만듭니다. 아직 사용자 스택 전체에 시그널 프레임을 복사하는 단계는 아닙니다.

### 162행

```c

	user->size = offsetof(struct rt_sigframe, uc.uc_mcontext.__reserved);

```

고정 프레임 시작에서 __reserved까지의 바이트 거리를 구해 현재 사용 크기의 출발점으로 정합니다.

### 164행

```c

	user->limit = user->size + reserved_size;

```

고정 부분 끝에 reserved_size를 더해 확장 기록이 들어갈 초기 한계를 구합니다.

### 166행

```c

	user->limit -= TERMINATOR_SIZE;

```

마지막 종료 표시가 들어갈 자리를 미리 빼 둡니다. 가변 기록을 가득 채워도 끝을 표시할 공간이 남아야 합니다.

### 167행

```c

	user->limit -= EXTRA_CONTEXT_SIZE;

```

추가 확장 영역을 가리킬 extra_context 공간도 미리 확보합니다. 일반 기록의 여유 공간과 관리용 공간을 구분합니다.

