配置环境变量

vsomeip应用启动时以下的环境变量会被读取:
VSOMEIP_APPLICATION_NAME,赋予当前程序在vsomeip中使用的名字。vsomeip会通过改名字在配置文件中进行匹配查找。该名字与二进制可执行文件的名字是不一样的。
VSOMEIP_CONFIGURATION,vsomeip默认会使用配置文件/etc/vsomeip.json或者包含配置文件的文件夹/etc/vsomeip。你可以通过该变量使vsomeip使用自定义的配置文件。
VSOMEIP_MANDATORY_CONFIGURATION_FILES,vsomeip允许使用mandatory配置文件来加快应用的启动速度(此时,除负责连接某些外部设别的程序之外,其他所有程序运行时都需要按照mandatory配置文件工作)。默认mandatory配置文件是:vsomeip_std.json,vsomeip_app.json和vsomeip_plc.json。

基础知识:

析构函数:

  1. 对象离开其作用域:当一个局部对象的作用域结束时(例如在函数执行结束或代码块结束时),其析构函数会被自动调用。

  2. 动态分配对象的释放:通过new关键字动态分配的对象,必须使用delete来释放。在调用delete释放动态分配的对象时,其析构函数会被自动调用。

  3. 对象作为成员变量的析构:当一个对象是另一个类的成员变量时,当该类的析构函数被调用时,它的成员变量的析构函数会被自动调用。

  4. 继承和多态:在继承体系中,如果基类的析构函数是虚函数,当使用基类指针指向派生类对象并通过该指针删除对象时,会自动调用派生类的析构函数。

(void)argc;
(void)argv;
这样做只是为了满足编译器的要求,告诉编译器你有意不使用这些参数,从而消除编译器警告。

虚函数

override

class Base {
public:
    virtual void foo() {
        std::cout << "Base::foo() called." << std::endl;
    }
};

class Derived : public Base {
public:
    // 使用 override 表示重写基类虚函数 foo
    void foo() override {
        std::cout << "Derived::foo() called." << std::endl;
    }
};

在上述示例中,Derived类中的foo()函数使用override关键字,它表示该函数是对基类Base中的虚函数foo()进行重写。如果Base类中没有名为foo()的虚函数,或者它不是虚函数,编译器将产生错误。

virtual void start() = 0

上述是C++中声明一个纯虚函数的语法。它是一个虚函数,没有实际的实现。任何派生类必须提供自己的start()函数实现,否则派生类也会成为抽象类。通常,希望定义一个接口(或者称为基类)并要求派生类提供特定行为时会使用纯虚函数。

如何改硬件的mac地址?

  1. 停用卡
    sudo ip link set dev xxxx(网卡名) down
  2. 分配mac地址
    sudo ip link set dev xxxx address XX:XX:XX:XX:XX:XX
  3. 激活卡
    sudo ip link set dev xxxx up
  4. 检查是否已更改
    ip link ls

API

application的创建

using namespace vsomeip;
std::shared_ptr<runtime> rtm_ = runtime::get();
std::shared_ptr<application> app_= rtm_->create_application("name")

源码如下:

std::shared_ptr<application> runtime_impl::create_application(
        const std::string &_name, const std::string &_path) {
    static std::uint32_t postfix_id = 0; // 计数id
    std::lock_guard<std::mutex> its_lock(applications_mutex_); // 上锁
    std::string its_name = _name; // 程序名
    auto found_application = applications_.find(_name); // 去map里面找程序名
    if( found_application != applications_.end()) {
        its_name += "_" + std::to_string(postfix_id++); // 如果找到了就做重名处理
    }
    std::shared_ptr<application> application
        = std::make_shared<application_impl>(its_name, _path); // 创建一个application类型的智能指针
    applications_[its_name] = application; // 放到map里面
    return application; // 返回application的智能指针
}

初始化的变量:

application_impl::application_impl(const std::string &_name)
        : runtime_(runtime::get()),
        client_(VSOMEIP_CLIENT_UNSET), //默认client id = 0xFFFF
        session_(0), //初始化session id = 0
        is_initialized_(false), 
        name_(_name), //应用名称
        work_(std::make_shared<boost::asio::io_service::work>(io_)),
        //route_manager指针, 有两种角色,一个是host,一个是proxy,实现不一样
        routing_(0),
        //初始化app状态为DEREGISTERRED状态
        state_(state_type_e::ST_DEREGISTERED),
        //安全模式
        security_mode_(security_mode_e::SM_OFF),
#ifdef VSOMEIP_ENABLE_SIGNAL_HANDLING
        signals_(io_, SIGINT, SIGTERM),
        catched_signal_(false),
#endif
        is_dispatching_(false),
        max_dispatchers_(VSOMEIP_MAX_DISPATCHERS),
        max_dispatch_time_(VSOMEIP_MAX_DISPATCH_TIME),
        stopped_(false),
        block_stopping_(false),
        is_routing_manager_host_(false),
        stopped_called_(false),
        watchdog_timer_(io_),
        client_side_logging_(false)

noexcept是C++11引入的关键字,用于指示函数不会抛出异常。它放置在函数声明或定义的尾部,并用于表示函数在运行时不会引发任何异常。

void myFunction() noexcept;

需要注意的是,如果在noexcept声明的函数内部抛出了异常,程序将会调用std::terminate函数,导致程序终止。因此,使用noexcept时需要确保函数内部不会引发异常,否则会破坏程序的正常执行。

init():

配置模块

  • 获取名字

  • application_impl.cpp 142行

    configuration_ = its_configuration_plugin->get_configuration(name_, path_);

关键是这个get_configuration(name_, path_)函数

std::shared_ptr<configuration>
configuration_plugin_impl::get_configuration(const std::string &_name,
        const std::string &_path) {

    std::lock_guard<std::mutex> its_lock(mutex_);
    if (!default_) {
        default_ = std::make_shared<cfg::configuration_impl>(_path);
        default_->load(_name);
    }
    return default_;

default_->load(_name)
函数主体:
bool configuration_impl::load(const std::string &_name)
内部逻辑:

  1. 配置默认环境
  2. 如果有本地环境配置,覆盖配置
  3. 如果有存在的环境配置,覆盖配置

路由配置加载:

bool
configuration_impl::load_routing(const configuration_element &_element)

路由配置

创建路由

    if (is_routing_manager_host_) {
        // 创建host类型的路由
        VSOMEIP_INFO << "Instantiating routing manager [Host].";
        if (client_ == VSOMEIP_CLIENT_UNSET) {
            client_ = static_cast<client_t>(
                      (configuration_->get_diagnosis_address() << 8)
                    & configuration_->get_diagnosis_mask());
            utility::request_client_id(configuration_, name_, client_);
        }
        routing_ = std::make_shared<routing_manager_impl>(this);
    } else {
        // 创建proxy类型的路由
        VSOMEIP_INFO << "Instantiating routing manager [Proxy].";
        routing_ = std::make_shared<routing_manager_client>(this, client_side_logging_, client_side_logging_filter_);
    }

创建host或proxy类型的路由

routing_manager_impl::routing_manager_impl(routing_manager_host *_host) :
        routing_manager_base(_host),
        version_log_timer_(_host->get_io()),
        if_state_running_(false),
        sd_route_set_(false),
        routing_running_(false),
        status_log_timer_(_host->get_io()),
        memory_log_timer_(_host->get_io()),
        ep_mgr_impl_(std::make_shared<endpoint_manager_impl>(this, io_, configuration_)),
        pending_remote_offer_id_(0),
        last_resume_(std::chrono::steady_clock::now().min()),
        statistics_log_timer_(_host->get_io()),
        ignored_statistics_counter_(0)
{
}

路由模块初始化

routing_->init()
将通信端点管理器赋给父类中的ep_mgr_指针
routing_manager_base::init(ep_mgr_impl_)
创建stub端,即创建一个用于本地域通讯的服务端

bool is_successful = host_->get_endpoint_manager()->create_routing_root(
        root_, is_socket_activated_, shared_from_this());

路由模块初始化时序图:

组播地址配置:
route add -nv 224.224.224.245 dev eth0和route add -net 224.0.0.0/4 dev eth0的区别

  • route add -nv 224.224.224.245 dev eth0:
    这个命令的目的是将特定的目标IP地址(224.224.224.245)配置到指定的网络接口(eth0)上。
    -n 参数告诉系统不要进行反向DNS查找,以IP地址形式显示输出。
    -v 参数用于显示详细的操作信息,通常是"verbose"的缩写。
  • route add -net 224.0.0.0/4 dev eth0:
    这个命令的目的是将属于特定目标IP地址范围(224.0.0.0/4)的所有流量配置到指定的网络接口(eth0)上。
    -net 参数表示将目标地址视为一个网络地址范围,而不是单独的IP地址。
    224.0.0.0/4 是一个组播(multicast)IP地址范围,用于多点通信。

总的来说,第一个命令是将特定IP地址配置到网络接口上,而第二个命令是将一个IP地址范围(用于组播)配置到网络接口上。在某些情况下,你可能需要根据具体需求来选择使用哪种命令。