spice server qxl red_worker_main()代码分析

发布时间:2016-12-8 0:26:30 编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"spice server qxl red_worker_main()代码分析",主要涉及到spice server qxl red_worker_main()代码分析方面的内容,对于spice server qxl red_worker_main()代码分析感兴趣的同学可以参考一下。

1.在qxl中red_dispatcher_init 非常重要 [cpp] view plaincopyprint? RedDispatcher *red_dispatcher_init(QXLInstance *qxl)  {      RedDispatcher *red_dispatcher;   // 创建RedDispatcher 结构指针      RedWorkerMessage message;        // 定义一个消息,用来判断后面线程Red_worker发过来的ready消息      WorkerInitData init_data;        // 定义一个WorkerInitData结构 用来存储创建Red_worker线程所需要的信息      QXLDevInitInfo init_info;        // 定义qxl初始化数据  保存qxl worker 中函数 get_init_info获取的初始化qxl dev的信息      int r;                           // 线程创建函数的返回参数      RedChannel *display_channel;     // display_channel      RedChannel *cursor_channel;      // cursor_channel      sigset_t thread_sig_mask;        // thread_sig_mask 线程信号掩码   ??????      sigset_t curr_sig_mask;          // curr_sig_mask 当前信号掩码     ??????      ClientCbs client_cbs = { NULL, }; // client_cbs 回调函数             quic_init();                     // quic 初始化      sw_canvas_init();                //sw_canvas 初始化  #ifdef USE_OPENGL      gl_canvas_init();                //gl初始化  #endif // USE_OPENGL          red_dispatcher = spice_new0(RedDispatcher, 1);  // 为red_dispatcher分配内存      ring_init(&red_dispatcher->async_commands);   //初始化red_dispatcher中的异步命令环      spice_debug("red_dispatcher->async_commands.next %p", red_dispatcher->async_commands.next); //打印调试信息      dispatcher_init(&red_dispatcher->dispatcher, RED_WORKER_MESSAGE_COUNT, NULL); // 初始化dispatcher创建套接字和给信息分配内存,后面详说      init_data.qxl = red_dispatcher->qxl = qxl;  //把qxl指针传给前面两种结构,后面一次类推  主要是为后面创建red_worker线程做准备      init_data.id = qxl->id;      init_data.red_dispatcher = red_dispatcher;      init_data.pending = &red_dispatcher->pending;      init_data.num_renderers = num_renderers;      memcpy(init_data.renderers, renderers, sizeof(init_data.renderers));        pthread_mutex_init(&red_dispatcher->async_lock, NULL);      init_data.image_compression = image_compression;      init_data.jpeg_state = jpeg_state;      init_data.zlib_glz_state = zlib_glz_state;      init_data.streaming_video = streaming_video; //上面的都是把一些有用的信息赋给init_data带给将要创建的线程red_worker,        red_dispatcher->base.major_version = SPICE_INTERFACE_QXL_MAJOR;  // 初始化red_dispatcher中的base成员qxl_worker      red_dispatcher->base.minor_version = SPICE_INTERFACE_QXL_MINOR;      red_dispatcher->base.wakeup = qxl_worker_wakeup;      red_dispatcher->base.oom = qxl_worker_oom;      red_dispatcher->base.start = qxl_worker_start;      red_dispatcher->base.stop = qxl_worker_stop;      red_dispatcher->base.update_area = qxl_worker_update_area;      red_dispatcher->base.add_memslot = qxl_worker_add_memslot;      red_dispatcher->base.del_memslot = qxl_worker_del_memslot;      red_dispatcher->base.reset_memslots = qxl_worker_reset_memslots;      red_dispatcher->base.destroy_surfaces = qxl_worker_destroy_surfaces;      red_dispatcher->base.create_primary_surface = qxl_worker_create_primary_surface;      red_dispatcher->base.destroy_primary_surface = qxl_worker_destroy_primary_surface;        red_dispatcher->base.reset_image_cache = qxl_worker_reset_image_cache;      red_dispatcher->base.reset_cursor = qxl_worker_reset_cursor;      red_dispatcher->base.destroy_surface_wait = qxl_worker_destroy_surface_wait;      red_dispatcher->base.loadvm_commands = qxl_worker_loadvm_commands; //上面都是初始化qxl_worker 主要是版本信息和注册函数 这些函数具体会在什么地方调用呢,这个在另一片日志里面有记载,之后我也会更新到这篇日志中来的        qxl->st->qif->get_init_info(qxl, &init_info);        init_data.memslot_id_bits = init_info.memslot_id_bits; //有关worker中的memslot初始化信息      init_data.memslot_gen_bits = init_info.memslot_gen_bits;      init_data.num_memslots = init_info.num_memslots;      init_data.num_memslots_groups = init_info.num_memslots_groups;      init_data.internal_groupslot_id = init_info.internal_groupslot_id;      init_data.n_surfaces = init_info.n_surfaces;  //上面都是有关worker中的memslot初始化信息        num_active_workers = 1;          //活动的worker有几个        sigfillset(&thread_sig_mask);     //信号集的设置 主要是设置某些 信号令red_worker线程对这些信号不发生反映??????      sigdelset(&thread_sig_mask, SIGILL);      sigdelset(&thread_sig_mask, SIGFPE);      sigdelset(&thread_sig_mask, SIGSEGV);      pthread_sigmask(SIG_SETMASK, &thread_sig_mask, &curr_sig_mask);      if ((r = pthread_create(&red_dispatcher->worker_thread, NULL, red_worker_main, &init_data))) { //创建red_worker线程            spice_error("create thread failed %d", r);      }      pthread_sigmask(SIG_SETMASK, &curr_sig_mask, NULL);   //设置信号集 ??????        read_message(red_dispatcher->dispatcher.send_fd, &message); //从套接字中阅读消息      spice_assert(message == RED_WORKER_MESSAGE_READY);      //判断消息是否是RED_WORKER_MESSAGE_READY        display_channel = red_dispatcher_display_channel_create(red_dispatcher); // 创建display_channel通道        if (display_channel) {              //创建好了之后,注册client_cbs回调函数          client_cbs.connect = red_dispatcher_set_display_peer;          client_cbs.disconnect = red_dispatcher_disconnect_display_peer;          client_cbs.migrate = red_dispatcher_display_migrate;          red_channel_register_client_cbs(display_channel, &client_cbs);          red_channel_set_data(display_channel, red_dispatcher);   //设置数据,令display_channel中的data指向red_dispatcher           red_channel_set_cap(display_channel, SPICE_DISPLAY_CAP_MONITORS_CONFIG); //设置性能??????          red_channel_set_cap(display_channel, SPICE_DISPLAY_CAP_STREAM_REPORT);  //设置性能??????          reds_register_channel(display_channel);    //把channel挂到server的channel环上      }        cursor_channel = red_dispatcher_cursor_channel_create(red_dispatcher); //与上面display_chennel类似        if (cursor_channel) {          client_cbs.connect = red_dispatcher_set_cursor_peer;          client_cbs.disconnect = red_dispatcher_disconnect_cursor_peer;          client_cbs.migrate = red_dispatcher_cursor_migrate;          red_channel_register_client_cbs(cursor_channel, &client_cbs);          red_channel_set_data(cursor_channel, red_dispatcher);          reds_register_channel(cursor_channel);      }        qxl->st->qif->attache_worker(qxl, &red_dispatcher->base); //qxl_worker赋给qxl指针 ,,,,,,      qxl->st->qif->set_compression_level(qxl, calc_compression_level());//设置压缩参数        red_dispatcher->next = dispatchers; //把创建的red_dispatcher挂到全局的dispatchers环中      dispatchers = red_dispatcher;      return red_dispatcher; //返回red_dispatcher  }   RedDispatcher *red_dispatcher_init(QXLInstance *qxl) { RedDispatcher *red_dispatcher; // 创建RedDispatcher 结构指针 RedWorkerMessage message; // 定义一个消息,用来判断后面线程Red_worker发过来的ready消息 WorkerInitData init_data; // 定义一个WorkerInitData结构 用来存储创建Red_worker线程所需要的信息 QXLDevInitInfo init_info; // 定义qxl初始化数据 保存qxl worker 中函数 get_init_info获取的初始化qxl dev的信息 int r; // 线程创建函数的返回参数 RedChannel *display_channel; // display_channel RedChannel *cursor_channel; // cursor_channel sigset_t thread_sig_mask; // thread_sig_mask 线程信号掩码 ?????? sigset_t curr_sig_mask; // curr_sig_mask 当前信号掩码 ?????? ClientCbs client_cbs = { NULL, }; // client_cbs 回调函数 quic_init(); // quic 初始化 sw_canvas_init(); //sw_canvas 初始化 #ifdef USE_OPENGL gl_canvas_init(); //gl初始化 #endif // USE_OPENGL red_dispatcher = spice_new0(RedDispatcher, 1); // 为red_dispatcher分配内存 ring_init(&red_dispatcher->async_commands); //初始化red_dispatcher中的异步命令环 spice_debug("red_dispatcher->async_commands.next %p", red_dispatcher->async_commands.next); //打印调试信息 dispatcher_init(&red_dispatcher->dispatcher, RED_WORKER_MESSAGE_COUNT, NULL); // 初始化dispatcher创建套接字和给信息分配内存,后面详说 init_data.qxl = red_dispatcher->qxl = qxl; //把qxl指针传给前面两种结构,后面一次类推 主要是为后面创建red_worker线程做准备 init_data.id = qxl->id; init_data.red_dispatcher = red_dispatcher; init_data.pending = &red_dispatcher->pending; init_data.num_renderers = num_renderers; memcpy(init_data.renderers, renderers, sizeof(init_data.renderers)); pthread_mutex_init(&red_dispatcher->async_lock, NULL); init_data.image_compression = image_compression; init_data.jpeg_state = jpeg_state; init_data.zlib_glz_state = zlib_glz_state; init_data.streaming_video = streaming_video; //上面的都是把一些有用的信息赋给init_data带给将要创建的线程red_worker, red_dispatcher->base.major_version = SPICE_INTERFACE_QXL_MAJOR; // 初始化red_dispatcher中的base成员qxl_worker red_dispatcher->base.minor_version = SPICE_INTERFACE_QXL_MINOR; red_dispatcher->base.wakeup = qxl_worker_wakeup; red_dispatcher->base.oom = qxl_worker_oom; red_dispatcher->base.start = qxl_worker_start; red_dispatcher->base.stop = qxl_worker_stop; red_dispatcher->base.update_area = qxl_worker_update_area; red_dispatcher->base.add_memslot = qxl_worker_add_memslot; red_dispatcher->base.del_memslot = qxl_worker_del_memslot; red_dispatcher->base.reset_memslots = qxl_worker_reset_memslots; red_dispatcher->base.destroy_surfaces = qxl_worker_destroy_surfaces; red_dispatcher->base.create_primary_surface = qxl_worker_create_primary_surface; red_dispatcher->base.destroy_primary_surface = qxl_worker_destroy_primary_surface; red_dispatcher->base.reset_image_cache = qxl_worker_reset_image_cache; red_dispatcher->base.reset_cursor = qxl_worker_reset_cursor; red_dispatcher->base.destroy_surface_wait = qxl_worker_destroy_surface_wait; red_dispatcher->base.loadvm_commands = qxl_worker_loadvm_commands; //上面都是初始化qxl_worker 主要是版本信息和注册函数 这些函数具体会在什么地方调用呢,这个在另一片日志里面有记载,之后我也会更新到这篇日志中来的 qxl->st->qif->get_init_info(qxl, &init_info); init_data.memslot_id_bits = init_info.memslot_id_bits; //有关worker中的memslot初始化信息 init_data.memslot_gen_bits = init_info.memslot_gen_bits; init_data.num_memslots = init_info.num_memslots; init_data.num_memslots_groups = init_info.num_memslots_groups; init_data.internal_groupslot_id = init_info.internal_groupslot_id; init_data.n_surfaces = init_info.n_surfaces; //上面都是有关worker中的memslot初始化信息 num_active_workers = 1; //活动的worker有几个 sigfillset(&thread_sig_mask); //信号集的设置 主要是设置某些 信号令red_worker线程对这些信号不发生反映?????? sigdelset(&thread_sig_mask, SIGILL); sigdelset(&thread_sig_mask, SIGFPE); sigdelset(&thread_sig_mask, SIGSEGV); pthread_sigmask(SIG_SETMASK, &thread_sig_mask, &curr_sig_mask); if ((r = pthread_create(&red_dispatcher->worker_thread, NULL, red_worker_main, &init_data))) { //创建red_worker线程 spice_error("create thread failed %d", r); } pthread_sigmask(SIG_SETMASK, &curr_sig_mask, NULL); //设置信号集 ?????? read_message(red_dispatcher->dispatcher.send_fd, &message); //从套接字中阅读消息 spice_assert(message == RED_WORKER_MESSAGE_READY); //判断消息是否是RED_WORKER_MESSAGE_READY display_channel = red_dispatcher_display_channel_create(red_dispatcher); // 创建display_channel通道 if (display_channel) { //创建好了之后,注册client_cbs回调函数 client_cbs.connect = red_dispatcher_set_display_peer; client_cbs.disconnect = red_dispatcher_disconnect_display_peer; client_cbs.migrate = red_dispatcher_display_migrate; red_channel_register_client_cbs(display_channel, &client_cbs); red_channel_set_data(display_channel, red_dispatcher); //设置数据,令display_channel中的data指向red_dispatcher red_channel_set_cap(display_channel, SPICE_DISPLAY_CAP_MONITORS_CONFIG); //设置性能?????? red_channel_set_cap(display_channel, SPICE_DISPLAY_CAP_STREAM_REPORT); //设置性能?????? reds_register_channel(display_channel); //把channel挂到server的channel环上 } cursor_channel = red_dispatcher_cursor_channel_create(red_dispatcher); //与上面display_chennel类似 if (cursor_channel) { client_cbs.connect = red_dispatcher_set_cursor_peer; client_cbs.disconnect = red_dispatcher_disconnect_cursor_peer; client_cbs.migrate = red_dispatcher_cursor_migrate; red_channel_register_client_cbs(cursor_channel, &client_cbs); red_channel_set_data(cursor_channel, red_dispatcher); reds_register_channel(cursor_channel); } qxl->st->qif->attache_worker(qxl, &red_dispatcher->base); //qxl_worker赋给qxl指针 ,,,,,, qxl->st->qif->set_compression_level(qxl, calc_compression_level());//设置压缩参数 red_dispatcher->next = dispatchers; //把创建的red_dispatcher挂到全局的dispatchers环中 dispatchers = red_dispatcher; return red_dispatcher; //返回red_dispatcher }   2.上面red_dispatcher_init中的函数dispatcher没有详说,下面对其代码详细解析 [cpp] view plaincopyprint? void dispatcher_init(Dispatcher *dispatcher, size_t max_message_type,                       void *opaque)  {      int channels[2]; //定义两个整形值,用来存储互相连接的两个套接字    #ifdef DEBUG_DISPATCHER      setup_dummy_signal_handler(); //虚拟信号处理 ??????  #endif      dispatcher->opaque = opaque;  //赋值      if (socketpair(AF_LOCAL, SOCK_STREAM, 0, channels) == -1) {          spice_error("socketpair failed %s", strerror(errno));          return;      } //利用socketpair创建两个相互连接的套接字,用于主副线程之间的通信,主要用于message信息的传输      pthread_mutex_init(&dispatcher->lock, NULL); //线程锁的初始化       dispatcher->recv_fd = channels[0];  //将套接字赋给dispatcher成员      dispatcher->send_fd = channels[1];      dispatcher->self = pthread_self();        dispatcher->messages = spice_malloc0_n(max_message_type,                                             sizeof(dispatcher->messages[0]));  //为message分配内存空间      dispatcher->max_message_type = max_message_type;   // message最大类型赋值给dispatcher中的max_message_type  }   void dispatcher_init(Dispatcher *dispatcher, size_t max_message_type, void *opaque) { int channels[2]; //定义两个整形值,用来存储互相连接的两个套接字 #ifdef DEBUG_DISPATCHER setup_dummy_signal_handler(); //虚拟信号处理 ?????? #endif dispatcher->opaque = opaque; //赋值 if (socketpair(AF_LOCAL, SOCK_STREAM, 0, channels) == -1) { spice_error("socketpair failed %s", strerror(errno)); return; } //利用socketpair创建两个相互连接的套接字,用于主副线程之间的通信,主要用于message信息的传输 pthread_mutex_init(&dispatcher->lock, NULL); //线程锁的初始化 dispatcher->recv_fd = channels[0]; //将套接字赋给dispatcher成员 dispatcher->send_fd = channels[1]; dispatcher->self = pthread_self(); dispatcher->messages = spice_malloc0_n(max_message_type, sizeof(dispatcher->messages[0])); //为message分配内存空间 dispatcher->max_message_type = max_message_type; // message最大类型赋值给dispatcher中的max_message_type }    

上一篇:InitInstance函数
下一篇:今日刷水题--杭电OJ之2030,汉字统计

相关文章

相关评论