이전 기사에서 계속: QEMU 소스 코드의 전체 분석 32 —— Machine (2)
이 문서의 내용에 대한 참조:
" Linux 운영 체제 에 대한 흥미로운 이야기 " —— Liu Chao, Geek Time
" QEMU /KVM" 소스 코드 분석 및 적용 - Li Qiang, Machinery Industry Press
매우 감사합니다!
이전 두 기사에서는 Intel 440FX 마더보드의 아키텍처와 마더보드를 시뮬레이트하는 QEMU를 소개했습니다. 이 장의 시작 부분에서 QEMU의 마더보드 시뮬레이션 및 초기화를 설명하기 위해 여러 기사를 사용할 것입니다.
가상 머신 초기화
QEMU 마더보드 시뮬레이션의 해당 유형은 MachineClass이며 정렬 파일에는 주로 hw/core/machine.c, hw/i386/pc_piix.c가 포함됩니다. 여기서 머신은 가상 머신 시뮬레이션에서 마더보드의 상태를 보여줍니다. 이 기사에서는 i440FX+piix3 마더보드를 예로 들어 설명합니다.
기계 유형의 정의는 hw/i386/pc_piix.c에 정의된 DEFINE_I440FX_MACHINE 매크로를 통해 수행되며 코드는 다음과 같습니다.
#define DEFINE_I440FX_MACHINE(suffix, name, compatfn, optionfn) \
static void pc_init_##suffix(MachineState *machine) \
{ \
void (*compat)(MachineState *m) = (compatfn); \
if (compat) { \
compat(machine); \
} \
pc_init1(machine, TYPE_I440FX_PCI_HOST_BRIDGE, \
TYPE_I440FX_PCI_DEVICE); \
} \
DEFINE_PC_MACHINE(suffix, name, pc_init_##suffix, optionfn)
DEFINE_I440FX_MACHINE의 정의는 함수와 다른 매크로 DEFINE_PC_MACHINE을 포함하여 비교적 간단합니다. DEFINE_PC_MACHINE은 include/hw/i386/pc.h에 정의되어 있으며 코드는 다음과 같습니다.
#define DEFINE_PC_MACHINE(suffix, namestr, initfn, optsfn) \
static void pc_machine_##suffix##_class_init(ObjectClass *oc, void *data) \
{ \
MachineClass *mc = MACHINE_CLASS(oc); \
optsfn(mc); \
mc->init = initfn; \
} \
static const TypeInfo pc_machine_type_##suffix = { \
.name = namestr TYPE_MACHINE_SUFFIX, \
.parent = TYPE_PC_MACHINE, \
.class_init = pc_machine_##suffix##_class_init, \
}; \
static void pc_machine_init_##suffix(void) \
{ \
type_register(&pc_machine_type_##suffix); \
} \
type_init(pc_machine_init_##suffix)
DEFINE_PC_MACHINE 매크로에는 pc_machine_##suffix##class_init 함수가 정의되어 있는데 함수 이름에서 알 수 있듯이 이는 machine_class를 종이 위의 클래스에서 Class 객체로 초기화하는 방식이다. 이 함수에서는 Class 객체인 MachineClass 객체가 생성됩니다. MachineClass 객체의 init 함수는 위에서 정의한 pc_init##suffix를 가리키며, 이 함수는 기계의 종류에 따라 초기화되는 함수이며 나중에 호출될 것임을 나타냅니다.
그런 다음 DEFINE_PC_MACHINE은 종이에 클래스를 생성하기 위한 원시 자료인 pc_machine_type_##suffix의 TypeInfo를 정의하고 type_init 함수는 나중에 호출됩니다.
각각의 새 릴리스는 새 머신 유형을 정의합니다. 다음은 hw/i386/pc_piix.c에 있는 몇 가지 예입니다.
DEFINE_I440FX_MACHINE(v7_1, "pc-i440fx-7.1", NULL,
pc_i440fx_7_1_machine_options);
DEFINE_I440FX_MACHINE(v7_0, "pc-i440fx-7.0", NULL,
pc_i440fx_7_0_machine_options);
DEFINE_I440FX_MACHINE(v6_2, "pc-i440fx-6.2", NULL,
pc_i440fx_6_2_machine_options);
......
DEFINE_I440FX_MACHINE(v1_5, "pc-i440fx-1.5", pc_compat_1_5_fn,
pc_i440fx_1_5_machine_options);
DEFINE_I440FX_MACHINE(v1_4, "pc-i440fx-1.4", pc_compat_1_4_fn,
pc_i440fx_1_4_machine_options);
예시를 위해 최신 버전 7.1을 예로 들어 보겠습니다.
DEFINE_I440FX_MACHINE(v7_1, "pc-i440fx-7.1", NULL,
pc_i440fx_7_1_machine_options);
먼저 예비 확장을 수행하여 다음을 얻습니다.
static void pc_init_v7_1(MachineState *machine)
{
void (*compat)(MachineState *m) = (NULL);
if (compat) {
compat(machine);
}
pc_init1(machine, TYPE_I440FX_PCI_HOST_BRIDGE, \
TYPE_I440FX_PCI_DEVICE);
}
DEFINE_PC_MACHINE(v7_1, "pc-i440fx-7.1", pc_init_v7_1, pc_i440fx_7_1_machine_options)
그런 다음 DEFINE_PC_MACHINE을 확장하여 다음을 얻습니다.
static void pc_init_v7_1(MachineState *machine)
{
void (*compat)(MachineState *m) = (NULL);
if (compat) {
compat(machine);
}
pc_init1(machine, TYPE_I440FX_PCI_HOST_BRIDGE, \
TYPE_I440FX_PCI_DEVICE);
}
static void pc_machine__class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
pc_i440fx_7_1_machine_options(mc);
mc->init = pc_init_v7_1;
}
static const TypeInfo pc_machine_type_v7_1 = {
.name = "pc-i440fx-7.1" TYPE_MACHINE_SUFFIX,
.parent = TYPE_PC_MACHINE,
.class_init = pc_machine_v7_1_class_init,
};
static void pc_machine_init_v7_1(void)
{
type_register(&pc_machine_type_v7_1);
}
type_init(pc_machine_init_v7_1)
DEFINE_I440FX_MACHINE 매크로는 새로운 유형을 정의하는 모든 작업을 직접 완료하는 것을 볼 수 있습니다. 버전 7.1에서는 새로운 TypeInfo "pc-i440fx-7.1-machine"을 정의합니다.
이것을 보고 일부 독자들은 "pc-i440fx-7.1-머신"이 어떻게 생겼는지 의문을 가질 수도 있습니다. 또한 TypeInfo의 개체는 분명히 pc_machine_type_v7_1인데 어떻게 말해야 할까요? 사실 이해하기 어렵지 않으니 TYPE_MACHINE_SUFFIX 매크로로 대체하면 이해가 될 것이다. TYPE_MACHINE_SUFFIX의 정의는 다음과 같이 include/hw/boards.h에 있습니다.
#define TYPE_MACHINE_SUFFIX "-machine"
이를 TypeInfo pc_machine_type_v7_1의 이름인 "pc-i440fx-7.1-machine"으로 대체하므로 DEFINE_I440FX_MACHINE(v7_1, "pc-i440fx-7.1", NULL, pc_i440fx_7_1_machine_options)는 "pc-i4 40fx-7.1 -machine"을 정의합니다. 이 TypeInfo는 이해하기 어렵지 않습니다.
v7_1뿐만 아니라 "DEFINE_I440FX_MACHINE(v7_1, "pc-i440fx-7.1", NULL, pc_i440fx_7_1_machine_options);"과 유사한 모든 머신 유형이 QOM 유형 목록에 추가됩니다.
다음에 무슨 일이 있었는지 알고 싶다면 다음 장을 봅시다.