【问题标题】:using fork() to make 4 processes?使用 fork() 进行 4 个进程?
【发布时间】:2013-07-25 22:52:06
【问题描述】:

我们最近在我的应用操作系统设计课程中被介绍了 fork(),但我不是很了解它。我们需要使用它在 C 文件中创建四个独立的进程,然后让其中三个进程写入一个命名管道,而第四个从它读取。

这是我目前尝试过的代码:

// creating the named pipe
mknod("/tmp/namedpipe", S_IFIFO | 0600, 0);
int myPipe;

const char* colour;

pid_t p1, p2;

p1 = fork();
if (p1 < 0)
{
   printf("Fork failed\n");
}
else if (p1 == 0) // this is the child of p1, we'll call it "red"
{
   printf("\nPid %d %s", getpid(), "(red) started\n");
   myPipe = open("/tmp/namedpipe", O_WRONLY);
   colour = "RED\n";
   write(myPipe, colour, strlen(colour) +1);
   close(myPipe);
}
else // the is the parent of p1, we'll call it "green"
{
   printf("\nPid %d %s", getpid(), "(red) started\n");
   myPipe = open("/tmp/namedpipe", O_WRONLY);
   colour = "RED\n";
   write(myPipe, colour, strlen(colour) +1);
   close(myPipe);

   p2 = fork();
   if (p2 < 0)
   {
      printf("Fork failed\n");
   }
   else if (p2 == 0) // this is the child of p2, we'll call it "blue"
   {
      printf("\nPid %d %s", getpid(), "(blue) started\n");
      myPipe = open("/tmp/namedpipe", O_WRONLY);
      colour = "BLU\n";
      write(myPipe, colour, strlen(colour) +1);
      close(myPipe);
   }
   else // the is the parent of p2, we'll call it "reader"
   {
      printf("This is the reader process");
      myPipe = open("/tmp/namedpipe", O_RDONLY);
      char nextChar;
      while (read(myPipe, &nextChar, 1) == 1)
         printf("%c", nextChar);
      close(myPipe);
   }
}

如果您注释掉所有与管道相关的语句,此代码似乎可以正常工作,但否则它会执行前两个打印语句然后挂起,强制使用 CTRL-C。我不确定问题是否出在分叉上,或者是否与我在管道中写入和读取的方式有关。请告诉我。

【问题讨论】:

    标签: c fork named-pipes


    【解决方案1】:

    在没有O_NONBLOCK 的情况下打开的命名管道在进程之间同步。如果一个进程试图打开以进行写入,它将阻塞,直到其他进程尝试打开以进行读取。如果顺序颠倒,则读取进程被阻塞,直到写入进程尝试打开。无论哪种方式,两个打开都同时成功。

    在您的程序中,您创建了一个尝试打开以进行写入的子进程“red”,以及一个也尝试打开以进行写入的父进程“green”。还没有人在读,所以两个都被屏蔽了。没有达到将创建其他 2 个进程的代码,因为它是在阻塞它的“绿色”进程中打开之后出现的。

    【讨论】:

      【解决方案2】:

      您打开管道进行写入。这将阻塞,直到打开管道进行读取。 由于父母不会分叉更多的孩子,这一切都停止了。

      我无法访问 Unix 平台,所以我没有尝试编译它,但您可以尝试 这样的东西:

      // creating the named pipe
      #define CHILD_COUNT 3
      mknod("/tmp/namedpipe", S_IFIFO | 0600, 0);
      const char* childname[CHILD_COUNT] = { "Red", "Blue", "Yellow" };
      const char* colorname[CHILD_COUNT] = { "RED\n", "BLUE\n", "YELLOW\n" };
      int myPipe;
      
      const char* colour;
      
      pid_t p;
      int i;
      for (i=0; i<CHILD_COUNT; i++) 
      {
        p = fork();
        if (p < 0) {
          printf("Fork failed\n");
        }
        else if (p == 0) // this is a child, do child stuff
        {
          printf("\nPid %d (%s) started\n", getpid(), childname[i]");
          myPipe = open("/tmp/namedpipe", O_WRONLY);
          colour = colorname[i]; // =="RED\n" for first child
          write(myPipe, colour, strlen(colour) +1);
          close(myPipe);
          return;
        }
        // else it's the parent, spawn more children
      }
      
      // Parent
      printf("This is the reader process");
      myPipe = open("/tmp/namedpipe", O_RDONLY);
      char nextChar;
      while (read(myPipe, &nextChar, 1) == 1)
          printf("%c", nextChar);
      close(myPipe);
      

      【讨论】:

      • 谢谢,我尝试使用您的代码,但在 for 循环中出现错误:error: ‘for’ loop initial declarations are only allowed in C99 mode test.c:24:2: note: use option -std=c99 or -std=gnu99 to compile your code 不确定这是什么意思
      • 因为有(int i=0; i&lt;CHILD_COUNT; i++)。使用 -std=c99 选项编译代码或将 i 的声明移到代码的开头:例如 int myPipe, i;
      猜你喜欢
      • 2019-03-25
      • 2017-06-27
      • 1970-01-01
      • 2014-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-06
      相关资源
      最近更新 更多