Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Apakah yang berlaku jika saya menjalankan 2 goroutine untuk mengubah suai VM dan memusnahkan VM yang sama menggunakan pakej libvirt-go pada contoh yang sama?

Apakah yang berlaku jika saya menjalankan 2 goroutine untuk mengubah suai VM dan memusnahkan VM yang sama menggunakan pakej libvirt-go pada contoh yang sama?

王林
王林ke hadapan
2024-02-08 21:48:121084semak imbas

我运行 2 个 goroutine 来修改虚拟机并在同一实例上使用 libvirt-go 包销毁同一虚拟机会发生什么?

php Editor Yuzai Masalah yang anda nyatakan melibatkan penggunaan pakej libvirt-go untuk memusnahkan mesin maya pada masa yang sama pada kejadian yang sama. Dalam kes ini, dua goroutine boleh mengubah suai mesin maya pada masa yang sama, yang boleh membawa kepada hasil yang tidak dapat diramalkan. Memandangkan goroutine tidak dapat menjamin tertib pelaksanaan apabila dilaksanakan serentak, ia mungkin membawa kepada keadaan perlumbaan atau konflik data, yang boleh menyebabkan kegagalan pemusnahan mesin maya, rasuah data atau keabnormalan lain. Untuk mengelakkan situasi ini, anda boleh memastikan bahawa hanya satu goroutine boleh mengubah suai mesin maya pada satu masa dengan menggunakan kunci mutex atau mekanisme kawalan konkurensi yang lain. Ini boleh memastikan atomicity dan konsistensi operasi dan mengelakkan masalah yang tidak perlu.

Kandungan soalan

Seperti yang kita semua tahu, libvirt selamat untuk benang. Walau bagaimanapun, menjalankan dua goroutine serentak yang bertindak pada sumber yang sama (seperti mengubah suai dan memadam mesin maya) meninggalkannya dalam keadaan samar-samar. Bagaimanakah libvirt memutuskan susunan pelaksanaan goroutine?

Ini kod yang saya cuba:

package main

import (
    "fmt"

    "github.com/libvirt/libvirt-go"
)

func main() {
    conn, err := libvirt.NewConnect("qemu:///system")
    if err != nil {
        fmt.Printf("Failed to connect to libvirt: %v\n", err)
        return
    }
    defer conn.Close()

    // Create a new VM
    domainXML := `
        <domain type='kvm'>
            <name>myvm</name>
            <memory unit='KiB'>1048576</memory>
            <vcpu placement='static'>1</vcpu>
            <os>
                <type arch='x86_64' machine='pc-i440fx-2.9'>hvm</type>
                <boot dev='hd'/>
            </os>
            <devices>
                <disk type='file' device='disk'>
                    <driver name='qemu' type='qcow2'/>
                    <source file='path/to/disk'/>
                    <target dev='vda' bus='virtio'/>
                    <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
                </disk>
            </devices>
        </domain>`

    dom, err := createVM(conn, domainXML)
    if err != nil {
        fmt.Printf("Failed to create VM: %v\n", err)
        return
    }

    go modifyVMMemory(dom, 2*1024*1024) // 2 GiB

    go deleteVM(dom)

}

func createVM(conn *libvirt.Connect, domainXML string) (*libvirt.Domain, error) {
    dom, err := conn.DomainCreateXML(domainXML, 0)
    if err != nil {
        return nil, err
    }
    return dom, nil
}

func modifyVMMemory(dom *libvirt.Domain, newMemory uint64) error {
    err := dom.SetMaxMemory(newMemory)
    if err != nil {
        return err
    }
    fmt.Print("Modified VM")
    return nil
}

func deleteVM(dom *libvirt.Domain) error {
    err := dom.Destroy()
    if err != nil {
        return err
    }

    err = dom.Undefine()
    if err != nil {
        return err
    }

    fmt.Print("Deleted VM")

    return nil
}

Prosedur berjaya diselesaikan jadi domain telah dimusnahkan dan boleh dicipta semula Tetapi menjalankannya semula mengakibatkan ralat berikut:

virError(Code=9, Domain=20, Message='operation failed: domain 'myvm' already exists with uuid 32c25acb-a4c5-4bfd-b2f5-f07b3d9b8eea')

Penyelesaian

Keselamatan benang bermaksud bahawa kod tidak akan mengalami masalah kerosakan memori apabila berbilang benang menggunakan sambungan yang sama pada masa yang sama.

Tingkah laku semantik yang anda akan perolehi masih tidak ditentukan.

libvirt QEMU/KVM pemandu dalam aplikasi pelanggan dan libvirtd(或 virtqemud)守护进程之间使用 RPC 层。所以首先你有非确定性,其中 Goroutine 首先运行。当 libvirt-go-module API 通过 CGo 调用 C ibvirt.so 库时,它们将被锁定到本机操作系统线程,然后该线程将在 libvirt.so 内部同步,以决定哪个首先将其 RPC 消息发送到网络上。在 libvirtd 守护进程中,也有很多线程,并且 RPC 消息理论上是 FIFO 处理的,但是,libvirtd 内部的 API 逻辑仍然会争夺锁,因此在与 QEMU 通信/交互时会增加更多的不确定性。基本上,您的 SetMaxMemoryDestroy API 调用可以按任一顺序运行。如果您需要保证顺序,则需要在应用程序中对它们进行序列化,以便仅在完成 ​​SetMaxMemory 后调用 Destroy

Akhirnya IIUC kod Go anda tidak mantap kerana main() 方法生成了两个 goroutine,但没有等待它们中的任何一个完成。 IOW,在任一 goroutine 完全运行之前,Go 进程很可能会退出。这可能就是为什么您收到有关 VM 已存在的错误消息的原因 - deleteVM goroutine tidak pernah berjalan sehingga proses keluar.

Atas ialah kandungan terperinci Apakah yang berlaku jika saya menjalankan 2 goroutine untuk mengubah suai VM dan memusnahkan VM yang sama menggunakan pakej libvirt-go pada contoh yang sama?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam