spice server qxl red_worker_main()代码分析
2015-07-05 10:12
549 查看
1.在qxl中red_dispatcher_init 非常重要
[cpp] view
plaincopy
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
}
[cpp] view
plaincopy
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
plaincopy
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
}
[cpp] view
plaincopy
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
}
[cpp] view
plaincopy
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
}
[cpp] view
plaincopy
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
plaincopy
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
}
[cpp] view
plaincopy
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
}
相关文章推荐
- 《C语言及程序设计》程序阅读——链表初步
- Perl Learning 4 Input & Output
- c++ primer 学习笔记 3 变量与基本类型
- Asp.Net 分页显示控件
- Java中Runnable和Thread的区别
- spice 图像压缩算法相关代码逻辑流程
- (转)phpmyadmin操作技巧:如何在phpmyadmin里面复制mysql数据库?
- 数据预处理-PDB文件处理代码
- Python编写算法导论基本算法
- Asp.Net Ajax的两种基本开发模式
- 取整的一些方法总结(java)
- Asp.Net 用户验证(自定义IPrincipal和IIdentity)
- c++读书笔记——类的定义
- C# 理解泛型
- 读取生产环境go语言的最佳实践展示
- 在django template中设置临时变量
- 30、Java中Set集合之HashSet、TreeSet和EnumSet
- C# 类型基础
- 代理模式,JDK动态代理
- YII1.0中验证码刷新不更新的问题的解决。