两个子进程通过命名管道进行通信

时间:2016-10-10 23:42:08

标签: c

我有一个主程序,它创建了两个子节点和一个命名管道(FIFO)。每个孩子通过execv()执行一个名为“sendSignal”的程序。“sendSignal”的一个参数是主程序中的FIFO。

孩子们要互相发信号。它决定主要(在变量firstShooter中)的一个参数,它首先发射信号。

我想知道这两个孩子如何通过这个命名管道互相发送他们的pid。

以下是主要计划:

<button type="button" ...>

这是sendSignal:

#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>

/* this program should be provided with 2 arguments */

int main(int argc, char **argv)
{

   char str1[15];
   char str2[15];
   char fileDescriptor[15];
   char *my_args[4];
   char *myfifo = "myfifo";

  int fd, pipeCheck;
  pid_t pid1, pid2, wid;


  /* If the user does not provide the argument to determin which child is firing first */
  if(argc != 2)
  {
    fprintf(stderr,"%s: 2 arguments needed, got %d\n",argv[0],argc-1);
    exit(1);
  }

  /* create the FIFO (named pipe) */
  pipeCheck = mkfifo(myfifo, 0666);

   /* check if the named pipe was created properly if not output an error */
   if(pipeCheck == -1)
   {
     fprintf(stderr, "%s: Error creating named pipe: %s\n",argv[0], strerror(errno));
      exit(1);    
   }


   pid1 = fork();

   if (pid1 < 0)
    {
      fprintf(stderr, ": fork failed: %s\n", strerror(errno));
      exit(1);
    }

    if(pid1 == 0)
    {


      my_args[0] = "sendSignal";
      my_args[1] = argv[1];
      my_args[2] = myfifo; //  the named pipe as arguemnt
      my_args[3] = NULL;
      execv("sendSignal",my_args);
      fprintf(stderr,"sendSignal cannot be executed by first child...");
      exit(-1);
    }


     pid2 = fork();

    if(pid2 < 0)
    {
       fprintf(stderr, ": fork failed: %s\n", strerror(errno));
       exit(1);
    }

    if(pid2 == 0)
    {

      my_args[0] = "sendSignal";
      my_args[1] = argv[1];
      my_args[2] = myfifo;  // named pipe as arguemnt
      my_args[3] = NULL; 
     // printf("this is converted = %s\n",my_args[1]);
      execv("sendSignal",my_args);
      fprintf(stderr,"sendSignal cannot be executed by second child...");
      exit(-1);
    }

close(fd);
unlink(myfifo);


wid = wait(NULL);


return 0;

}

2 个答案:

答案 0 :(得分:0)

您的两个子进程都有相同的参数:

my_args[0] = "sendSignal";
my_args[1] = argv[1];
my_args[2] = myfifo; //  the named pipe as argument
my_args[3] = NULL;

firstShooter参数没有意义,因为流程无法将自己标识为第一个或第二个。

我建议再添加一个参数 - 进程索引。可以通过以下方式修改sendSignal函数逻辑:

char pid1[15];
char pid2[15];
int processIndex = atoi(argv[3]);

fd = open(argv[2],O_RDWR);

if (processIndex == firstShooter)
{
  // Send firstShooter PID
  sprintf(pid1,"%d",getpid());
  write(fd,pid1,sizeof(pid1));

  // Got the other PID
  read(fd,pid2,sizeof(pid2));
}
else
{
  // Got the firstShooter PID
  read(fd,pid1,sizeof(pid1));

  // Send the other PID
  sprintf(pid2,"%d",getpid());
  write(fd, pid2, sizeof(pid2));
}

close(fd);

printf("pid1 = %s\n",pid1);
printf("pid2 = %s\n",pid2);

答案 1 :(得分:0)

您实施的方式存在一些问题。 1.在主程序中调用两个fork()将创建两个以上的子进程。(3个子进程)。所以给出一个条件来检查你是否在父本身的上下文中调用了下一个fork。

#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>

/* this program should be provided with 2 arguments */

int main(int argc, char **argv)
{
    int * status;
    char str1[15];
    char str2[15];
    char fileDescriptor[15];
    char *my_args[4];
    char *myfifo = "myfifo";

    int fd, pipeCheck;
    pid_t pid1, pid2, wid;


    /* If the user does not provide the argument to determin which child is firing first */
    if(argc != 2)
    {
        fprintf(stderr,"%s: 2 arguments needed, got %d\n",argv[0],argc-1);
        exit(1);
    }

     /* create the FIFO (named pipe) */
    pipeCheck = mkfifo(myfifo, 0666);

    /* check if the named pipe was created properly if not output an error */
    if(pipeCheck == -1)
    {
        fprintf(stderr, "%s: Error creating named pipe: %s\n",argv[0], strerror(errno));
        exit(1);    
    }


   pid1 = fork();

   if (pid1 < 0)
    {
      fprintf(stderr, ": fork failed: %s\n", strerror(errno));
      exit(1);
    }

    if(pid1 == 0)//child
    {
//  printf("pid1=0\n");
        printf("i am child 1 %d\n",getpid());
        my_args[0] = "sendSignal";
        my_args[1]=malloc(6);
        sprintf(my_args[1] , "%d", getpid());
        //my_args[1]="1";
        printf("p%s\n",my_args[1]);
        my_args[2] = myfifo; //  the named pipe as arguemnt
        my_args[3] ="1";
        execv("sendSignal",my_args);
        fprintf(stderr,"sendSignal cannot be executed by first child...");
        exit(-1);
    }
    else if(pid1>0)// parent
    {
        //  printf("pid1 %d",pid1);
        waitpid(pid1,&status,WIFEXITED(status));
        pid2 = fork();
        //  printf("p:%d",pid2);
    if(pid2 < 0)
    {
       fprintf(stderr, ": fork failed: %s\n", strerror(errno));
       exit(1);
    }
    if(pid2 == 0)
    {
        printf("i am child 2 %d\n",getpid());
        my_args[0] = "sendSignal";
        my_args[1]=malloc(6);
        sprintf(my_args[1] , "%d", getpid());
        my_args[2] = myfifo;  // named pipe as arguemnt
        my_args[3] = "2"; 
        // printf("this is converted = %s\n",my_args[1]);
        execv("sendSignal",my_args);
        fprintf(stderr,"sendSignal cannot be executed by second child...");
        exit(-1);
    }
    printf("done\n");
    }

close(fd);
wait(NULL);
fd=open("fifo1", O_RDONLY);
char * space=(char *)malloc(6);
read(fd,space,6);
printf("from fifo1 %s",space);

fd=open("fifo2", O_RDONLY);
//char * space=(char *)malloc(6);
read(fd,space,6);
printf("from fifo2 %s",space);
//unlink(myfifo);


wid = wait(NULL);
unlink(myfifo);

return 0;

}

2。这两个子进程正在访问同一个管道。管道用于单向通信,一端用于读取,另一种用于写入。因此,为流程创建两个管道。我建议最好不要去找管道。