[英]Forks and Pipes in C UNIX
我不確定我是不是在這里咆哮着正確的樹......但是這里有。
我正在嘗試將數據從父進程傳遞給所有子進程。 這是一個簡單的服務器程序,基本上將保留連接的客戶端列表,然后將連接的客戶端的路由表發送到每個客戶端。 這最終將包括關於每個客戶端的信息結構......但是現在我只想讓每個分叉進程從父進程獲得相同的信息。
在父進程中,首先我設置我的管道並將它們設置為非阻塞(當管道中沒有任何新數據時)。 與客戶端建立連接后,將增加條目數變量以反映此新連接。 然后我將子進程分叉到一個新函數並用新的表條目數更新我的管道數組(我現在有10個管道,看看我是否需要為每個子進程保留一個單獨的管道)。
pid_t pid;
int numchildren;
int i, n;
/* Create the pipes. */
for(i = 0; i < 10; i++)
{
if (pipe (mypipe[i]))
{
fprintf (stderr, "Pipe failed.\n");
return EXIT_FAILURE;
}
}
for(i = 0; i < 10; i++)
{
for(n=0; n<2; n++)
{
// Get previous flags
int f = fcntl(mypipe[i][n], F_GETFL, 0);
// Set bit for non-blocking flag
f |= O_NONBLOCK;
// Change flags on fd
fcntl(mypipe[i][n], F_SETFL, f);
}
//close(mypipe[i][0]);
}
pid = fork();
if (pid == (pid_t) 0)
{
close (mypipe[numentries-1][1]);
recievecmds(new_fd, mypipe[numentries-1][0]);
close(new_fd);
return EXIT_SUCCESS;
}
else if (pid < (pid_t) 0)
{
fprintf (stderr, "Fork failed.\n");
return EXIT_FAILURE;
}
else
{
sprintf (buf,"%d",numentries);
for(i = 0; i < 10; i++)
write(mypipe[i][1], buf, strlen(buf));
memset(&buf, 0, sizeof buf);
}
然后我嘗試在recievecmds()函數中讀取管道中的內容:
nbytes = read(mypipe[childindex][0], buf, sizeof(buf));
連接的第一個客戶端告訴我numentries = 1,第二個客戶端告訴我numentries = 2,依此類推。 我的意思是我真的甚至沒有看到管道的重點,因為看起來無論我放入管道,我都可以在我調用叉子的函數中傳遞它。 我是以錯誤的方式來做這件事的嗎? 試圖解決這個問題一直非常令人沮喪。 如何從父進程中同時更新所有子進程?
非常感謝你提前。
編輯 - 我的主要問題是我每次在無限循環中重新聲明管道。 非常愚蠢的錯誤,立刻意識到這可能是我問題的根源。 但是,現在第一個子/管道組合包含正確的數據......第二個不包含正確的數據。 我會看看我是否可以自己解決這個問題,謝謝你的建議!
當然,現在我遇到了問題,因為我手動選擇一個選項來從管道中獲取數據。 我將不得不想辦法在每次更新時獲取所有管道的數據,或者確保只獲取最新數據(可能一次只有一個字符)。
謝謝你忍住我們! 我為不發布整個程序而道歉......但是有很多。 我絕對應該提到我在無限循環中擁有它。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
enum { NUM_CHILDREN = 10 };
enum { NUM_MESSAGES = 10 };
static int write_pipes[NUM_CHILDREN];
static int n_pipes;
static void be_childish(int *pipe)
{
int i;
char buffer[32];
int nbytes;
int pid = getpid();
close(pipe[1]);
for (i = 0; i < n_pipes; i++)
close(write_pipes[i]);
printf("Child %d\n", pid);
while ((nbytes = read(pipe[0], buffer, sizeof(buffer))) > 0)
{
printf("Child %d: %d %.*s\n", pid, nbytes, nbytes, buffer);
fflush(0);
}
printf("Child %d: finished\n", pid);
exit(0);
}
int main(void)
{
pid_t pid;
int i, j;
/* Create the pipes and the children. */
for (i = 0; i < NUM_CHILDREN; i++)
{
int new_pipe[2];
if (pipe(new_pipe))
{
int errnum = errno;
fprintf(stderr, "Pipe failed (%d: %s)\n", errnum, strerror(errnum));
return EXIT_FAILURE;
}
if ((pid = fork()) < 0)
{
int errnum = errno;
fprintf(stderr, "Fork failed (%d: %s)\n", errnum, strerror(errnum));
return EXIT_FAILURE;
}
else if (pid == 0)
{
be_childish(new_pipe);
}
else
{
close(new_pipe[0]);
write_pipes[n_pipes++] = new_pipe[1];
}
}
for (i = 0; i < NUM_MESSAGES; i++)
{
char message[30];
int len;
snprintf(message, sizeof(message), "Message %d", i);
len = strlen(message);
for (j = 0; j < n_pipes; j++)
{
if (write(write_pipes[j], message, len) != len)
{
/* Inferior error handling; first failure causes termination */
fprintf(stderr, "Write failed (child %d)\n", j);
exit(1);
}
}
sleep(1);
}
printf("Parent complete\n");
return 0;
}
我建議使用共享內存段。 您的父進程和子進程可以對同一文件進行mmap,並對其進行讀/寫狀態。 這可以是實際文件,也可以是匿名內存段。 這正是Apache用ScoreBoardFile做的事情。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.