spice server qxl red_worker_main()代码分析

1.在red_dispatcher_init()中要创建 red_worker线程 下面是red_worker_main()线程运行的函数

SPICE_GNUC_NORETURN void *red_worker_main(void *arg)       //这里的arg其实就是 在red_dispatcher_init()中的init_data结构
{
    RedWorker *worker = spice_malloc(sizeof(RedWorker));    //创建worker 并分配内存

    spice_info("begin"); //打印调试和错误信息
    spice_assert(MAX_PIPE_SIZE > WIDE_CLIENT_ACK_WINDOW &&
           MAX_PIPE_SIZE > NARROW_CLIENT_ACK_WINDOW); //ensure wakeup by ack message

#if  defined(RED_WORKER_STAT) || defined(COMPRESS_STAT)
    if (pthread_getcpuclockid(pthread_self(), &clock_id)) {
        spice_error("pthread_getcpuclockid failed");
    }
#endif

    red_init(worker, (WorkerInitData *)arg);    //内容挺多,后面单独分析
    red_init_quic(worker);  // 图像压缩初始化的,初始化worker中的quic_data成员
    red_init_lz(worker);   //图像压缩初始化的,初始化worker中的lz_data成员
    red_init_jpeg(worker); //图像压缩初始化的,初始化worker中的jpeg_data成员
    red_init_zlib(worker); //图像压缩初始化的,初始化worker中的zlib_data成员
    worker->event_timeout = INF_EVENT_WAIT;// 超时时间设置
    for (;;) {       //这个for循环主要用于对超时和poll机制轮训的处理,并且真正做显示和视频图像处理的也就在这个循环中了
        int i, num_events;
        unsigned int timers_queue_timeout;

        timers_queue_timeout = spice_timer_queue_get_timeout_ms();
        worker->event_timeout = MIN(red_get_streams_timout(worker), worker->event_timeout);
        worker->event_timeout = MIN(timers_queue_timeout, worker->event_timeout);
        num_events = poll(worker->poll_fds, MAX_EVENT_SOURCES, worker->event_timeout);
        red_handle_streams_timout(worker);
        spice_timer_queue_cb();

        if (worker->display_channel) {
            /* during migration, in the dest, the display channel can be initialized
               while the global lz data not since migrate data msg hasn't been
               received yet */
            red_channel_apply_clients(&worker->display_channel->common.base,
                                      red_display_cc_free_glz_drawables);
        }

        worker->event_timeout = INF_EVENT_WAIT;
        if (num_events == -1) {
            if (errno != EINTR) {
                spice_error("poll failed, %s", strerror(errno));
            }
        }

        for (i = 0; i < MAX_EVENT_SOURCES; i++) {
            /* The watch may have been removed by the watch-func from
               another fd (ie a disconnect through the dispatcher),
               in this case watch_func is NULL. */
            if (worker->poll_fds[i].revents && worker->watches[i].watch_func) {
                int events = 0;
                if (worker->poll_fds[i].revents & POLLIN) {
                    events |= SPICE_WATCH_EVENT_READ;
                }
                if (worker->poll_fds[i].revents & POLLOUT) {
                    events |= SPICE_WATCH_EVENT_WRITE;
                }
                worker->watches[i].watch_func(worker->poll_fds[i].fd, events,
                                        worker->watches[i].watch_func_opaque);
            }
        }

        /* Clear the poll_fd for any removed watches, see the comment in
           watch_remove for why we don't do this there. */
        for (i = 0; i < MAX_EVENT_SOURCES; i++) {
            if (!worker->watches[i].watch_func) {
                worker->poll_fds[i].fd = -1;
            }
        }

        if (worker->running) {
            int ring_is_empty;
            red_process_cursor(worker, MAX_PIPE_SIZE, &ring_is_empty);//处理光标
            red_process_commands(worker, MAX_PIPE_SIZE, &ring_is_empty);//处理显示命令
        }
        red_push(worker);//往客户端推送显示的数据和视频
    }
    abort();
}

2.red_worker_main()中的  red_init()函数分析

static void red_init(RedWorker *worker, WorkerInitData *init_data)
{
    RedWorkerMessage message;  //定义一个信息 message
    Dispatcher *dispatcher;  // 定义一个dispatcher
    int i;

    spice_assert(sizeof(CursorItem) <= QXL_CURSUR_DEVICE_DATA_SIZE);

    memset(worker, 0, sizeof(RedWorker));  // 把RedWorker清零
    dispatcher = red_dispatcher_get_dispatcher(init_data->red_dispatcher);// 把init_data带过来的信息全部取过来,赋给worker成员
    dispatcher_set_opaque(dispatcher, worker); //dispatcher的opaque指针指向worker
    worker->red_dispatcher = init_data->red_dispatcher;
    worker->qxl = init_data->qxl;
    worker->id = init_data->id;
    worker->channel = dispatcher_get_recv_fd(dispatcher);
    register_callbacks(dispatcher);
    worker->pending = init_data->pending;
    worker->cursor_visible = TRUE;
    spice_assert(init_data->num_renderers > 0);
    worker->num_renderers = init_data->num_renderers;
    memcpy(worker->renderers, init_data->renderers, sizeof(worker->renderers));//上面是把init_data信息赋给RedWorker
    worker->renderer = RED_RENDERER_INVALID; //渲染
    worker->mouse_mode = SPICE_MOUSE_MODE_SERVER;//鼠标模式设置为服务器模式
    worker->image_compression = init_data->image_compression;//下面是图像压缩的设置
    worker->jpeg_state = init_data->jpeg_state;
    worker->zlib_glz_state = init_data->zlib_glz_state;
    worker->streaming_video = init_data->streaming_video; //视频压缩的设置,上面是图像压缩的设置
    worker->driver_cap_monitors_config = 0; //驱动器配置参数
    ring_init(&worker->current_list); //current_list环初始化
    image_cache_init(&worker->image_cache); //图像缓存初始化
    image_surface_init(worker); //图像表面初始化
    drawables_init(worker); //drawables初始化 主要是把drawables放到free_drawables链表中
    cursor_items_init(worker);//cursor_item_init初始化 主要是把cursor的item放到free_cursor_item链表中
    red_init_streams(worker); //stream流初始化 其中的成员streames 环初始化(两个向后指针都指向自己),free_streams=NULL,streams_buf[i]中的stream全部放到worker的free_streams中
    stat_init(&worker->add_stat, add_stat_name); //把add_stat_name赋给add_stat
    stat_init(&worker->exclude_stat, exclude_stat_name);//把exclude_stat_name赋给exclude_stat
    stat_init(&worker->__exclude_stat, __exclude_stat_name);
#ifdef RED_STATISTICS   //下面都是用于做统计的
    char worker_str[20];
    sprintf(worker_str, "display[%d]", worker->id);
    worker->stat = stat_add_node(INVALID_STAT_REF, worker_str, TRUE);//状态检测??
    worker->wakeup_counter = stat_add_counter(worker->stat, "wakeups", TRUE); //wakeup计数器
    worker->command_counter = stat_add_counter(worker->stat, "commands", TRUE);//command计数器
#endif          //上面都是用于统计的
    for (i = 0; i < MAX_EVENT_SOURCES; i++) {
        worker->poll_fds[i].fd = -1;
    }           //对worker中的poll_fds数组进行初始化,即每个pollfd结构的fd描述符都赋值为-1 

    worker->poll_fds[0].fd = worker->channel;  //添加一个事件套接字描述符
    worker->poll_fds[0].events = POLLIN;     //事件类型为输入
    worker->watches[0].worker = worker;   //worker
    worker->watches[0].watch_func = handle_dev_input;//处理输入的函数handle_dev_input
    worker->watches[0].watch_func_opaque = worker; //函数handle_dev_input的参数为worker

    red_memslot_info_init(&worker->mem_slots,
                          init_data->num_memslots_groups,
                          init_data->num_memslots,
                          init_data->memslot_gen_bits,
                          init_data->memslot_id_bits,
                          init_data->internal_groupslot_id);//初始化worker中的memslots结构

    spice_warn_if(init_data->n_surfaces > NUM_SURFACES);
    worker->n_surfaces = init_data->n_surfaces;  //表面数的赋值

    if (!spice_timer_queue_create()) {  //创建定时器队列,并进行判断
        spice_error("failed to create timer queue");
    }
    srand(time(NULL));          //随机数的初始化

    message = RED_WORKER_MESSAGE_READY;  //为mesage赋值为ready
    write_message(worker->channel, &message); //向主线程中写入ready信息,告诉主线程 初始化完毕,请指示下一步工作
}


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值