簡體   English   中英

多個子進程在同一個管道上讀/寫

[英]Multiple child processes reading/writing on the same pipe

我目前正在Linux環境中學習使用C的套接字編程。 作為一個項目,我試圖編寫一個基本的聊天服務器和客戶端。

目的是讓服務器為每個連接的客戶端分叉一個進程。

我遇到的問題是在一個孩子中讀取數據並將其寫入所有連接的客戶端。

我試圖通過循環調用select等待數據到達套接字或讀取管道末端的子進程來完成此操作。 如果它到達套接字的想法是它寫入管道的寫端,這導致select返回管道的讀端,准備好讀取。

由於此管道在所有子項之間共享,因此每個子項都應讀取管道上的數據。 這不起作用,因為它看起來不是每個子進程同時讀取的數據管道以及在調用中“錯過”數據塊的子進程。

以下是子進程中執行此操作的代碼:

for( ; ; )
{
  rset = mset;
  if(select(maxfd+1, &rset, NULL, NULL, NULL) > 0)
  {
    if(FD_ISSET(clientfd, &rset))
    {
      read(clientfd, buf, sizeof(buf));
      write(pipes[1], buf, strlen(buf));
    }
    if(FD_ISSET(pipes[0], &rset))
    {
      read(pipes[0], buf, sizeof(buf));
      write(clientfd, buf, sizeof(buf));
    }
  }
}

我假設我目前使用的方法根本不起作用。 是否可以通過IPC將從客戶端收到的消息寫入所有其他連接的客戶端?

謝謝

為了解決孩子從管道中讀取的數據超出應有的數據(並且反過來讓另一個孩子“試圖從空管道中讀取”),你應該考慮使用POSIX消息隊列或者父節點和單個子進程之間的單個管道進程而不是單個全局管道在父進程和子進程之間進行通信。 就目前而言,當服務器寫入管道與其子進程通信時,由於操作系統對進程的調度是不確定的,因此無法確切地控制在任何給定時間從管道中讀取哪個子進程。 。 換句話說,如果沒有某種類型的同步機制或讀/寫障礙,如果服務器寫入管道,則代碼中沒有任何內容阻止一個孩子“跳過”讀取,而第二個孩子不進行雙讀留下另一個應該從服務器上獲取廣播數據的孩子,因此被阻止了。

解決這個問題的一個簡單方法可能是在父級和單個子級之間共享一個私有管道。 因此,在服務器中,子進程可以從客戶端讀取,將該數據發送回父進程,然后父進程可以使用為所有子進程累積的整個管道描述符列表,回寫每個子進程廣播消息然后被發送回每個客戶端。 沒有孩子會被“飢餓”的數據,因為沒有可能被另一個子進程雙重閱讀。 每個管道上只有一個讀寫器,通信是確定的。

如果您不想為服務器的父進程中的每個子進程處理多個管道,則可以使用POSIX消息隊列(在mqueue.h找到)使用全局消息隊列。 有了這種方法,如果一個孩子抓起一條消息,它不是想擁有(即,你可能需要通過圍繞struct包含某種類型的ID值),這將使該消息放回隊列,並嘗試讀取另一消息...這不像直接管道方法那樣快速有效,但是它可以讓你回寫一個沒有為當前孩子指定的消息,而沒有使用全局管道發生的交錯復雜性或FIFO機制。

寫入管道的每個數據字節將只讀取一次。 在管道的讀取端打開的情況下,它不會復制到每個進程。

如果要將數據復制到多個目標進程,則必須顯式復制數據。 例如,您可以擁有一個“主”進程,該進程具有進出每個“從屬”進程的管道。 當一個從站想要向其他從站廣播一條消息時,它會將它發送給主進程,該進程循環並將其寫入到每個管道中,然后寫入其他從站。

暫無
暫無

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

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