starup_routine.md 7.0 KB

程序运行逻辑简要流程

运行安装

  • 当前运行的版本须与 install.ini (如果该文件存在并位于版本根目录)当前版本一致

实体启动

  • 等待一个实体启动的最长时间为2分钟(Starting的过程)
  • 等待一个实体终止的最长时间也是2分钟(UnLoading的过程)

SpShell 初始化

int app_init()
  1. 创建并显示启动界面
  2. 申请共享内存空间16MB(shm)
  3. 初始化环境(env)
    1. 分配对象内存后放入到共享内存
    2. 从共享空间中初始化 url
    3. 初始化组成的文件路径信息(sp_dir_t)
      1. 主要对终端程序下各模块的路径进行赋值,供后续提取用
    4. 解析主要文件的内容信息(sp_cfg_t)
      1. 加载root.ini
        1. 加载终端信息,终端号,机型等;
        2. 加载配置的路径信息
      2. 加载shell.ini
        1. 读取实体节点,实体名称只能是数字或字母(sp_cfg_shell_entity_t*)
        2. 读取模块(类库)的版本信息(sp_cfg_shell_module_t*)
        3. 读取系统变量(sp_cfg_shell_sysevent_t*)
        4. 读取自启动实体列表(arr_startlist)
        5. 读取实体的调试(Debug)标识(debug_level)
      3. 加载(如果不存在则创建)install.ini文件
    5. 创建实体管理器(sp_mod_mgr_t)
    6. 将实体配置信息加载到实体管理器(sp_mod_t,sp_entity_t)
    7. 获取和记录应用启动时间(btr)
  4. 创建相关组件
    1. 创建并启动总线守护模块(bus_deamon)
      1. 创建 ioqueue_t 对象
        1. 创建未绑定的IO端口对象
      2. 根据url创建接收器对象,url分两种,管道和TCP
      3. 接收到对端的句柄,并创建一个 end_session_t 对象加入到 非注册列表(unregistered_session_list)
      4. 收到注册事件 BUS_TYPE_ENDPT_REGISTER
        1. 加入 已注册列表(registered_session_list),并对已在列表中的session发送新成员的epid
    2. 创建IO管理器(sp_iom_t)
      1. 创建属于spshell的对端接收器(bus::bus_endpt_t)
        1. 发送注册消息
      2. 创建计时器堆(timer_queue_t*)
    3. 创建并启动服务实例(sp_svc_t)
      1. 创建线程池(threadpool)
      2. 创建计时器管理(tmr)
      3. 初始化包处理器列表
    4. 初始化实体管理器(sp_mod_mgr_t)
      1. 启动进程监控器(无操作)
      2. 在SVC中注册实体管理器的SP_PKT_MOD类型事件的回调函数
    5. 创建日志管理(log_t)
      1. 创建日志后台守护对象
    6. 创建变量模块(var)
    7. 创建广播管理模块(bcm)
    8. 创建并启动RPC服务端(rpc)
    9. 创建并启动Sliverlight代理服务端
  5. 启动自启动实体(线程)
    1. 根据自启动列表依次执行(cfg)
    2. 加载模块
      1. 创建进程
      2. 获取模块的Session在线状态,4分钟的时间超时
      3. 发送 MOD_CMD_INIT 指令
      4. 加入到进程监视器中(process_monitor_t)
    3. 加载实体
  6. 启动控制台服务端

    int app_run()
    

执行 sp_iom_run

模块初始化

前提

sphost.exe的启动

  1. 设置当前进程所属的环境变量
  2. 调用Spbase中的SpRun

模块开发定义

  1. 开发模块(.dll)时通过宏声明实体的类型和数量(SpEntityModuleStub)

模块初始化

  1. 从环境中获取实体的信息(env,mod_mgr,cfg)
  2. New一个 SpModule 对象
  3. 加载模块DLL,DLL进入函数设置入口函数和出口函数(即ModuleBase::Init())和全局变量 s_pModuleInst
  4. 初始化模块(SpModule::Init)
    1. 创建IO管理器
      1. 创建对端接收器(bus::bus_endpt_t)
        1. 初始化事件回调函数
        2. BUS_RESULT_DATA -> iom::on_pkt;
        3. BUS_RESULT_INFO -> iom::on_pkt;
        4. BUS_RESULT_EVENT -> iom::NULL;
        5. BUS_RESULT_SYSTEM -> iom::on_sys;
        6. BUS_RESULT_MSG -> iom::on_msg;
      2. 发送注册请求(BUS_TYPE_ENDPT_REGISTER)并得到回应
    2. 创建日志客户端(sp_log_client_t);
      1. local_svc_id=SP_INVALID_SVC_ID
    3. 创建一个模块桩(sp_mod_stub_cb)并添加包处理器(mod_on_pkt)到IO管理器;
  5. 循环执行吞吐操作(SpModule::Run(),底层是sp_iom_run)
    1. 总线连接端吞吐查询;
    2. 计时器吞吐查询;
    3. sp_iom_run 函数在sphost 和 spshell中都会调用
  6. 收到注册实体的MOD_CMD_INIT通知
    1. 触发处理函数mod_on_pkt
    2. sp_mod_stub_t::__on_module_init
    3. SpModule::on_module_init()
    4. 开始注册模块下的实体
      1. 针对逐个实体调用 ModuleBase::RegistEntity(从ModuleBase::Init()进入)
      2. 根据权限优先级别生成实体功能类(SpModule::AddEntityBase)
    5. 将结果通过 MOD_CMD_MOD_RESULT 返回

实体初始化

注意:

  1. 实体对象的创建,是在DLL被加载进来的时候就New出来了,在Module全局变量的构造函数实现;
  2. 实体与模块是共用一个iom实例对象的;
  3. 模块与实体是一对多的关系

初始化过程

  1. 初始化实体功能类(SpEntity)
    1. 创建服务实例(svc)
    2. 设置线程池装饰器
      1. 将当前实体对象设置为线程实体(线程局部存储TLS)
    3. 再创建一个线程池(m_tpool);
      1. 将当前实体对象设置为线程实体(线程局部存储TLS)
    4. 创建一个实体桩(sp_mod_entity_stub_cb)
      1. 赋值回调函数
        1. 启动前(SpEntity::__on_entity_prestart::OnPreStart)
        2. 停止(SpEntity::on_entity_stop::OnPreClose)
        3. 暂停前
        4. 握手(SpEntity::on_entity_test::OnSelfTest)
        5. 继续前
        6. 重定向订阅(SpEntity::on_entity_redirect_subscribe::OnBroadcastSubscribe)
      2. 用户数据(实体对象指针)
      3. 将SP_PKT_MOD包类型事件的处理函数加到服务层(svc)
    5. 创建并启动RPC客户端管理对象(m_rpc_mgr)
      1. 回调函数(SpEntity::__on_rpc_request)
      2. 将包和系统类型事件的处理函数加到服务层(svc)
      3. 创建并启动会话管理对象(sp_ses_mgr_t),只有实体才有这
      4. 回调函数(__on_accept)//调用OnNewSession接口
      5. 将包和系统类型事件的处理函数加到服务层(svc)
    6. 创建日志客户端(m_ent->cfg->idx);
    7. 创建一个变量客户端(var)
    8. 创建一个广播客户端(bcm)
    9. 创建日志监听管理器对象(sp_log_listener_mgr_t)
      1. 回调函数(on_log)
    10. 启动日志监听管理器对象
      1. 将包类型事件的处理函数加到服务层(svc)

其他的启动

Sphost初始化

获取内存空间地址

  1. 申请共享内存空间并返回地址;

执行模块进程

  1. 设置进程环境变量;

实体会话注册