2010-12-22 89 views
2

目前我有一個客戶端進程和一個服務器進程。客戶端進程需要每隔一段時間聯繫服務器進程以交換數據,但需要知道服務器的pid才能這樣做。客戶應該如何知道如何做到這一點?我想避免重複的硬盤訪問。此應用程序僅在Linux下運行。目前,服務器通過其存在的pid或RAM磁盤來設置鎖定文件。客戶端檢查文件。我還能如何有效地完成此事務,以便服務器可以向客戶端發送信號? (注:客戶端是PHP,服務器C)簡單的Linux IPC問題

+0

正如其他人所建議的,我正在錯誤地處理這個問題,但是:一個方便的方法來完成我當時想做的事情(優化重複的文件系統訪問)是否存在!它是通常安裝在/ dev/shm上的tmpfs文件系統。它可能不是100%可移植的,但它似乎是相當標準的。 – conartist6 2011-02-07 19:37:24

回答

3

一些想法:

  1. 什麼都不做;如果您反覆閱讀它,則讀取光盤文件(在適當的永久光盤上)不會導致任何IO,因爲該文件已經在緩存中。
  2. 重構你的系統,所以你不需要知道pid文件
  3. 你確定你真的在乎嗎?過早優化和所有這一切。你每秒鐘做多少次,1000次或更多?
1

一些其他的選項包括:

  1. 設置服務器偵聽特定端口上。
  2. 服務器可以設置一個命名管道,客戶端可以通過它進行通信。
+0

所以......沒有人回答我的問題。我的問題不完全是關於IPC。它關於IPC的同步。我已經通過命名管道與客戶端和服務器進行通信。問題是服務器應該如何知道何時收聽管道。現在,這是通過信號完成的(因此知道服務器的pid並將其保留在重複訪問信息不會垃圾郵件讀取的地方)。你是說,而不是試圖同步服務器應該只是聽管道上的客戶端通信,只要它沒有做別的事情? – conartist6 2010-12-23 02:06:55

3

我認爲,當你說 「過程」,這兩個是同一臺機器上?如果是這樣,您可以在/tmp目錄中使用指定的FIFO。這是使用IPC與指定FIFO /tmp/test.fifofork()兩個過程的一個例子:

#include <stdio.h> 
#include <string.h> 
#include <errno.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <linux/stat.h> 

int errno; 

int main(int argc, char** argv) 
{ 
    char fifo_path[] = "/tmp/test.fifo"; 
    char buffer[128]; 

    int result = mkfifo(fifo_path, 0600); 

    printf("mkfifo result = %d\n", result); 

    if (errno == EEXIST) 
     printf("errno == EEXIST\n"); 

    pid_t child = fork(); 

    if (child == 0) 
    { 
     printf("%d> child; opening fifo \"%s\" for writing\n", getpid(), 
       fifo_path); 

     FILE* fifo = fopen(fifo_path, "w"); 
     char in_buffer[128]; 

     fgets(in_buffer, 128, stdin); 

     fputs(in_buffer, fifo); 

     fclose(fifo); 
    } 
    else 
    { 
     printf("%d> parent; opening fifo \"%s\" for reading\n", getpid(), 
       fifo_path); 

     FILE* fifo = fopen(fifo_path, "r"); 

     fgets(buffer, 128, fifo); 

     if (buffer[0] == EOF) 
      printf("%d> got EOF\n", getpid()); 
     else 
     { 
      buffer[strlen(buffer) - 1] = 0; 
      printf("%d> read string \"%s\"\n", getpid(), buffer); 
     } 

     fclose(fifo); 
    } 

    return 0; 
} 

所以只要這兩個進程知道FIFO的完整路徑,就可以讀取和寫入。

+0

這是我已經有的,但問題是同步。目前我的設置是讓客戶端信號服務器準備好進行事務處理,然後事務發生在服務器的信號處理函數中。它如何知道將信號發送到哪個pid? – conartist6 2010-12-23 02:02:16

+0

你不需要知道PID;你只需要知道客戶端是否正在讀取FIFO。有一種方法可以做到這一點;雖然我不確定。我相信服務器在寫入FIFO之前會阻塞,直到它被打開以供讀取。您可以使用某些參數來創建FIFO,這意味着服務器不會阻塞,但是如果沒有從中讀取,服務器將收到SIGPIPE信號。我希望這有幫助。 – Doddy 2010-12-26 18:08:52

2

通常情況下,您不使用pid,而是使用某種類型的地址 - IP地址(包括端口),Unix域套接字地址,文件系統中的路徑,或者構建於其上的一些更高級別的IPC系統其中一個(D-Bus,X等)可以與服務器進行通信並進行通信。這個pid唯一有用的是發送一個信號,這可能是一種非常糟糕的通信方式,如果將客戶機和服務器劃分爲不同的權限域,則該信號將不起作用。

0

我想你可以在non_blocking模式下使用名稱IPC消息隊列。我不知道命名管道是否支持non_blocking模式,但如果它是那麼你也可以使用它。在non_block模式下,您只需註冊隊列描述符來發信號並進入一般等待狀態。如果隊列上有任何活動,你的進程將會醒來。請通過互聯網進行一些搜索,你可以找到許多相同的例子。

爲了給出正確的答案,我應該知道你的服務器進程的設計。