簡體   English   中英

如何在不同內核之間正確共享運行時創建的多態數據? 嵌入式 c++

[英]How to properly share polymorphic data created at runtime between different cores? Embedded c++

我正在使用雙核設備,並且需要核心 A 創建一個包含 arguments 的數據結構,以獲取在核心 B 上運行的功能列表,定期更新它並通知核心 B。 arguments 的數量和類型可以更改在運行期間。

我的計划如下..

創建一個ParamsInterface基礎 class 並且每個 function 都有自己的參數 class 派生自基礎 ZA2F2ED4F8EBC2CBB1。 使用多態性,這將允許我在共享 memory 中創建ParamsInterface*的向量,並從核心 A 填充它。

核心 A 通過new填充它需要的任何子 class 填充向量,並將返回的指針推送到向量。

示例核心 A:

volatile std::vector<ParamsInterface*> sharedParams __attribute__((section(".shared_memory")))

class ParamsInterface
{
public:
    virtual ~ParamsInterface(){};
};

class Function1Params: public ParamsInterface
{
public:
    float mParam1;
    bool  mParam2;
};


void populate() 
{
    Function1Params *params = new Function1Params ;
    params->mParam1= 1.1;
    params->mParam2 = true;
    sharedParams.push_back(params);
}

然后核心 B 應該能夠靜態地將指針轉換為子類型,因為它知道向量的每個成員將是哪種類型。 當然訪問是由硬件信號量控制的,所有指針在刷新列表之前都會被刪除。

核心 B 示例:

void process(ParamsInterface* params)
{
    Function1Params paramsCasted = static_cast<Function1Params *>(params);
    processFunc1(paramsCasted->mParam1, paramsCasted->mParam2);
}

問題是當核心 B 讀取這個共享的、未緩存的數據時,ParamsInterface* 指向的地址不正確,並且在嘗試強制轉換時遇到了硬錯誤。 我檢查了 Core A 創建的指針,它指向兩個內核都可以訪問的 memory 區域。

我的問題有兩個方面,首先,我在這里做錯了什么-也許期望一種永遠行不通的方法起作用? 其次,我是否錯過了更好的方法來做到這一點? 我遺漏了有關函數列表如何工作以嘗試保持問題簡潔的信息。

非常感謝您的幫助。

編輯:

因此,問題似乎與創建 ParamsInterface 對象的位置有關。 核心 A 創建它們並將它們放置在堆中,不幸的是,它恰好位於不在托管的區域中,而核心 B 顯然無法訪問。

如果我使用placement new將它們放置在memory 的托管部分中,我必須指定一個精確的地址,但這會變得非常復雜,因為所有ParamsInterface 對象的大小都可能不同。

那么有沒有辦法將 new() '多態'對象放入特定 memory 部分中的容器中? 還是我需要編寫某種自定義 memory 池管理器?

謝謝

從非常類似於 C 的角度來看,您似乎正在接近 C++ 代碼。 它們不僅在語法上是非常不同的野獸。

C++ 代碼是獨立解釋的,與硬件上下文無關,編譯器沒有義務尊重您編寫的內容,除了確保維護代碼產生的副作用。 這被稱為假設規則。

這擴展到多線程和多進程環境中的 memory 訪問。 除非另有說明,否則編譯器可以假設 memory 只會被他們正在編譯的代碼更改和讀取,並且不涉及外部因素。

這是一個具體的例子:

int* sharedParams[12] __attribute__((section(".shared_memory")));

void populate() 
{
    auto params = new int{12};
    sharedParams[4] = params;
}

int main() {
    populate();

    while(1) {}
}

如果我用gcc -O3 -flto編譯它,我得到以下程序:

 jmp    401020 <main>
 cs nop WORD PTR [rax+rax*1+0x0]
 nop    DWORD PTR [rax+0x0]

sharedParams數組甚至不再存在! 見神螺栓

牢記這一點,以下內容:

當然訪問是由硬件信號量控制的。

是不足夠的。 C++ 語言不知道這些,跨線程/內核的對象之間的同步必須在語言級別以及硬件級別完成。 如果您不這樣做,則允許編譯器對 memory 的使用方式做出各種假設,並且會優化很多東西。

有兩種方法可以解決這個問題:

  1. 使用語言級別的結構,例如標准庫中的各種實用程序。 std::atomic_thread_fence可能是您在這里需要的。 見神螺栓
void populate() 
{    
    int* params = new int{12};
    sharedParams[4] = params;
    std::atomic_thread_fence( std::memory_order_release ); // std::memory_order_acquire when reading
}

注意std::atomic_thread_fence 並不是非常適合這個用例,但是因為您已經在語言范圍之外進行操作。 應該適合這里的賬單,但不會有正式的保證。

  1. 將有爭議的 memory 標記為volatile ,以便編譯器停止對其何時以及如何更改進行假設。 見神螺栓
volatile int* sharedParams[12] __attribute__((section(".shared_memory")));
void populate() 
{
    int volatile * params = new volatile int{12};
    sharedParams[4] = params;
}

第一種選擇是非常可取的。 雖然它不像每次訪問時都設置完整的 memory 屏障那么殘酷,但后者會嚴重束縛編譯器的雙手。 volatile也不保證事情會以正確的順序發生。

進一步閱讀: https://en.cppreference.com/w/cpp/atomic/memory_order

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM