当前位置: 首页 > news >正文

OpenBMC开发之obmc-ikvm与libvncserver的连理关系

1. 系统启动流程

  • 启动服务(obmc-ikvm.service):ExecStart=/usr/bin/obmc-ikvm -v /dev/video0 -k /dev/hidg0 -p /dev/hidg1
  • ikvm_server.cpp/mian()函数创建Args和Manager对象,解析输入参数和创建管理服务ikvm::Manager manager(args)
  • ikvm_manager.cpp 创建 Manager 对象的时候,初始化 input/video/server 对象,三个对象在 ikvm_manager.hpp 头文件中创建
Manager::Manager(const Args& args) :continueExecuting(true), serverDone(false), videoDone(true),input(args.getKeyboardPath(), args.getPointerPath(), args.getUdcName()),video(args.getVideoPath(), input, args.getFrameRate(),args.getSubsampling()),server(args, input, video)            //创建Server对象
{}
void Manager::run()
{std::thread run(serverThread, this);..........
}void Manager::serverThread(Manager* manager)
{while (manager->continueExecuting){manager->server.run();              //执行Server.run()函数manager->setServerDone();manager->waitVideo();}
}
  • 创建 Server 对象的时候会 通过rfbGetScreen()创建 vncserver 的屏幕缓冲结构体 rfbScreenInfoPtr rfbScree, Server::run()函数调用 rfbProcessEvents()
rfbScreenInfoPtr server;
Server::Server(const Args& args, Input& i, Video& v) :pendingResize(false), frameCounter(0), numClients(0), input(i), video(v)
{std::string ip("localhost");const Args::CommandLine& commandLine = args.getCommandLine();int argc = commandLine.argc;// ikvm_server.hpp: rfbScreenInfoPtr serverserver = rfbGetScreen(&argc, commandLine.argv, video.getWidth(),          //在libvncserver中calloc内存,并对结构体初始化赋值video.getHeight(), Video::bitsPerSample,            //代码位置:src/libvncserver/main.cVideo::samplesPerPixel, Video::bytesPerPixel);..............
}void Server::run()
{   // libvncserver/main.c/L1261/rfbBool rfbProcessEvents(rfbScreenInfoPtr screen,long usec)rfbProcessEvents(server, processTime); // 与libvncserver相关的函数、处理事件从这里开始// 代码位置:src/libvncserver/main.cif (server->clientHead){frameCounter++;if (pendingResize && frameCounter > video.getFrameRate()){doResize();pendingResize = false;}}
}
  • libvncserver/mian.c/rfbProcessEvents()是整个 libvncserver 的入口,套接字监听及消息处理关键在**rfbCheckFds(screen,usec)**函数
//obmc-ikvm函数入口:Server::run()
rfbBool rfbProcessEvents(rfbScreenInfoPtr screen,long usec)
{rfbClientIteratorPtr i;rfbClientPtr cl,clPrev;rfbBool result=FALSE;extern rfbClientIteratorPtrrfbGetClientIteratorWithClosed(rfbScreenInfoPtr rfbScreen);/* 如果未指定超时时间,使用屏幕的延迟更新时间 */if(usec<0)usec=screen->deferUpdateTime*1000;/* 检查文件描述符集合中的活动,处理网络 I/O 事件 */rfbCheckFds(screen,usec);/* 检查 HTTP 文件描述符集合中的活动,处理 HTTP 请求 */rfbHttpCheckFds(screen);/* 获取包含已关闭连接的客户端迭代器 */i = rfbGetClientIteratorWithClosed(screen);/* 遍历所有客户端连接 */cl=rfbClientIteratorHead(i);while(cl) {/* 更新客户端屏幕 */result = rfbUpdateClient(cl);/* 保存当前客户端指针,以便在迭代器前进后检查连接状态 */clPrev=cl;cl=rfbClientIteratorNext(i);/* 如果客户端套接字无效,表示连接已关闭 */if(clPrev->sock==RFB_INVALID_SOCKET) {/* 处理客户端连接断开事件 */rfbClientConnectionGone(clPrev);result=TRUE;}}/* 释放客户端迭代器 */rfbReleaseClientIterator(i);return result;
}
  • rfbCheckFds 主要干两件事:监听新的 socket 连接和转发正常消息(rfbHttpCheckFds 监听 Http 连接,功能类似)

画板

  • **rfbNewTCPOrUDPClient()**函数是初始化rfbClientPtr cl 和迭代器rfbClientIteratorPtr 的地方,同时也是调用newClientHook()钩子函数的地方(回调在 ikvm_server.cpp 中定义enum rfbNewClientAction Server::newClient(rfbClientPtr cl))

2. 客户端迭代器

2.1 动态链表

//libvncserver/src/libvncserver/rfbserver.c
struct rfbClientIterator
{rfbClientPtr next;rfbScreenInfoPtr screen;rfbBool closedToo;
}
struct rfbClientIterator;
//libvncserver/include/rfb/rfb.h
//屏幕帧缓冲区结构体
typedef struct _rfbScreenInfo
{void* screenData;                     //ikvm_server.cpp中定义:Server对象char* frameBuffer;                    //ikvm_server.cpp中定义:宽*高*bytesPerPixelstruct _rfbClientRec* clientHead;     //存储最后一个建立会话的cl信息struct _rfbClientRec* pointerClient;  /**< "Mutex" for pointer events */.................
} rfbScreenInfo, *rfbScreenInfoPtr;
//libvncserver/include/rfb/rfb.h
//连接到VNC服务器的客户端信息
typedef struct _rfbClientRec {rfbScreenInfoPtr screen;void* clientData;struct _rfbClientRec *prev;            //创建的最后cl为NULL,其他的见下图struct _rfbClientRec *next;            //创建的首个cl为NULL,其他的见下图.................
} rfbClientRec, *rfbClientPtr;

假如定义:rfbClientIterator i = rfbGetClientIterator(screen),启动了 3 个 KVM 会话:rfbClientPtr cl0 cl1 cl2

  • rfbScreen 是在创建 obmc-ikvm :Server 对象时创建的,是唯一的
  • Server.run() -> fbProcessEvents(server, processTime) -> i->screen = rfbScreen, i->next = screen->clientHead [libvncserver/main.c/fbProcessEvents(L1278)]
  • CL 是双向动态链表,其赋值逻辑为:libvncserver/src/libvncserver/rfbserver.c/rfbNewTCPOrUDPClient(L470)
//libvncserver/src/libvncserver/rfbserver.c/rfbNewTCPOrUDPClient(L470)
static rfbClientPtr
rfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen,rfbSocket sock,rfbBool isUDP)
{.................cl->next = rfbScreen->clientHead;      //首个会话为clientHead = NULL,指向前一个clcl->prev = NULL;if (rfbScreen->clientHead)rfbScreen->clientHead->prev = cl; //修改前一个cl的prev值rfbScreen->clientHead = cl;           //永远存储最后一个创建的会话cl.................
}

画板

2.2 初始化

首次初始化,在 libvncserver/main.c/rfbProcessEvents()函数中完成,具体场景为:

i = rfbGetClientIteratorWithClosed(screen);               //malloc迭代器结构体,初始化赋值i->screen = rfbScreencl=rfbClientIteratorHead(i);                              //获取最后建立的客户端,cl = i->next = i->screen->clientHeadwhile(cl) {/* 更新客户端屏幕 */result = rfbUpdateClient(cl);/* 保存当前客户端指针,以便在迭代器前进后检查连接状态 */clPrev=cl;cl=rfbClientIteratorNext(i);                            //动态链表查询,直到查询到第一个建立的客户端,其cl0->next = NULL。。。。。}

2.3 应用场景

  • 创建并获取迭代器:it = rfbGetClientIterator(server)
  • 动态链表查询客户:cl = rfbClientIteratorNext(it),查询到首个客户端时,cl0->next = NULL,从而退出

相关文章:

  • 详解多线程高并发IOCP开发模式(含示例说明)
  • STM32的三种启动方式
  • 裂项法、分式分解法——复杂分式的拆解
  • 【LLaMAFactory】LoRa + 魔搭 微调大模型实战
  • llama-factory微调报错:
  • JavaScript在边缘计算(Edge Computing)环境下的性能考量
  • 八股文---Redis(1)
  • 山东科技大学深度学习考试回忆
  • 嵌入式芯片中的 低功耗模式 内容细讲
  • CTF--秋名山车神
  • LeetCode 2563.统计公平数对的数目:排序 + 二分查找
  • QML中的3D功能--纹理应用
  • 致远OA——自定义开发rest接口
  • OSPF综合实验(HCIP)
  • 09-DevOps-Jenkins实现CI持续集成
  • Java集合框架中的List、Map、Set详解
  • 【unity】Vulkan模式下部分Android机型使用VideoPlayer组件播放视频异常问题
  • 超简单的git学习教程
  • 又来聊一下加班的问题
  • jenkins尾随命令
  • 王毅、董军将主持召开中印尼外长防长“2+2”对话机制首次部长级会议
  • 浙江金华一副镇长被指殴打村民,镇党委称仍在调查核实
  • 全国首票海关特殊监管区域外保税再制造业务落地上海
  • 硅基世界的“缘分”——系统与人工智能携手进化
  • 马克龙:美乌欧在法磋商乌克兰问题“积极且有建设性”
  • 习近平抵达柬埔寨金边国际机场发表书面讲话(全文)