簡體   English   中英

C應用程序和Python之間的IPC

[英]IPC between C application and Python

所以我對IPC比較新,我有收集數據的ac程序和分析數據的python程序。 我希望能夠:

  1. 將python程序作為我的主要c程序的子進程調用
  2. 將包含要處理的數據的ac結構傳遞給python進程
  3. 將python進程中的int值返回給c程序

我一直在簡單地查看Pipes和FIFO,但到目前為止找不到任何信息來解決這類問題,因為據我所知,fork()例如只會復制調用進程,所以不是我想要的,因為我我試圖打電話給另一個過程。

關於fork()和執行不同進程的需要。 fork()確實創建了當前進程的副本。 但這通常與exec() (各種形式之一)相結合,以使進程副本執行不同的程序。

至於IPC ,你有幾個選擇。 有人提到了一個隊列 - 但像ZeroMQ這樣的東西太過分了。 您可以使用多種機制之一進行IPC

  1. 管道 (命名管道或匿名)
  2. Unix域套接字
  3. TCPUDP通過套接字API
  4. 共享內存
  5. 消息隊列

pipe方法最簡單。 請注意,當您在C程序和Python之間來回傳遞數據時,您需要擔心數據的傳輸語法。 如果選擇使用C結構(可以是非可移植的),則需要在Python端解包數據。 否則你可以使用一些文本格式 - sprintf / sscanfJSON等的組合。

我建議查看應用程序並構建您遇到的問題。

多線程

到目前為止,啟動兩個流程並不是最大的問題,因為Ziffusion說你可以讓另一個流程做其他事情。 另外還有用於C的python綁定,因此您可以創建另一個線程(例如,不需要它是一個進程)並從C程序調用您的python例程。

通訊

共享信息更有趣,因為您必須解決兩個問題:一個是從技術上將數據從一個地方轉移到另一個地方而反之亦然; 另一個是兩個不同的東西如何對同一數據起作用。 這涉及消息傳遞模式和流程:

  • 誰生成數據?
  • 誰收到數據?
  • 在繼續之前是否有一段代碼等待某事?
  • 在處理數據時是否需要控制數據發生的變化?
  • 我想自己編碼嗎?
  • 我可以在項目中使用庫嗎?
  • 有安全限制嗎?
  • ...

回答上述問題后,您可以定義應用程序的各個部分的交互方式。 一個主要區別是同步與異步。

同步與異步

同步意味着對於每個消息都有一個應答,該應答應包含在有限(通常盡可能小)的大小的時間包絡中。 這是為了避免延遲。 當您必須精確控制正在發生的事情時,或者您需要及時回答 問題時 ,最好使用這種模式。 事實上,http是如何下載網頁的:無論何時加載網站,您都希望立即看到內容。 這是一種名為REQ uest / REP ly的模式

異步通常用於繁重處理:數據生成器(例如數據庫接口或傳感器)將大量數據發送到工作線程,而無需等待答案。 然后,工作線程開始對數據執行任務,完成后將結果發送到數據接收器/用戶。 這種模式稱為PUB lish / SUB scribe。

還有很多其他的,但這些構成了溝通的基礎。

編組

您面臨的另一個問題是如何構建數據傳遞,編組。 如何將數據的含義和內容從一個上下文轉換為完全不同的上下文。 例如,從你的C部分到你的Python部分。 維護序列化庫是繁瑣且危險的,更不用說容易出現向后兼容性問題。

履行

當您實現時,您通常需要最干凈,最強大的代碼。 這兩件事顯然是相互對立的。 所以我通常會去尋找能夠完全滿足我需要的庫。 在這種情況下,我的建議是嘗試ZeroMQ:它很薄,靈活,低級。 它將為您提供一個強大的框架來連接線程,進程甚至機器。 ZeroMQ提供鏈接,但您仍需要通過此鏈接運行協議。 為了避免令人難以置信的麻煩並簡化您關於編組問題的工作,我建議您調查可用的編組庫,以簡化此任務。 Cap'n protoFlatbuffers ,協議緩沖區(Google,還不能發布超過2個鏈接)它們可以很容易地用中間語言定義數據,並用任何其他語言解析它而無需編寫所有類你自己。

至於管道和共享記憶,我的拙見是:忘記它們的存在。

您組織架構的方式有點混亂。 你真正想要的是消息隊列 所以在你的例子中:

  • 您的python worker偵聽要在隊列A中處理的新信息;
  • 你的C程序在隊列A中輸入數據;
  • 你的python worker處理數據並將結果排隊到隊列B中;
  • 您的C程序偵聽隊列B上的新項目;

這可能會有所不同,但概念很簡單。

它們易於實現,並且有大量的庫和工具可以幫助您完成此任務。 ZeroMQ肯定會為你做的。 它適用於C和Python。

如果你的結構足夠簡單,你根本就不能使用IPC。 前提是,您可以序列化為可用作程序參數的字符串參數,並提供返回的int值可以在0-127范圍內,您可以簡單地:

  • 在C代碼中:

    • 准備命令參數以傳遞給Python腳本
    • fork-exec(假設類Unix系統)是一個帶有腳本路徑和腳本參數的Python解釋器
    • 等孩子終止
    • 讀取腳本作為代碼終止傳遞的內容
  • 在Python中:

    • 從命令行獲取參數並重建結構的元素
    • 處理它
    • 使用exit(n)結束腳本,其中n是0-127范圍內的整數,將返回給調用者。

如果以上不符合您的要求,下一級將是使用管道:

  • 在C代碼中:

    • 准備2個管道對,一個用於C-> Python(讓我們稱之為輸入),一個用於Python-> C(讓我們稱之為輸出)
    • 將結構序列化為char緩沖區
    • 叉子
    • 在孩子
      • 關閉輸入管道的寫入側
      • 關閉輸出管道的讀取側
      • dup讀取輸入管道的一側到文件描述符0(stdin)(參見`dup2)
      • dup輸出管道寫入文件描述符1(stdout)
      • 執行帶有腳本名稱的Python解釋器
    • 在父母
      • 關閉輸入管的讀取側
      • 關閉輸出管道的寫側
      • 在輸入文件的寫入端寫入緩沖區(最后以其大小,如果不能先驗地知道)
      • 等孩子終止
      • 從輸出管道的讀取端讀取返回值
  • 在Python中:

    • 從標准輸入讀取序列化數據
    • 處理它
    • 將輸出整數寫入標准輸出
    • 出口

暫無
暫無

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

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