설명 DEFINE_PER_CPU(struct runqueue, runqueues);거대하다
/* will be freed after init */
. = ALIGN(4096); /* Init code and data */
__init_begin = .;
/* :) */
. = ALIGN(32);
__per_cpu_start = .;
.data.percpu : { *(.data.percpu) }
__per_cpu_end = .;
. = ALIGN(4096);
__init_end = .;
/* freed after init ends here */
이 설명은 __per_cpu_start 및__per_cpu_end 표식.data.percpu 이 섹션의 시작과 끝
그리고 전체.data.percpu 이 섹션은 모두 __init_begin 및 __init_end 사이,
즉, 이 섹션이 차지하는 메모리는 시스템이 시작된 후에 방출(free)된다는 것이다
있다
#define DEFINE_PER_CPU(type, name)\
__attribute__((__section__(".data.percpu"))) __typeof__(type) per_cpu__##name
그래서
static DEFINE_PER_CPU(struct runqueue, runqueues);
확장됩니다.
__attribute__((__section__(".data.percpu"))) __typeof__(struct runqueue) per_cpu__runqueues;
바로data.percpu 이 섹션에서 변수per_를 정의했습니다.cpu__runqueues,
그 유형은structrunqueue입니다.사실 여기 이른바 변수per_cpu__runqueues,
사실은 이 변수의 주소를 표시하는 편이량이다.
--------------------
그 다음, 시스템이 시작되면 start_kernel () 에서 다음 함수를 호출합니다.
unsigned long __per_cpu_offset[NR_CPUS];
static void __init setup_per_cpu_areas(void)
{
unsigned long size, i;
char *ptr;
/* Created by linker magic */
extern char __per_cpu_start[], __per_cpu_end[];
/* Copy section for each CPU (we discard the original) */
size = ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES);
#ifdef CONFIG_MODULES
if (size < PERCPU_ENOUGH_ROOM)
size = PERCPU_ENOUGH_ROOM;
#endif
ptr = alloc_bootmem(size * NR_CPUS);
for (i = 0; i < NR_CPUS; i++, ptr += size) {
__per_cpu_offset[i] = ptr - __per_cpu_start;
memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
}
}
이 함수에서 각 CPU에 전용 데이터 영역을 할당하고data.percpu의 데이터를 복사합니다.
CPU마다 하나씩 있습니다.데이터로부터__per_cpu_start에서 각 CPU 자체의 전용 데이터 영역으로 옮겼습니다.
따라서 그 변수를 액세스하면 원래의 값을 사용할 수 없습니다. 예를 들어 액세스per_cpu__runqueues
per_를 더 이상 사용할 수 없습니다.cpu__runqueues입니다. 편이량 조정이 필요합니다.
각 CPU에 고유한 전용 데이터 영역의 첫 번째 주소를 추가해야 함__per_cpu_start 오프셋
여기서 바로 __per_cpu_offset[i], CPU i의 전용 데이터 영역은
__per_cpu_start 오프셋은 __per_cpu_offset[i].
이렇게 하면 전유 데이터 구역의 각 변수의 새로운 주소를 편리하게 계산할 수 있다. 예를 들어per_cpu_runqueues,
새 주소가per_cpu_runqueues+__per_cpu_offset[i].
이런 처리를 거쳐서..data.percpu 이 섹션은 시스템을 초기화한 후에 방출할 수 있습니다.
--------------------
퍼cpu의 변수를 어떻게 저장하는지 다시 봅시다
/* This macro obfuscates arithmetic on a variable address so that gcc
shouldn't recognize the original var, and make assumptions about it */
#define RELOC_HIDE(ptr, off) \
({ unsigned long __ptr; \
__asm__ ("" : "=g"(__ptr) : "0"(ptr)); \
(typeof(ptr)) (__ptr + (off)); })
/* var is in discarded region: offset to particular copy we want */
#define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu]))
#define __get_cpu_var(var) per_cpu(var, smp_processor_id())
#define get_cpu_var(var) (*({ preempt_disable(); &__get_cpu_var(var); }))
__get_cpu_var (runqueues), 등효적으로 확장
__per_cpu_offset[smp_processor_id()] + per_cpu__runqueues
그리고 lvalue입니다. 즉, 값을 부여할 수 있다는 것입니다.
이게 바로 상술per_cpu__runqueues 변수는 CPU의 전용 데이터 영역에 있는 새 주소입니다.
서로 다른per cpu 변수는 서로 다른 편이량을 가지고 서로 다른 CPU는 전용 데이터 구역의 첫 번째 주소가 다르기 때문에
따라서 __를 통해get_cpu_var () 는 다른 변수에 액세스합니다.
--END
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Ruby의 구조체 클래스은 접근자 메서드가 있는 속성 모음입니다. 클래스를 명시적으로 작성할 필요 없이. Struct 클래스는 구성원 및 해당 값 집합을 포함하는 새 하위 클래스를 생성합니다. 각 멤버에 대해 #attr_accessor 와...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.