spice server qxl red_worker_main()代码分析
2013-07-05 15:52
399 查看
1.在red_dispatcher_init()中要创建 red_worker线程 下面是red_worker_main()线程运行的函数
2.red_worker_main()中的 red_init()函数分析
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信息,告诉主线程 初始化完毕,请指示下一步工作 }
相关文章推荐
- spice server qxl red_worker_main()代码分析
- spice server qxl red_worker_main()代码分析
- spice server qxl red_worker_main()代码分析
- Spice代码分析(三)——red_worker: red_init
- Spice代码分析(三)——red_worker: red_init
- Spice代码分析(三)——red_worker: red_init
- hostapd的radius/eap server代码分析(1)-main
- hostapd的radius/eap server代码分析(1)-main
- spice server qxl worker 及memslot
- Darwin Streaming Server 核心代码分析
- arcgis sample代码之SOE示例代码Length Calculator Server Object Extension的源码分析
- MDK启动代码__main(),__rt_entry()分析
- 2-4-RHEL6.3搭建samba服务器案例分析与总结(Red Hat Enterprise Linux Server6.3)@树袋飘零
- GoAhead2.5源代码分析之10-web server主程序(main.c)
- 代码分析_fasta_main
- dpdk之多进程client_server_mp源代码分析
- kubernetes之kube-ApiServer代码分析
- NSQ系列之nsqlookupd代码分析二(初识nsqlookupd tcpServer)
- 2-6-RHEL6.5搭建vsftpd服务器案例分析与总结(Red Hat Enterprise Linux Server6.3)@树袋飘零
- hostapd的radius/eap server代码分析(2)-hostapd配置