2019-03-21 【c++&c#】進(jìn)程間通訊__共享內(nèi)存

進(jìn)程間通訊方式:共享內(nèi)存,管道(linux),udp通訊(若是在同一臺(tái)電腦上通過(guò)udp通訊您宪,那么它并沒(méi)有經(jīng)過(guò)網(wǎng)絡(luò)勒葱,而是利用了網(wǎng)卡上的一塊內(nèi)存坎缭,而且非潮鸩t?煽考沽拧#?/p>

這是項(xiàng)目中用到的一處共享內(nèi)存拣宰,別人寫的轩端。記錄一下放典,讓每個(gè)看似毫無(wú)意義的項(xiàng)目都能吸收到一點(diǎn)有用的東西。
項(xiàng)目中使用到的地方:服務(wù)器要發(fā)送數(shù)據(jù)給unity基茵,但是接收數(shù)據(jù)的格式是需要以固定的MFC(c/c++)代碼接收奋构。然后就在MFC代碼中增加一處共享內(nèi)存,作為中轉(zhuǎn)站拱层,unity讀取這處共享內(nèi)存獲得數(shù)據(jù)弥臼。

  • 0.前置準(zhǔn)備

| 句柄數(shù)據(jù)結(jié)構(gòu)

        typedef struct semps
        {
            HANDLE hMFCWrite;                            //聲明信號(hào)量變量
            HANDLE hU3DRead;                             //聲明信號(hào)量變量
            HANDLE hU3DWrite;                            //聲明信號(hào)量變量
            HANDLE hMFCRead;                             //聲明信號(hào)量變量

            char *pBuf; 
            CMainFrame *mFrm;
        }Semps;

        Semps mSemp;
        HANDLE hMapFile;
  • 1.實(shí)例化共享內(nèi)存

image.png
ProcessMsg::ProcessMsg(CMainFrame *frm)
{

    mSemp.hMFCWrite = CreateSemaphoreA(NULL,1,1,"WriteMap_1");
    mSemp.hU3DRead = CreateSemaphoreA(NULL,0,1,"ReadMap_1"); //第二各參數(shù)為0,代表進(jìn)程創(chuàng)建信號(hào)量之時(shí)便聲明了對(duì)該信號(hào)量的占用

    mSemp.hU3DWrite = CreateSemaphoreA(NULL,1,1,"WriteMap_2");
    mSemp.hMFCRead = CreateSemaphoreA(NULL,0,1,"ReadMap_2"); //第二各參數(shù)為0根灯,代表進(jìn)程創(chuàng)建信號(hào)量之時(shí)便聲明了對(duì)該信號(hào)量的占用


    //創(chuàng)建共享內(nèi)存區(qū)
    char szName[] = "shareMemory";    // 共享內(nèi)存的名字

    // 創(chuàng)建共享文件句柄
    hMapFile = CreateFileMapping(
        INVALID_HANDLE_VALUE,    // 物理文件句柄
        NULL,                    // 默認(rèn)安全級(jí)別
        PAGE_READWRITE,          // 可讀可寫
        0,                       // 高位文件大小
        BUF_SIZE,                // 地位文件大小
        szName                   // 共享內(nèi)存名稱
        );
 
 
    mSemp.pBuf = (char *)MapViewOfFile(
        hMapFile,            // 共享內(nèi)存的句柄
        FILE_MAP_ALL_ACCESS, // 可讀寫許可
        0,
        0,
        BUF_SIZE
        );

    mSemp.mFrm = frm;

    AfxBeginThread((AFX_THREADPROC)ThreadProc,(LPVOID)&mSemp,THREAD_PRIORITY_IDLE);
}

Tips :


https://docs.microsoft.com/zh-cn/windows/desktop/api/winbase/nf-winbase-createsemaphorea

https://blog.csdn.net/educast/article/details/8477294
  • 由上圖可知径缅,此時(shí)已經(jīng)創(chuàng)建好了共享內(nèi)存文件(通過(guò)CreateFileMapping),并完成映射(通過(guò)MapViewOfFile)烙肺,接下來(lái)就是要弄unity里面連接映射的地方了纳猪。
  • 2.MFC向共享內(nèi)存寫入數(shù)據(jù)

//發(fā)送消息到u3d
void ProcessMsg::SendMsgToU3D(char *str){
    strncpy(mSemp.pBuf, str, BUF_SIZE);

    //strncpy(mSemp.pBuf, str, BUF_SIZE - 1);
    //mSemp.pBuf[BUF_SIZE - 1] = '\0';

    //放u3d讀
    //ReleaseSemaphore(mSemp.hU3DRead,1,0);
    //放u3d開(kāi)寫
    //ReleaseSemaphore(mSemp.hU3DWrite,1,0);
}
  • 3.unity連接映射地址

image.png

Ps:固定格式代碼

    const int INVALID_HANDLE_VALUE = -1;
    const int PAGE_READWRITE = 0x04;

    bool _loadingRedStartMap = false;

    //共享內(nèi)存
    [DllImport("Kernel32.dll", EntryPoint = "CreateFileMapping")]
    private static extern IntPtr CreateFileMapping(IntPtr hFile, //HANDLE hFile,
     UInt32 lpAttributes,//LPSECURITY_ATTRIBUTES lpAttributes,  //0
     UInt32 flProtect,//DWORD flProtect
     UInt32 dwMaximumSizeHigh,//DWORD dwMaximumSizeHigh,
     UInt32 dwMaximumSizeLow,//DWORD dwMaximumSizeLow,
     string lpName//LPCTSTR lpName
     );

    [DllImport("Kernel32.dll", EntryPoint = "OpenFileMapping")]
    private static extern IntPtr OpenFileMapping(
     UInt32 dwDesiredAccess,//DWORD dwDesiredAccess,
     int bInheritHandle,//BOOL bInheritHandle,
     string lpName//LPCTSTR lpName
     );

    const int FILE_MAP_ALL_ACCESS = 0x0002;
    const int FILE_MAP_WRITE = 0x0002;

    [DllImport("Kernel32.dll", EntryPoint = "MapViewOfFile")]
    private static extern IntPtr MapViewOfFile(
     IntPtr hFileMappingObject,//HANDLE hFileMappingObject,
     UInt32 dwDesiredAccess,//DWORD dwDesiredAccess
     UInt32 dwFileOffsetHight,//DWORD dwFileOffsetHigh,
     UInt32 dwFileOffsetLow,//DWORD dwFileOffsetLow,
     UInt32 dwNumberOfBytesToMap//SIZE_T dwNumberOfBytesToMap
     );

    [DllImport("Kernel32.dll", EntryPoint = "UnmapViewOfFile")]
    private static extern int UnmapViewOfFile(IntPtr lpBaseAddress);

    [DllImport("Kernel32.dll", EntryPoint = "CloseHandle")]
    private static extern int CloseHandle(IntPtr hObject);

    [DllImport("Kernel32.dll", EntryPoint = "CreateSemaphoreA")]
    private static extern IntPtr CreateSemaphoreA(
        UInt32 lpSemaphoreAttributes, // SD
        UInt32 lInitialCount, // initial count
        UInt32 lMaximumCount, // maximum count
        string lpName// object name
    );

    [DllImport("Kernel32.dll", EntryPoint = "OpenSemaphoreA")]
    private static extern IntPtr OpenSemaphoreA(
        UInt32 dwDesiredAccess, // access 0x1F0003
        int bInheritHandle, // inheritance option
        string lpName // object name
    );

    [DllImport("Kernel32.dll", EntryPoint = "ReleaseSemaphore")]
    private static extern int ReleaseSemaphore(
        IntPtr hSemaphore,
        UInt32 lReleaseCount,
        Int32 lpPreviousCount
    );

    [DllImport("Kernel32.dll", EntryPoint = "WaitForSingleObject")]
    private static extern UInt32 WaitForSingleObject(
        IntPtr hHandle,
        UInt32 dwMilliseconds
    );

    private IntPtr handle;     //文件句柄
    private IntPtr addr;       //共享內(nèi)存地址

    IntPtr hMFCWrite;
    IntPtr hU3DRead;

    IntPtr hU3DWrite;
    IntPtr hMFCRead;

    uint mapLength;            //共享內(nèi)存長(zhǎng)

         //  Process pMFC;            //程序
         //  pMFC = Process.Start(Application.streamingAssetsPath + "\\MFC\\MFC_Client.exe");
         //  StartCoroutine(WaitToInit(0.5f));
  • 4.Unity數(shù)據(jù)讀取(注意,使用共享內(nèi)存時(shí)有些地方需要上鎖):

image.png
    //不安全的代碼在項(xiàng)目生成的選項(xiàng)中選中允許不安全代碼
    static unsafe void byteCopy(byte[] dst, IntPtr src)
    {
        fixed (byte* pDst = dst)
        {
            byte* pdst = pDst;
            byte* psrc = (byte*)src;
            while ((*pdst++ = *psrc++) != '\0')
                ;
        }
    }
  • 5.Unity數(shù)據(jù)發(fā)送

image.png
    static unsafe void Copy(byte[] byteSrc, IntPtr dst)
    {
        fixed (byte* pSrc = byteSrc)
        {
            byte* pDst = (byte*)dst;
            byte* psrc = pSrc;
            for (int i = 0; i < byteSrc.Length; i++)
            {
                *pDst = *psrc;
                pDst++;
                psrc++;
            }
        }
    }
  • 5.結(jié)束的時(shí)候要做點(diǎn)事

1.MFC
image.png

2.Unity

    void OnApplicationQuit()
    {
        if (sw != null)
        {
            sw.Close();
        }

        if (fs != null)
        {
            fs.Close();
        }

        if (isLocalTest)
        {
            return;
        }


        ReleaseSemaphore(hU3DRead, 1, 0);   //不調(diào)這一句的話桃笙,關(guān)閉unity時(shí)會(huì)卡死

        //清空內(nèi)存
        byte[] sendStr = Encoding.Default.GetBytes("" + '\0');
        //如果要是超長(zhǎng)的話氏堤,應(yīng)另外處理,最好是分配足夠的內(nèi)存
        if (sendStr.Length < mapLength)
        {
            Copy(sendStr, addr);
        }

        //關(guān)閉線程
        if (threadRead != null)
        {
            threadRead.Interrupt();
            threadRead.Abort();
        }

        //關(guān)閉MFC進(jìn)程
        if (pMFC != null)
        {
            pMFC.Kill();
        }

        //UnityEngine.Debug.Log("關(guān)閉U3D");

        if (addr != null)
        {
            UnmapViewOfFile(addr);
        }

        if (handle != null)
        {
            CloseHandle(handle);
        }

        if (hU3DWrite != null)
        {
            CloseHandle(hU3DWrite);
        }

        if (hMFCRead != null)
        {
            CloseHandle(hMFCRead);
        }

        if (hMFCWrite != null)
        {
            CloseHandle(hMFCWrite);
        }

        if (hU3DRead != null)
        {
            CloseHandle(hU3DRead);
        }
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末搏明,一起剝皮案震驚了整個(gè)濱河市鼠锈,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌星著,老刑警劉巖购笆,帶你破解...
    沈念sama閱讀 212,383評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異虚循,居然都是意外死亡由桌,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門邮丰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人铭乾,你說(shuō)我怎么就攤上這事剪廉。” “怎么了炕檩?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,852評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵斗蒋,是天一觀的道長(zhǎng)捌斧。 經(jīng)常有香客問(wèn)我,道長(zhǎng)泉沾,這世上最難降的妖魔是什么捞蚂? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,621評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮跷究,結(jié)果婚禮上姓迅,老公的妹妹穿的比我還像新娘。我一直安慰自己俊马,他們只是感情好丁存,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著柴我,像睡著了一般解寝。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上艘儒,一...
    開(kāi)封第一講書(shū)人閱讀 49,929評(píng)論 1 290
  • 那天聋伦,我揣著相機(jī)與錄音,去河邊找鬼界睁。 笑死觉增,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的晕窑。 我是一名探鬼主播抑片,決...
    沈念sama閱讀 39,076評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼杨赤!你這毒婦竟也來(lái)了敞斋?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,803評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤疾牲,失蹤者是張志新(化名)和其女友劉穎植捎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體阳柔,經(jīng)...
    沈念sama閱讀 44,265評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡焰枢,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了舌剂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片济锄。...
    茶點(diǎn)故事閱讀 38,716評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖霍转,靈堂內(nèi)的尸體忽然破棺而出荐绝,到底是詐尸還是另有隱情,我是刑警寧澤避消,帶...
    沈念sama閱讀 34,395評(píng)論 4 333
  • 正文 年R本政府宣布低滩,位于F島的核電站召夹,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏恕沫。R本人自食惡果不足惜监憎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評(píng)論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望婶溯。 院中可真熱鬧鲸阔,春花似錦、人聲如沸爬虱。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,798評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)跑筝。三九已至死讹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間曲梗,已是汗流浹背赞警。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,027評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留虏两,地道東北人愧旦。 一個(gè)月前我還...
    沈念sama閱讀 46,488評(píng)論 2 361
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像定罢,于是被迫代替她去往敵國(guó)和親笤虫。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒(méi)有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,093評(píng)論 1 32
  • 一祖凫、溫故而知新 1. 內(nèi)存不夠怎么辦 內(nèi)存簡(jiǎn)單分配策略的問(wèn)題地址空間不隔離內(nèi)存使用效率低程序運(yùn)行的地址不確定 關(guān)于...
    SeanCST閱讀 7,784評(píng)論 0 27
  • 轉(zhuǎn)載自VR設(shè)計(jì)云課堂[http://www.reibang.com/u/c7ffdc4b379e]Unity S...
    水月凡閱讀 1,009評(píng)論 0 0
  • 最近網(wǎng)友通過(guò)網(wǎng)站搜索Unity3D在手機(jī)及其他平臺(tái)下占用內(nèi)存太大. 這里寫下關(guān)于unity3d對(duì)于內(nèi)存的管理與優(yōu)化...
    楊樹(shù)葉的楊閱讀 1,069評(píng)論 0 0
  • 文 大冰 是哦琼蚯,你我皆凡人,哪兒來(lái)的那么多永遠(yuǎn)惠况,比肩過(guò)后往往是擦肩遭庶。 該來(lái)的該去的總會(huì)如約發(fā)生,就像閃電消失后是傾...
    vivo王大益閱讀 307評(píng)論 0 0