命名管道,使用 Fork()

Posted

技术标签:

【中文标题】命名管道,使用 Fork()【英文标题】:Named Pipes, using Fork() 【发布时间】:2016-04-29 05:29:42 【问题描述】:

我遇到了一个很大的问题。因此,对于我的任务,我必须使用命名管道 (FIFO) 并使用 Fork()。我有三个程序,lab6(这是我的主要/父母/打印答案)然后我有我的生命支持(这是一个孩子)然后我有我的导航(这也是一个孩子)。两个孩子必须写信给父母,父母会阅读并打印出来。真的很难解释答案应该如何。它很复杂,但我的数学是正确的,我只是在尝试将此文件移动到单独的 FIFO 文件时遇到问题。我收到分段错误错误。所以我的问题是我做错了什么?我正在尝试将此代码转换为 FIFO。 p.s.不要担心任何时间或种子生成器或类似的东西。我只需要导航来计算它的部分并将其发送给父母,生命支持也是如此,但我似乎无法让 FIFO 工作。

主文件-

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

 #define FIFO_FILE "MYFIFO"         //default is current directory


 void getTime();
 void writeToMain( char *, int );
 void lifeSupport();
  void navigation();
 int generate(int);
  void countdown( int );

 //Global Variables
  const int MAX_LINE = 80;
  int ret, myPipes[2];
   char *message;

 int time_;
  char myClock[25];

 //Pipe variables
  int totalTime = 0;
  char toSend[120];



int main(void)

    FILE *fpoint;
    char readbuffer[80];
    int again = 1;


    mknod(FIFO_FILE, S_IFIFO | 0666, 0);

    while(again)

    fpoint = fopen(FIFO_FILE, "r");
    fgets(readbuffer, 80, fpoint);
    printf("recevived string: %s\n, readbuffer");
    fclose(fpoint);
    if(strcmp(readbuffer, "stop") == 0 ) again = 0;

    return(0);

            


              if( ret == 0 )
            if(fork() == 0)

                    while (repeat)

                            totalTime = 0;
                             getTime();
                            lifeSupport();
                            navigation();

                            getTime();
                            sprintf(toSend, "[ %s ] \tSleep \t\t[ %d  second(s) ]\n", myClock, 30 - totalTime);
                            write( myPipes[PipeStdOut], toSend, strlen(toSend) + 1 );

                            sleep(30 - totalTime);
                    
            

            else

                    while(again)
                    read( myPipes[PipeStdIn], buffer, MAX_LINE);
                    again = strcmp(buffer, "Stop");


                    if (again == 0) ;
                            else
                                printf("%s \n", buffer);
                     

            
         //exit main

儿童(生命支持)-

       #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<unistd.h>
    #include<sys/stat.h>
    #include<linux/stat.h>
    #define FIFO_FILE "MYFIFO"



    void getTime();
    void writeToMain( char *, int );
    void lifeSupport();
    void navigation();
    int generate(int);
    void countdown( int );

    void lifeSupport()
            getTime();
            message = "Beginning life support systems \t";
            sprintf(toSend, "[ %s ] %s ", myClock, message);
            write( myPipes[PipeStdOut], toSend, strlen(toSend) + 1 );
            sleep(1);
            totalTime ++;

            getTime();
            time_ = generate(5);
            message = "Adjusting breathing gas levels";
            sprintf(toSend, "[ %s ] %s  \t[ %d Second(s) ]", myClock, message, time_);
            write( myPipes[PipeStdOut], toSend, strlen(toSend) + 1 );
            sleep(time_);
      totalTime += time_;

             getTime();
            time_ = generate(3);
            message = "Adjusting environment";
            sprintf(toSend, "[ %s ] %s  \t\t[ %d Second(s) ]", myClock, message, time_);
            write( myPipes[PipeStdOut], toSend, strlen(toSend) + 1 );
            sleep(time_);
            totalTime += time_;

            getTime();
            message = "Done. Life support adjusted. \t[ 1 Second(s) ]";
            sprintf(toSend, "[ %s ] %s ", myClock, message);
            write( myPipes[PipeStdOut], toSend, strlen(toSend) + 1 );
            sleep(1);
            totalTime ++;

             getTime();
            message = "\t\tExecution time";
            sprintf(toSend, "%s [ %d Second(s) ]\n", message, (totalTime - 1));
    write( myPipes[PipeStdOut], toSend, strlen(toSend) + 1 );
    sleep(1);
    totalTime ++;


            FILE *fpoint;
            int again =1;
            char strIn[80] = "Use message from command line";

            if(argc !=2)
         printf("USAGE: NamedPipeClient[string]\n");
                    exit(1);
                    

            while(again == 1)

            if((fpoint = fopen (FIFO_FILE, "w")) == NULL)
                    perror("fopen");
                    exit(1);

            if((fpoint = fopen(FIFO_FILE, "w")) == NULL)
                    perror("fopen");
                    exit(1);
                            
                    
            

和最后一个孩子(导航。记住两个孩子都写信给父母)-

       #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<unistd.h>
    #include<sys/stat.h>
    #include<linux/stat.h>
    #define FIFO_FILE "MYFIFO"


    void getTime();
    void writeToMain( char *, int );
    void lifeSupport();
    void navigation();
    int generate(int);
    void countdown( int );

    void navigation()
    getTime();
    message = "Beginning navigation systems";
    sprintf(toSend, "[ %s ] %s \t[ 1 Second(s) ]", myClock, message);
    write( myPipes[PipeStdOut], toSend, strlen(toSend) + 1 );
    sleep(1);
    totalTime ++;

    getTime();
    time_ = generate(6);
    message = "Adjusting navigation systems";
    sprintf(toSend, "[ %s ] %s  \t[ %d Second(s) ]", myClock, message, time_);
    write( myPipes[PipeStdOut], toSend, strlen(toSend) + 1 );
    sleep(time_);
    totalTime += time_;
           getTime();
    message = "Done. Navigation systems adjusted \t[ 1 Second(s) ]";
    sprintf(toSend, "[ %s ] %s ", myClock, message);
    write( myPipes[PipeStdOut], toSend, strlen(toSend) + 1 );
    sleep(1);
    totalTime ++;

    message = "\t\tExecution time";
    sprintf(toSend, "%s  [ %d Second(s) ]", message, (totalTime - 2));
    write( myPipes[PipeStdOut], toSend, strlen(toSend) + 1 );
    sleep(1);
    totalTime += 2;

    getTime();
    message = "\tTotal time";
    sprintf(toSend, "[ %s ] %s \t[ %d Second(s) ]",  myClock, message, totalTime);
    write( myPipes[PipeStdOut], toSend, strlen(toSend) + 1 );
    sleep(1);



            while(again == 1)

            if((fpoint = fopen (FIFO_FILE, "w")) == NULL)
                    perror("fopen");
                    exit(1);
            

            if((fpoint = fopen(FIFO_FILE, "w")) == NULL)
                 perror("fopen");
                    exit(1);
            
    
            fputs(strIn,fpoint);
            fclose(fpoint);

    return(0);
    

我知道这很多,任何帮助都非常有用。如果这太过分了,我会尊重规则并删除除此之外的问题,我认为这将是一个不错的挑战。哈哈 提前致谢!

【问题讨论】:

您确实检查了fopen()fclose() 的返回值。为什么不对其他 ffunctions 这样做? 什么意思? @tofro 1.在从 FIFO 的主要读取中不检查 fgets() 的返回值。 2. 没有任何东西写入lifeSupport 中的 FIFO(不明白为什么要包含它,FIFO 只是打开了,没有做任何事情),3. 没有检查 @987654329 中的返回值@写入@987654330 中的 FIFO @-如果不检查,你怎么想知道发生了什么问题? 【参考方案1】:

您似乎试图尽可能地向我们隐瞒您的问题。您的程序示例不是最小的 - 它归结为(主要)

int main (void)

   mknod(FIFO_FILE, S_IFIFO | 0666, 0);

   while(again)

      fpoint = fopen(FIFO_FILE, "r");
      fgets(readbuffer, 80, fpoint);
      printf("recevived string: %s\n, readbuffer");
      fclose(fpoint);

      // All the fork() stuff follows here
      ....
   

您创建 FIFO,打开它并从中读取(无需检查您是否真的得到了一些东西)。当您的子进程实际上会执行此操作时甚至还没有启动时,您希望谁在其中放置一些东西?

由于您不检查 fgets() 的返回值,您将在未初始化的缓冲区 (readbuffer) 上工作,因此破坏开始了。

即使如果你有一些外部的东西神奇地写入 FIFO,你需要检查 fgets() 的返回值,尤其是在多进程环境中 - 你不能只需假设其他进程在您阅读时已经写了一些东西。

【讨论】:

以上是关于命名管道,使用 Fork()的主要内容,如果未能解决你的问题,请参考以下文章

IPC - 命名管道(fifo)- 使用

IPC - 命名管道(fifo)- 使用

IPC - 命名管道(fifo)- 使用

IPC - 命名管道(fifo)- 使用

管道和命名管道

进程间通信——管道