2015-07-18 5 views
0

У меня есть кусок (1024 байта) разделяемой памяти между двумя процессами, для которых у меня есть адрес, на который указывает. Я хочу скопировать некоторые данные в эту общую память и прочитать ее на другом процессе. Исходя из фона C, проще всего сопоставить запись по этому адресу, а затем записать в запись, но, похоже, она не копируется правильно.Сопоставление фрагмента общей памяти для чтения/записи в Ada

В настоящее время я пытаюсь преобразовать указатель в тип указателя на запись с использованием Unchecked Conversion и скопировать в запись, но я вижу различия в данных, когда сравниваю исходную полезную нагрузку с полученным во втором процессе.

Является ли это правильный способ сделать это ?:

type Payload_Array_Type is array (1..255) of Integer_32; 

type Common_Buffer_Type is 
    record 
    Size : Integer_32; 
    Payload : Payload_Array_Type; 
    end record; 

type Common_Buffer_Ptr_Type is access Common_Buffer_Type; 

function Convert_Common_Memory_Ptr is new Unchecked_Conversion (
    Source => System.Address, 
    Target => Common_Buffer_Ptr_Type); 

Common_Memory_Ptr : System.Address; 

procedure Copy_To_Common_Buffer 
(
    Size : Integer_32; 
    Payload : Payload_Array_Type 
) is 
    Common_Buffer_Ptr : Common_Buffer_Ptr_Type; 
begin 
    Common_Buffer_Ptr := Convert_Common_Memory_Ptr(Common_Memory_Ptr); 
    Common_Buffer_Ptr.Size := Size; 
    Common_Buffer_Ptr.Payload(1..255) := Payload(1..255);  
end Copy_To_Common_Buffer; 
+2

Не могли бы вы включить этот фрагмент в полный пример, который демонстрирует проблему? Несколько комментариев: (1) вы объявляете 'Common_Memory_Pointer', но никогда не инициализируете его, чтобы он мог указывать куда угодно или нигде. (2) В базовом программировании не должно быть необходимости для Unchecked_Conversion (3) Зачем назначать отдельные компоненты записи, когда вы можете просто назначить другую запись? (4) Если он разделен между двумя задачами Ada, он должен, вероятно, быть защищенным объектом. –

+1

@Brian, он делится между двумя _processes_. Darthfett, 'System.Address_To_Access_Conversions' будет более« правильным », но, вероятно, не будет работать лучше. Когда вы получаете адрес из любого используемого механизма сопоставления, обычно проще объявить его в Ada как тип доступа к вашему типу записи, а не беспокоиться о конверсиях. –

+0

@Simon, мне непонятно, если эти * процессы * являются одновременно задачами Ada под одной задачей среды или отдельными исполняемыми файлами, независимо запущенными из ОС? Если последнее, то (а) защищенные объекты не помогут. (b), вероятно, необходимо использовать аспекты представления, чтобы точно указать точный макет памяти в обоих исполняемых файлах. Если вы не можете гарантировать, что они построены с использованием одного и того же компилятора, флагов и т. Д. –

ответ

2

Я хотел бы попробовать сделать это следующим образом:

procedure Payload is 

    type Payload_Array_Type is array (1..255) of Integer_32; 

    type Common_Buffer_Type is record 
     Size : Integer_32; 
     Payload : Payload_Array_Type; 
    end record; 
    for Common_Buffer_Type use record -- representation clause should be common to both processes 
     Size at 0 range 0 .. 31; 
     Payload at 0 range 32 .. 1023; 
    end record; 
    for Common_Buffer_Type'Size use 1024; -- check this is also used in the other process. 

    type Common_Buffer_Ptr_Type is access Common_Buffer_Type; 

    Common_Memory_Ptr : System.Address; -- assuming this is where the shared object resides with a real address, possibly make it constant 

    procedure Copy_To_Common_Buffer (Size : in Integer_32; 
        Payload : in Payload_Array_Type) is 
     Common_Buffer : Common_Buffer_Type; 
     for Common_Buffer'Address use Common_Memory_Ptr; -- address overlay 
    begin 
     Common_Buffer := (Size => Size, 
      Payload => Payload); 
    end Copy_To_Common_Buffer; 

begin 

    Copy_To_Common_Buffer (9,(others => 876)); 

end Payload; 

Определения типов должны быть общими для двух процессов, а также к сведению Я использовал предложение представления, чтобы указать, куда идут компоненты.

Я использовал адресную накладку, чтобы указать место, где я пишу, и написал всю запись за один раз.

Также посмотрите, как использовать прагма волатильную, как предлагает @Brian Drummond.

+0

Принимая это, так как это выглядит как лучший способ сделать это.Проблема, с которой я столкнулся, в какой-то мере была связана с аппаратным вопросом, поскольку все 32-битное слово должно было быть написано сразу, иначе данные не были бы написаны правильно. Оценил это в то время, но, должно быть, забыл принять/поддержать! – Darthfett