LINUX.ORG.RU

[C][FIFO] Чатик, не ходят данные

 ,


0

2

Пытаюсь запилить чатик между двумя процессами, используя 2 FIFO: в первое FIFO первый запущенный процесс пишет, из второго читает. Второй запущенный - наоборот.
Определение первый-второй работает, а вот данные ни один процесс не читает. Происходит зависание на «reading». ЧЯДНТ?


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

#define RFIFO ".rfifo"
#define WFIFO ".wfifo"

int main(void)
{
  FILE *rf, *wf;
  int rd, wd;
  char buf[1024];

  mknod(WFIFO, S_IFIFO | S_IRWXU, 0);
  mknod(RFIFO, S_IFIFO | S_IRWXU, 0);

  wd = open (RFIFO, O_WRONLY | O_NONBLOCK);
  if ((wf = fdopen (wd, "w")) == NULL) /* если никто не читает, вернет NULL. если читают - процесс второй, так и используем для записи */
    {
      close (wd);
      rf = fopen (RFIFO, "r");	/* блокируется до открытия на запись */
      wf = fopen (WFIFO, "w");
      printf ("first. FIFO open.\n");
    }
  else
    {
      sleep (1); /* во избежание одновременного открытия двумя процессами */
      rf = fopen (WFIFO, "r");
      printf ("second. FIFO open.\n");
    }

  while(1)
    {
      if (fgets (buf, 1024, stdin) != NULL)
      	{
      	  if (fputs (buf, wf) != EOF)
	    printf ("put\n");
      	}
      printf ("reading\n");
      if (fgets (buf, 1024, rf) != NULL)
      	{
      	  printf ("%s", buf);
      	}
      printf ("read\n");
    }
  
  fclose (rf);
  fclose (wf);
  
  return EXIT_SUCCESS;
}

во-первых, просто не даёшь им достаточное кол-во данных на вход. Данные буфферизируются на входе/выходе и никуда не уходят. Хинт: пробуй делать fflush на пишущий пайп если получаешь '\n' символ из stdin.

во-вторых, всё равно рано или поздно приложение загошишь в дедлок, т.к. нельзя читать блокирующими вызовами в такой схеме. Нужно делать либо по два процесса/потока на каждой стороне, либо использовать неблокирующее io - см man unlocked_stdio, а лучше man poll, read, write

mashina ★★★★★
()
Ответ на: комментарий от mashina

Спасибо. Еще, наверное, можно setbuf использовать. Не понимаю, откуда дедлок. Поясните пожалуйста, или укажите где почитать. Если сделать отдельный поток для чтения - прокатит?

age
() автор топика

может я чего не понимаю, но ты пишешь в один пайп, а читаешь из другого...

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

#define RFIFO ".fifo"

int main(void)
{
  int fd;
  char buf[1024];
  int len;

  mknod(RFIFO, S_IFIFO | S_IRWXU, 0);

  fd = open(RFIFO, O_RDWR);

  while(1)
    {
      if ((fgets(buf, sizeof(buf), stdin)) != NULL)
      {
          len = strlen(buf);
          write(fd, buf, len);
          memset(buf, 0 , sizeof(buf));
          read(fd, buf, len);
          printf(buf);
      }
    }

  close (fd);
  return 0;
}
Rubbiroid
()
Ответ на: комментарий от mashina

> неблокирующее io - см man unlocked_stdio

Это две большие разницы. Unlocked - это небезопасный доступ к объектам stdio.

const86 ★★★★★
()
Ответ на: комментарий от Rubbiroid

Проверил, тут же считывает обратно.

age
() автор топика
Ответ на: комментарий от age

> Оба процесса из одного бинарника,

Сделай их разными. Или хотя бы передавай параметрами имена FIFO, из который происходит чтение и запись.

смотри начало кода.

Я смотрел. Просто трудно было поверить, что кто-то решит написать пример взаимодействия по FIFO в виде одной программы без параметров.

tailgunner ★★★★★
()
Ответ на: комментарий от Rubbiroid

Не, можно и в одно программе, конечно. Но, судя по вопросу, топикстартеру лучше бы начать с чего-нибудь попроще. Например, c двух разных программ.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Не понимаю, зачем разделять бинарники или вводить параметры для такой простой задачи. Специально пример я не писал. Этот код я использую, и пример в нем есть - mashina ведь заметил ошибку.

age
() автор топика
Ответ на: комментарий от age

> Не понимаю, зачем разделять бинарники или вводить параметры для такой простой задачи.

Чтобы твой код было легче понять.

mashina ведь заметил ошибку.

Надеюсь, дело было в unlocked_stdio

tailgunner ★★★★★
()
Ответ на: комментарий от const86

то две большие разницы. Unlocked - это небезопасный доступ к объектам stdio.

да, ошибся.

Надеюсь, дело было в unlocked_stdio

не юродствуй, суть проблемы это не затрагивает

mashina ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.