Skip to the content.

qemu io/ 目录中的功能

简单来说,就是真正和外界打交道的代码:

  io
     channel-buffer.c
     channel-command.c
     channel-file.c
     channel-null.c
     channel-socket.c
     channel-tls.c
     channel-util.c
     channel-watch.c
     channel-websock.c
     channel.c
     dns-resolver.c
     meson.build
     net-listener.c
     task.c
     trace-events
     trace.h

从这里想到的:

void socket_send_channel_create(QIOTaskFunc f, void *data)
{
    QIOChannelSocket *sioc = qio_channel_socket_new();
    qio_channel_socket_connect_async(sioc, outgoing_args.saddr,
                                     f, data, NULL, NULL);
}

应该是很简单的东西把,通过这两个 backtrace 基本上可以看到了, channel 应该是 qemu 和外部世界打交道的,可以提供给 chardev ,也是可以提供给 multifd 的

而 ./chardev 的各种 char 的后端应该使用的也是使用的 ./channel

vu_message_read 来看 qemu io 的基本流程

首先在一个 while 循环中调用 qio_channel_readv_full ,将 header 读取到。

然后调用 qio_channel_readv_all_eof 来把所有。

https://github.com/yandex-cloud/yc-libvhost-server

AioContext 在 QIOChannel 的作用是什么

没用那么大的作用:

在 fd 重新注册 handler

配置上 qio_channel_restart_write qio_channel_restart_read

当 fd 再有事件之后,那么就是调用这两个函数。

migration/rdma.c 也是抽象为一个 channel 了

static void qio_channel_rdma_class_init(ObjectClass *klass,
                                        const void *class_data G_GNUC_UNUSED)
{
    QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass);

    ioc_klass->io_writev = qio_channel_rdma_writev;
    ioc_klass->io_readv = qio_channel_rdma_readv;
    ioc_klass->io_set_blocking = qio_channel_rdma_set_blocking;
    ioc_klass->io_close = qio_channel_rdma_close;
    ioc_klass->io_create_watch = qio_channel_rdma_create_watch;
    ioc_klass->io_set_aio_fd_handler = qio_channel_rdma_set_aio_fd_handler;
    ioc_klass->io_shutdown = qio_channel_rdma_shutdown;
}

和 chardev/char-socket.c 和 io/channel-socket.c 的关系

chardev/char-socket.c 依赖底层的 io/channel-socket.c

chardev/char-socket.c 表示用 socket 来模拟 chardev ,核心是 chardev ,而 io/channel-socket.c 是 qemu 如何和 socket 打交道的封装,不一定用来模拟 chardev , 也可以用于热迁移的数据发送。

他们的典型例子就是 chardev/char-socket.c:tcp_chr_write

static int tcp_chr_write(Chardev *chr, const uint8_t *buf, int len)
{
    SocketChardev *s = SOCKET_CHARDEV(chr);

    if (s->state == TCP_CHARDEV_STATE_CONNECTED) {
        int ret =  io_channel_send_full(s->ioc, buf, len,
                                        s->write_msgfds,
                                        s->write_msgfds_num);

        /* free the written msgfds in any cases
         * other than ret < 0 && errno == EAGAIN
         */
        if (!(ret < 0 && EAGAIN == errno)
            && s->write_msgfds_num) {
            g_free(s->write_msgfds);
            s->write_msgfds = 0;
            s->write_msgfds_num = 0;
        }

        if (ret < 0 && errno != EAGAIN) {
            if (tcp_chr_read_poll(chr) <= 0) {
                /* Perform disconnect and return error. */
                trace_chr_socket_poll_err(chr, chr->label);
                tcp_chr_disconnect_locked(chr);
            } /* else let the read handler finish it properly */
        }

        return ret;
    } else {
        /* Indicate an error. */
        errno = EIO;
        return -1;
    }
}

问题

本站所有文章转发 CSDN 将按侵权追究法律责任,其它情况随意。