虛擬機器無法關閉 qemu虛擬機器的關機方式

2021-10-14 18:58:26 字數 4195 閱讀 8050

qemu虛擬機器的關閉方式主要包括如下幾種方式:

通過qemu monitor的system_powerdown命令進行關閉,

在libvirt對qemu進行管理的情況下,通過virsh shutdown命令進行關閉。

在虛擬機器內使用guest os自帶的關機按鈕進行關閉。

通過qemu monitor的quit命令進行關閉。

在libvirt對qemu進行管理的情況下,通過virsh destroy命令進行關閉。

在主機端通過ctrl+c強制關閉qemu程序關閉虛擬機器。

kill/pkill命令結束程序

system_powerdown是qemu monitor中支援的乙個命令。

qemu程序的主迴圈位於vl.c:main_loop(),在主迴圈會迴圈呼叫main_loop_should_exit()判斷是否結束主迴圈。

main_loog_should_exit()函式中會通過qemu_powerdown_requested()函式判斷qemu虛擬機器是否接收到了powerdown的請求,如果有該請求,則呼叫qemu_system_powerdown(),該函式先發出powerdown的事件,然後通知註冊到powerdown的notifier函式

不同的主機板,會註冊不同的powerdown notifier

以piix4為例,在piix4_pm_realize函式中,會將piix4_pm_powerdwon_req()這個notify handler註冊到qemu虛擬機器的powerdown notifier中。

該notifier handler主要是呼叫acpi_pm1_evt_power_down()函式,在該函式中,會檢測在該虛擬機器主機板上,電源鍵(power button)是否被使能,如果被使能了,則模擬該電源鍵被按下,傳送sci(system control interrupt)中斷,觸發guest os進行關機。

所以qemu monitor的system_powerdown命令本質上是模擬電源鍵被按下觸發sci中斷的動作。至於guest os是否會關機,則由guest os的行為配置決定的,如在windows中,如果在電源設定中,將windows的電源按鍵設定為不響應,則傳送system_powrdown命令後,windows將不做響應,無法實現虛擬機關機,除非windows中將電源鍵功能設定為關機。

virsh shutdown命令會呼叫到libvirt的virdomainshutdown()函式,該函式會繼續呼叫不同型別hypervisor的shutdown函式,如對於qemu而言,它會呼叫到qemu dirver對應的domainshutdown,即qemudomainshutdown(),在該函式中,會執行如下操作:

檢測qemu guest agent是否存在,如果存在並且可用,則通過qemu guest agent告知guest os進行關機操作。

如果qemu guest agent不存在,則檢測qemu虛擬機器是否支援acpi power button,如果支援,則呼叫qemumonitorsystempowerdown()函式,即在qemu monitor中,傳送system_powerdown命令,模擬電源鍵被按下並出發sci的動作,觸發guest os進行關機。

所以,在不用qemu guest agent的情況下,virsh shutdown命令其實就對應到qemu monitor中的system_powerdown命令,只是該命令由libvirt傳送。

在虛擬機器內使用guest os自帶的關機按鈕/功能進行關機,以ubuntu為例,通過systemctl poweroff命令對ubuntu進行關機,該命令會呼叫到kernel/power/poweroff.c檔案中定義個poweroff_work對應的工作,該工作主要是執行do_poweroff()對系統進行關機。

kernel/power/poweroff.c:do_poweroff() -> kernel_power_off() ,該函式關閉所有的使用者程式和裝置,最後呼叫machine_power_off()函式。

machine_power_off() -> power_off() -> native_machine_poweroff() -> pm_power_off() 若該ubuntu執行的虛擬機器支援acpi標準,則pm_power_off將指向acpi_power_off()函式。

acpi_power_off() -> acpi_enter_sleep_state()

該函式將會往acpi標準中規定的暫存器pm1 control registers fixed hardware feature control bits中的slp_type和slp_en域寫相應的資料,讓虛擬機器主機板進入到指定的睡眠狀態,即acpi標準中定義的s0 ~ s5狀態。

而在qemu模擬器方面,在hw/acpi/core.c中會對pm1 control registers fixed hardware feature control bits的寫進行監控,當向sly_typ和sly_en寫特定值的時候,會觸發qemu呼叫qemu_system_shutdown_request()發出shutdown的請求。

qemu程序的主要迴圈函式main_loop()中,會迴圈呼叫main_loop_should_exit()函式,該函式會檢測系統中是否有shutdown的請求發出。若有shutdown的請求,則qemu程序退出主迴圈,結束並退出qemu虛擬機器。

qemu monitor的quit命令讓qemu程序直接退出。

直接在qemu monitor中輸入quit命令,將觸發qemu虛擬機器直接退出,guest os完全不知道虛擬機器即將關閉,所以對guest os來說,將會直接閃退,類似物理機的直接掉電。

quit命令將排程到qemu的hmp_quit()函式,該函式將會告知qemu程序在虛擬機器關閉的時候退出,同時發出shutdown的請求,qemu程序的主迴圈main_loop()在執行main_loop_should_exit()檢查是否需要退出主迴圈的時候,將檢測到該事件,然後直接退出。

libvirt提供的virsh destroy命令,將呼叫到qemu driver的qemudomaindestroy() -> qemudomaindestroyflags() -> qemuprocessstop() -> qemuprocesskill()介面,將qemu程序關掉。

qemuprocesskill()中,將會向qemu程序傳送sigkill或sigterm訊號,讓qemu程序退出。

在qemu這邊,qemu的主程序中,會通過os_setup_signal_handling()設定對訊號的響應。

termsig_handler() -> qemu_system_killed(),在qemu_system_killed()中,將會生成shutdown的請求,並且shutdown請求的原因是host signal。該請求將會讓qemu程序的主迴圈退出,不等guest os準備好關機。

在主機端通過ctrl+c組合鍵,讓qemu程序退出,其實是向qemu程序傳送sigint訊號,該訊號的處理方式和sigterm是一樣的,也就是最後呼叫到qemu_system_killed()函式,發出shutdown請求,讓qemu主程序退出,同時記錄下shutdown的原因為host signal。

在主機端使用kill -9 pid或者pkill -9 pname的方式,也是向主機程序傳送sigkill訊號,讓程序退出的。

qemu編譯 建立虛擬機器

首先安裝編譯qemu依賴包 apt get install gcc libsdl1.2 dev zlib1g dev libasound2 dev linux kernel headers pkg config libgnutls dev libpci dev tar jxvf qemu 1.4.2...

qemu虛擬機器離線快照

qemu磁碟快照管理 1 建立快照 qemu img snapshot c snapshot name your os img.qcow2 2 檢視快照 qemu img snapshot l your os img.qcow2 3 刪除快照 qemu img snapshot d snapshot...

關閉虛擬機器Hyper V

這就要說前幾天安裝的docker了。開啟了hyper v服務之後發現安裝模擬器失敗,必須要關閉hyper v 那就來關閉試試吧 第一步 檢視是否關閉功能 第二步 試了網上的方法,以管理員身份開啟cmd關閉服務 bcdedit set hypervisorlaunchtype off 然後重啟。發現沒...