zoukankan      html  css  js  c++  java
  • guest侧virtio probe + qemu侧 vhost_dev_init + kernel vhost + vhost user +unix域套接字

    guest侧virtio probe

    https://www.jianshu.com/p/e4b29d16bae4

    https://kernelgo.org/virtio-overview.html

     https://blog.csdn.net/qq_15437629/article/details/82084470

    virtio 虚拟化系列之一:从 virtio 论文开始

    https://zhuanlan.zhihu.com/p/68154666

    前端驱动通知后端:
    内核流程mark一下PCI设备驱动流程这个后面可以学习一下,先扫描PCI bus发现是virtio设备再扫描virtio-busworker_thread --> process_one_work --> pciehp_power_thread --> pciehp_enable_slot --> 
    pciehp_configure_device --> pci_bus_add_devices --> pci_bus_add_device --> device_attach --> 
    __device_attach --> bus_for_each_drv --> __device_attach_driver --> driver_probe_device --> 
    pci_device_probe --> local_pci_probe --> virtio_pci_probe --> register_virtio_device --> 
    device_register --> device_add --> bus_probe_device --> device_initial_probe 
    --> __device_attach --> bus_for_each_drv --> __device_attach_driver -->
    driver_probe_device --> virtio_dev_probe --> virtnet_probe (网卡设备驱动加载的入口)
    
    static int virtnet_probe(struct virtio_device *vdev) 
    {
        ......
        virtio_device_ready(vdev);
    }

    qemu侧 vhost_dev_init---- vsock也有
    hw/block/vhost-user-blk.c:318:    ret = vhost_dev_init(&s->dev, &s->vhost_user, VHOST_BACKEND_TYPE_USER, 0);
    hw/virtio/vhost-vsock.c:345:    ret = vhost_dev_init(&vsock->vhost_dev, (void *)(uintptr_t)vhostfd,
    hw/virtio/vhost-vsock.c:348:        error_setg_errno(errp, -ret, "vhost-vsock: vhost_dev_init failed");
    hw/virtio/vhost-user-fs.c:384:    ret = vhost_dev_init(&fs->vhost_dev, &fs->vhost_user,
    hw/virtio/vhost-user-fs.c:387:        error_setg_errno(errp, -ret, "vhost_dev_init failed");
    hw/virtio/vhost.c:1180:int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
    hw/scsi/vhost-user-scsi.c:97:    ret = vhost_dev_init(&vsc->dev, &s->vhost_user,
    hw/scsi/vhost-scsi.c:190:    ret = vhost_dev_init(&vsc->dev, (void *)(uintptr_t)vhostfd,
    hw/net/vhost_net.c:174:    r = vhost_dev_init(&net->dev, options->opaque,
    include/hw/virtio/vhost
    kernel vhost + vhost user


     vhost_dev_init-->vhost_virtqueue_init-->vhost_virtqueue_init-->vhost_set_vring_call
        hw/virtio/vhost-user.c:1935:        .vhost_set_vring_call = vhost_user_set_vring_call,
        hw/virtio/vhost-backend.c:256:        .vhost_set_vring_call = vhost_kernel_set_vring_call,
    kernel vhost 还是 vhost user
     
    273 int vhost_set_backend_type(struct vhost_dev *dev, VhostBackendType backend_type)
    274 {
    275     int r = 0;
    276 
    277     switch (backend_type) {
    278 #ifdef CONFIG_VHOST_KERNEL
    279     case VHOST_BACKEND_TYPE_KERNEL:
    280         dev->vhost_ops = &kernel_ops;
    281         break;
    282 #endif
    283 #ifdef CONFIG_VHOST_USER
    284     case VHOST_BACKEND_TYPE_USER:
    285         dev->vhost_ops = &user_ops;
    286         break;
    287 #endif
    288     default:
    289         error_report("Unknown vhost backend type");
    290         r = -1;
    291     }
    292 
    293     return r;
    294 }
     vhost_user设置unix域套接字
     vhost_user_backend_init()
    
    ---------........
    
    ---------vhost_setup_slave_channel(dev)
    
    ------------------.........
    
    ------------------qemu_set_fd_handler(u->slave_fd, slave_read, NULL, dev)
    
    ------------------.......

    Qemu IO事件处理框架

    qemu添加fd

    用户添加fd的函数为qemu_set_fd_handler,参数中fd为本次添加的fd,后面分别是对该fd的处理函数(read or write),最后opaque为处理函数的参数。

    https://www.cnblogs.com/ck1020/p/8782032.html


     vhost_user设置unix域套接字服务端

    比如contrib/virtiofsd/fuse_virtio.c:722:int virtio_session_mount(struct fuse_session *se)  创建服务端
    721 
    722 int virtio_session_mount(struct fuse_session *se)
    723 {
    724         struct sockaddr_un un;
    725 
    726         if (strlen(se->vu_socket_path) >= sizeof(un.sun_path)) {
    727                 fprintf(stderr, "Socket path too long
    ");
    728                 return -1;
    729         }
    730 
    731         /* Poison the fuse FD so we spot if we accidentally use it;
    732          * DO NOT check for this value, check for se->vu_socket_path
    733          */
    734         se->fd = 0xdaff0d11;
    735 
    736         /* Create the Unix socket to communicate with qemu
    737          * based on QEMU's vhost-user-bridge
    738          */
    739         unlink(se->vu_socket_path);
    740         strcpy(un.sun_path, se->vu_socket_path);
    741         size_t addr_len = sizeof(un.sun_family) + strlen(se->vu_socket_path);
    742 
    743         int listen_sock = socket(AF_UNIX, SOCK_STREAM, 0);
    744         if (listen_sock == -1) {
    745                perror("vhost socket creation");
    746                return -1;
    747         }
    748         un.sun_family = AF_UNIX;
    749 
    750         if (bind(listen_sock, (struct sockaddr *) &un, addr_len) == -1) {
    751                 perror("vhost socket bind");
    752                 return -1;
    753         }
    754 
    755         if (listen(listen_sock, 1) == -1) {
    756                 perror("vhost socket listen");
    757                 return -1;
    758         }
    759 
    760         fprintf(stderr, "%s: Waiting for vhost-user socket connection...
    ", __func__);
    761         int data_sock = accept(listen_sock, NULL, NULL);
    762         if (data_sock == -1) {
    763                 perror("vhost socket accept");
    764                 close(listen_sock);
    765                 return -1;
    766         }
    767         close(listen_sock);
    768         fprintf(stderr, "%s: Received vhost-user socket connection
    ", __func__);
    769         se->vu_socketfd = data_sock;
    
    770 
    771         /* TODO: Some cleanup/deallocation! */
    772         se->virtio_dev = calloc(sizeof(struct fv_VuDev), 1);
    773         se->virtio_dev->se = se;
    774         vu_init(&se->virtio_dev->dev, se->vu_socketfd,
    775                 fv_panic,
    776                 fv_set_watch, fv_remove_watch,
    777                 &fv_iface);
    778 
    779         return 0;
    780 }
    gueset kernel 会调用_class_init

    前端驱动通知后端:
    内核流程mark一下PCI设备驱动流程这个后面可以学习一下,先扫描PCI bus发现是virtio设备再扫描virtio-busworker_thread --> process_one_work --> pciehp_power_thread --> pciehp_enable_slot --> 
    pciehp_configure_device --> pci_bus_add_devices --> pci_bus_add_device --> device_attach --> 
    __device_attach --> bus_for_each_drv --> __device_attach_driver --> driver_probe_device --> 
    pci_device_probe --> local_pci_probe --> virtio_pci_probe --> register_virtio_device --> 
    device_register --> device_add --> bus_probe_device --> device_initial_probe 
    --> __device_attach --> bus_for_each_drv --> __device_attach_driver -->
    driver_probe_device --> virtio_dev_probe --> virtnet_probe (网卡设备驱动加载的入口)
    static int virtnet_probe(struct virtio_device *vdev) 
    {
        ......
        virtio_device_ready(vdev);
    }
    
    /**
     * virtio_device_ready - enable vq use in probe function
     * @vdev: the device
     *
     * Driver must call this to use vqs in the probe function.
     *
     * Note: vqs are enabled automatically after probe returns.
     */
    static inline
    void virtio_device_ready(struct virtio_device *dev)
    {
            unsigned status = dev->config->get_status(dev);
    
            BUG_ON(status & VIRTIO_CONFIG_S_DRIVER_OK);
            dev->config->set_status(dev, status | VIRTIO_CONFIG_S_DRIVER_OK);
    }
     



  • 相关阅读:
    Shiro 集成Spring 使用 redis时 使用redisTemplate替代jedisPool(五)
    shiro 实现 网站登录记住我功能 学习记录(四)
    magento2根据属性id或code来添加options
    微信小程序-注册程序app.js
    微信小程序-目录结构
    如何在最新的PHP 7.1.0上安装和运行最新的Magento 2.1.3
    添加新的php版本到wamp中
    全局使用php
    PHP设计模式之单例模式
    SourceTree使用
  • 原文地址:https://www.cnblogs.com/dream397/p/13867951.html
Copyright © 2011-2022 走看看