Skip to content
This repository has been archived by the owner on Aug 18, 2021. It is now read-only.

Latest commit

 

History

History
452 lines (400 loc) · 19.4 KB

README.md

File metadata and controls

452 lines (400 loc) · 19.4 KB

IPC Diversion Section

Overview

  • It is a general-purpose implementation of Inter-processing communication between the Server and Client (IPC section).
  • It consists mainly of the following:
    • IPC library implementation source: src, include
    • IPC unit test program: ipc_unit_test

Building Method

  • Building by following steps:
    $ mkdir build
    $ cd build
    $ cmake ..
    $ make
    • The above commands can be executed with the following script:
      $ ./buildtest.sh

The installation described next will be installed on the host PC (/usr/local/). To change the installation destination, change the option passed to cmake.

Example 
$ cmake -DCMAKE_INSTALL_PREFIX=./install ..

Installing Method

$ cd build
$ sudo make install

When succeeded, the following log will be output.

[100%] Built target ipc
Install the project...
-- Install configuration: ""
-- Installing: /usr/local/lib/pkgconfig/ipc.pc
-- Installing: /usr/local/lib/libipc.so.1.0.0
-- Installing: /usr/local/lib/libipc.so.1
-- Installing: /usr/local/lib/libipc.so
-- Installing: /usr/local/include/ipc.h
-- Installing: /usr/local/include/ipc_protocol.h

Building Product

  • At last, Building will generate the following:
    • <installdir>/include/ (External Public header files)
      ipc.h
      ipc_protocol.h
    • <installdir>/lib/ (Shared library files)
      libipc.so   ( Symbolic link ) 
      libipc.so.1 ( Symbolic link )
      libipc.so.1.0.0
    • build/ipc_unit_test/ (Test program executable file)
      ipc_unit_test_client
      ipc_unit_test_server

How to use

  • This library contains functions for Server and Client; Each has different usage.

Common of Server/Client

  • The user needs to link with the following libraries.
    • libipc.so
  • User includes the library as following.
    • #include <ipc.h>
      • ipc_protocol.h description is not required; it described later within ipc.h (include <ipc.h>).
  • The header files are used as follows.
    • ipc.h
      • Declare a list of available API functions.
    • ipc_protocol.h
      • Define IPC usage types and data structures for each usage.
  • In libraries, Server and Client communicate using Unix Domain Socket.
    • Generate different communication files for each usage type.
    • By default, a communication file is generated in the execution hierarchy of the Server.
    • For changing the location where generating the communication files, set the environment variable "IPC_DOMAIN_PATH"
    Example)
    $ export IPC_DOMAIN_PATH="/tmp"
      →Unix Domain Socket communication files will be generated under /tmp.
    

For IC-Service

  • Using this library for IC-Service, use the following values and structures (see ipc_protocol.h).
    • UsageType:IPC_USAGE_TYPE_IC_SERVICE
    • Sending data structure:IPC_DATA_IC_SERVICE_S
    • Changing type callback notification (enum):IPC_KIND_IC_SERVICE_E
    • Unix Domain Socket communication File name:IpcIcService
  • For IC-Service, the Cluster API library (libcluster_api.so) is the IPC Client.
    • The API for Client is called from libcluster_api.so (described later)

Server API

  • Server applied libipc.so can use the following APIs:
    • ipcServerStart(IPC_USAGE_TYPE_E usageType);
      • Starting the IPC Server for the specified usageType.
    • ipcSendMessage(IPC_USAGE_TYPE_E usageType, const void* pData, signed int size);
      • Sending data to the IPC Client for the specified usageType.
      • Specifying address and size of the sending data by pData and size arguments.
      • Sending data is stored in the Data Pool prepared on the IPC Client side.
    • ipcServerStop(IPC_USAGE_TYPE_E usageType);
      • Terminate the IPC Server for the specified usageType.

Client API

  • The Client applied libipc.so can use the following APIs:
    • ipcClientStart(IPC_USAGE_TYPE_E usageType);
      • Starting the IPC Client for the specified usageType.
      • Connecting with IPC Server for the same usageType.
    • ipcReadDataPool(IPC_USAGE_TYPE_E usageType, void* pData, signed int* pSize);
      • Reading all data in the Data Pool for the specified usageType.
      • The address where storing the read data is specified in pData. Moreover, the size of storing data is specified in pSize.
      • The contents of the Data Pool output to pData, and the actual read size output to pSize.
    • ipcRegisterCallback(IPC_USAGE_TYPE_E usageType, IPC_CHANGE_NOTIFY_CB changeNotifyCb);
      • When receiving data from the IPC Server, register the callback function for the specified usageType, which receiving notification of which data changed to what.
    • ipcClientStop(IPC_USAGE_TYPE_E usageType);
      • Terminate the IPC Client for the specified usageType.

Unit test executing method

  • Limitations

    • Currently 2020/12/25, this test program connects Server and Client for IC-Service.
    • The Unix domain socket communication files are generated under /tmp/ with the file name ipcIcService.
  • Since Inter processing communication takes place between ipc_unit_test_server and ipc_unit_test_client, so start each one in a separate terminal. Testing example as bellow (Manually operated):

    1. Starting Server and then starting Client

      (Terminal 1)
      $ ./ipc_unit_test_server
      command (h=help, q=quit):
      (Terminal 2)
      $ ./ipc_unit_test_client
      command (h=help, q=quit):

      At this point, the Server and Client connection for IC-Service is completed. (Executing ipcServerStart () and ipcClientStart ())

    2. Editing and Sending Server data

      (Terminal 1)
      command (h=help, q=quit):w ←★input w 
      write command (h=help q=goto main menu):2 1 ←★input 2 1
      write command (h=help q=goto main menu):70 50 ←★input 70 50
      write command (h=help q=goto main menu):l ←★input 1
      ★Sending data list is displayed, the result of input contents as below. 
        2: brake(4) = 1 ←★write command 2 1 result
        70: oTempUnitVal(4) = 50 ←★write command 70 50 result
      write command (h=help q=goto main menu):q ←★input q
      command (h=help, q=quit):s ←★input s (Executing ipcSendMessage())
      ipcSendMessage return:0
      command (h=help, q=quit):

      On the Client side, The callback function should be responding.

      (Terminal 2)
      command (h=help, q=quit):Enter changeNotifyCb ←★callback
      kind = 2, size = 4, data=1 ←★Notification of brake value changed to 1 
      Leave changeNotifyCb

      ★oFor TempUnitVal change as an IC-Service, there is no callback since it is not monitored.

    3. Check Client side receiving.

      (Terminal 2)
      command (h=help, q=quit):r ←★input r
      ★Sending data list is displayed, Sending data contained as bellow. 
        2: brake(4) = 1
       70: oTempUnitVal(4) = 50
    4. Exit Client then Server.

      (Terminal 2)
      command (h=help, q=quit):q
      bye...
      $
      (Terminal 1)
      command (h=help, q=quit):q
      bye...
      $

Adding/Changing IPC usage type method

  • First, the implementation only for IC-Service, but configured to add data for other services easily.
  • Information for each usage type is managed in the following files:
    • include/ipc_protocol.h (External Public header)
    • src/ipc_usage_info_table.c (IPC Internal Source)
  • Adding information for new service or changing information for existed service only by two files above.
    • No changes are required other than .c or .h files in ipc.
    • However, Regarding the application and test program used IPC, It is necessary to take measures according to the adding/changing of the ipc_protocol.h definition.
  • Ideally, code can be generated automatically using tools and else. We do not consider that implementation this time.

Sample code for adding/changing the usage type (Sample code difference)

First, the sample code for adding/changing two files as follow.

Example 1: When adding a new usage type

The following example shows differences when adding the temporary usage type NEW_SERVICE. (Parameters influenced when adding new usage type within the IPC)

diff --git a/include/ipc_protocol.h b/include/ipc_protocol.h
index c0ad861..2bc1115 100644
--- a/include/ipc_protocol.h
+++ b/include/ipc_protocol.h
@@ -6,6 +6,7 @@
 typedef enum {
     IPC_USAGE_TYPE_IC_SERVICE = 0,
     IPC_USAGE_TYPE_FOR_TEST,
+    IPC_USAGE_TYPE_NEW_SERVICE, // Adding usage type
     IPC_USAGE_TYPE_MAX
 } IPC_USAGE_TYPE_E;

@@ -145,4 +146,17 @@ typedef struct {
     signed int test;
 } IPC_DATA_FOR_TEST_S;

+// for IPC_USAGE_TYPE_NEW_SERVICE
+typedef enum { // Preparing only the type which we want to monitor/notify data change
+    IPC_KIND_NS_PARAM1 = 0,
+    IPC_KIND_NS_PARAM2
+} IPC_KIND_NEW_SERVICE_E;
+
+typedef struct { // This part for sending and receiving all data 
+    int param1;
+    int param2;
+    int param3;
+    int param4;
+} IPC_DATA_NEW_SERVICE_S;
+
 #endif // IPC_PROTOCOL_H
diff --git a/src/ipc_usage_info_table.c b/src/ipc_usage_info_table.c
index 976cc73..51264c6 100644
--- a/src/ipc_usage_info_table.c
+++ b/src/ipc_usage_info_table.c
@@ -51,16 +51,24 @@ static IPC_CHECK_CHANGE_INFO_S g_ipcCheckChangeForTest[] = {
     DEFINE_OFFSET_SIZE(IPC_DATA_FOR_TEST_S, test, IPC_KIND_TEST_TEST)
 };

+//   for IPC_USAGE_TYPE_FOR_TEST
+static IPC_CHECK_CHANGE_INFO_S g_ipcCheckChangeNewService[] = { // Describing only the type which we want to monitor/notify data change
+    DEFINE_OFFSET_SIZE(IPC_DATA_NEW_SERVICE_S, param1, IPC_KIND_NS_PARAM1),
+    DEFINE_OFFSET_SIZE(IPC_DATA_NEW_SERVICE_S, param2, IPC_KIND_NS_PARAM2)
+}; //This example not monitoring/notifying changes of param3, param4 data
+
 // == usage info table ==
 //   index of [] is IPC_USAGE_TYPE_E
 IPC_DOMAIN_INFO_S g_ipcDomainInfoList[] =
 {
     {sizeof(IPC_DATA_IC_SERVICE_S), "ipcIcService"},
-    {sizeof(IPC_DATA_FOR_TEST_S), "ipcForTest"}
+    {sizeof(IPC_DATA_FOR_TEST_S), "ipcForTest"},
+    {sizeof(IPC_DATA_NEW_SERVICE_S), "ipcNewService"} // add sending/receiving size information for new Service 
 };

 IPC_CHECK_CHANGE_INFO_TABLE_S g_ipcCheckChangeInfoTbl[] = {
     DEFINE_CHANGE_INFO_TABLE(g_ipcCheckChangeIcService),
-    DEFINE_CHANGE_INFO_TABLE(g_ipcCheckChangeForTest)
+    DEFINE_CHANGE_INFO_TABLE(g_ipcCheckChangeForTest),
+    DEFINE_CHANGE_INFO_TABLE(g_ipcCheckChangeNewService) // Registering data change monitoring table for new Service
 };

Example 2: Deleting part of the existing usage type data

The following example shows differences when deleting the member variable brake from usage sending/receiving data of existing IC-Service. (Parameters influenced when a member variable is deleted within the IPC)

diff --git a/include/ipc_protocol.h b/include/ipc_protocol.h
index c0ad861..7fed8bf 100644
--- a/include/ipc_protocol.h
+++ b/include/ipc_protocol.h
@@ -13,7 +13,6 @@ typedef enum {
 typedef enum {
     IPC_KIND_ICS_TURN_R = 0,
     IPC_KIND_ICS_TURN_L,
-    IPC_KIND_ICS_BRAKE,
     IPC_KIND_ICS_SEATBELT,
     IPC_KIND_ICS_HIGHBEAM,
     IPC_KIND_ICS_DOOR,
@@ -51,7 +50,6 @@ typedef struct {
     // Telltale
     signed int turnR;
     signed int turnL;
-    signed int brake;
     signed int seatbelt;
     signed int frontRightSeatbelt;
     signed int frontCenterSeatbelt;
diff --git a/src/ipc_usage_info_table.c b/src/ipc_usage_info_table.c
index 976cc73..40ac8df 100644
--- a/src/ipc_usage_info_table.c
+++ b/src/ipc_usage_info_table.c
@@ -12,7 +12,6 @@
 static IPC_CHECK_CHANGE_INFO_S g_ipcCheckChangeIcService[] = {
     DEFINE_OFFSET_SIZE(IPC_DATA_IC_SERVICE_S, turnR, IPC_KIND_ICS_TURN_R),
     DEFINE_OFFSET_SIZE(IPC_DATA_IC_SERVICE_S, turnL, IPC_KIND_ICS_TURN_L),
-    DEFINE_OFFSET_SIZE(IPC_DATA_IC_SERVICE_S, brake, IPC_KIND_ICS_BRAKE),
     DEFINE_OFFSET_SIZE(IPC_DATA_IC_SERVICE_S, seatbelt, IPC_KIND_ICS_SEATBELT),
     DEFINE_OFFSET_SIZE(IPC_DATA_IC_SERVICE_S, highbeam, IPC_KIND_ICS_HIGHBEAM),
     DEFINE_OFFSET_SIZE(IPC_DATA_IC_SERVICE_S, door, IPC_KIND_ICS_DOOR),

Common items regarding new addition of usage type

  • Adding some new enumerations/structures, with addition to existing enumeration/structure. There are no restrictions on the names.

Adding Information to include/ipc_protocol.h

  • For one usage type, adding the following three items of information.
    • Add usage type name.
    • For new usage, Define enumeration for the change notification type.
    • For new usage, Define sending/receiving data structure.
  • Adding usage type name
    • Sample code of this part will be as follow:
       typedef enum {
           IPC_USAGE_TYPE_IC_SERVICE = 0,
           IPC_USAGE_TYPE_FOR_TEST,
      +    IPC_USAGE_TYPE_NEW_SERVICE, // Adding usage type
           IPC_USAGE_TYPE_MAX
       } IPC_USAGE_TYPE_E;
    • Adding a member for the usage type in enum IPC_USAGE_TYPE_E.
    • Make sure to add it just before IPC_USAGE_TYPE_MAX (Avoiding effect on existing definitions)
    • The value defined here is used to specify the argument usageType such as ipcServerStart() defined in ipc.h.
  • For new usage, Define enumeration for the change notification type.
    • Sample code of this part will be as follow:
      +typedef enum { // Preparing only the type which we want to monitor data change
      +    IPC_KIND_NS_PARAM1 = 0,
      +    IPC_KIND_NS_PARAM2
      +} IPC_KIND_NEW_SERVICE_E;
    • Adding an enumeration for the data change notification type. Related to the sending/receiving data structures will describe next.
    • This value is used to specify the third argument kind of callback function registered by ipcRegisterCallback().
    • There are no restrictions for naming enumeration and member.
  • For new usage, Define sending/receiving data structure.
    • Sample code of this part will be as follow:
      +typedef struct { // This part for sending and receiving all data
      +    int param1;
      +    int param2;
      +    int param3;
      +    int param4;
      +} IPC_DATA_NEW_SERVICE_S;
    • For new usage, adding send/receive data structures.
    • The IPC Server will send all the data in the defined structure to the IPC Client.

Regarding adding src/ipc_usage_info_table.c

  • For one usage type, adding the following three items of information.

    • Add a type mapping table for data change notification.
    • Add communication domain information (Communication size and file name).
    • Add mapping table for a relationship between usage and change type.
  • Add a type mapping table for data change notification.

    • Sample code of this part will be as follow:
      +//   for IPC_USAGE_TYPE_FOR_TEST
      +static IPC_CHECK_CHANGE_INFO_S g_ipcCheckChangeNewService[] = { // Preparing only the type which we want to monitor data change
      +    DEFINE_OFFSET_SIZE(IPC_DATA_NEW_SERVICE_S, param1, IPC_KIND_NS_PARAM1),
      +    DEFINE_OFFSET_SIZE(IPC_DATA_NEW_SERVICE_S, param2, IPC_KIND_NS_PARAM2)
      +}; // This example not monitoring/notifying changes of param3, param4 data
      
    • For new usage, add a structure array of IPC_CHECK_CHANGE_INFO_S.
    • Describing a table that maps the definition of change notification type enumeration (defined in ipc_protocol.h) with the data structure members.
    • This table is used for Callback notification of the last receiving data type change when the IPC Client received data from the IPC Server.
    • In structure array, describing multiple macros which defining matching as shown below.
      DEFINE_OFFSET_SIZE(<Data structure name>, <Structure member name>, Change notification enumeration member name),
    • In the case of the above sample code, g_ipcCheckChangeNewService[] will be as follows.
      • If the value of param1 is different from the value of the previous receiving, the callback change type IPC_KIND_NS_PARAM1 is notified to the IPC Client.
      • If the value of param2 is different from the value of the previous receiving, the callback change type IPC_KIND_NS_PARAM2 is notified to the IPC Client.
      • For param3 and param4 are not described, the callback does not notify even if the value of the previous receiving is different.
  • Add communication domain information (Communication size and file name).

    • Sample code of this part will be as follow:
       IPC_DOMAIN_INFO_S g_ipcDomainInfoList[] =
       {
           {sizeof(IPC_DATA_IC_SERVICE_S), "ipcIcService"},
      -    {sizeof(IPC_DATA_FOR_TEST_S), "ipcForTest"}
      +    {sizeof(IPC_DATA_FOR_TEST_S), "ipcForTest"},
      +    {sizeof(IPC_DATA_NEW_SERVICE_S), "ipcNewService"} //add sending/receiving size information for new Service 
       };
    • In structure array g_ipcDomainInfoList[], adding the domain information for new usage.
    • This addition determines the sending/receiving data size used for the newly added usage type and Domain file name used for Unix Domain Socket communication.
    • It is necessary to match the definition order of the enum IPC_USAGE_TYPE_E of ipc_protocol.h, so ensure adding it at the end.
    • Add communication data size structure and the domain filename information to the end of g_ipcDomainInfoList[], as follows:
      {sizeof(<communication data structure name>), "domain file name"},
  • Add mapping table for a relationship between usage and change type.

    • Sample code of this part will be as follow:
       IPC_CHECK_CHANGE_INFO_TABLE_S g_ipcCheckChangeInfoTbl[] = {i
           DEFINE_CHANGE_INFO_TABLE(g_ipcCheckChangeIcService),
      -    DEFINE_CHANGE_INFO_TABLE(g_ipcCheckChangeForTest)
      +    DEFINE_CHANGE_INFO_TABLE(g_ipcCheckChangeForTest),
      +    DEFINE_CHANGE_INFO_TABLE(g_ipcCheckChangeNewService) // Registering data change monitoring table for new service
       };
    • In structure array g_ipcCheckChangeInfoTbl[], adding information about the mapping table for a relationship between new usage and change notification type.
    • It is necessary to match the definition order of the enum IPC_USAGE_TYPE_E of ipc_protocol.h, so ensure adding it at the end.
    • Describing the above-mentioned "change notification type mapping table structure" in the following macro, then add it to the end of g_ipcCheckChangeInfoTbl[].
      DEFINE_CHANGE_INFO_TABLE(<change notification type mapping table structure name>), 

Changing of sending data for existing usage

  • When deleting or renaming a member variable in an existing sending data structure in ipc_protocol.h

    • Trying to build each ipc part and application that uses ipc for the service, then fix the part that causing the Compile error.
  • When adding a member variable in an existing sending data structure in ipc_protocol.h

Supplement

  • In src/ipc_usage_info_table.c, the information is described in the DEFINE_OFFSET_SIZE() macro, which using offsetof() and sizeof() to get the offset and size of member variables from the head of the related structure.
    • In order to make it easier to add usage types, the IPC process does not directly specify variable names in data structures.
    • For each usage, by preparing an offset table of the data structure, it becomes possible to know what variables are in which byte of the sending data.
      • This structure makes it possible to check data change without directly specifying the member variable name inside the IPC process.
    • Adding the usage type according to Adding/Changing IPC usage type method, the IPC inter processing can process new usage.