您的位置:首页 > 编程语言

spice server qxl red_worker_main()代码分析

2013-07-05 15:52 399 查看
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信息,告诉主线程 初始化完毕,请指示下一步工作
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: