Перейти к содержанию
    

работа с FIFO в linux

Имеется два потока.

поток 1:

  запускает поток 2, 
  открывает FIFO (Read only), 
  читает FIFO, 
  закрывает FIFO.

 

поток 2:

  открывает FIFO (Write only), 
  пишет в FIFO, 
  закрывает FIFO.

 

Работа происходит в блокирующем режиме.

Проблема возникает при обмене маленьким обьемом данных.

В этом случае может возникнуть ситуация, когда поток1 блокируется на открытии FIFO, а поток 2 быстро выполняет всю работу и завершается, при этом поток 1 остается заблокированым на открытии.

Как побороть?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Имеется два потока.

поток 1:

  запускает поток 2, 
  открывает FIFO (Read only), 
  читает FIFO, 
  закрывает FIFO.

 

поток 2:

  открывает FIFO (Write only), 
  пишет в FIFO, 
  закрывает FIFO.

Может так:

поток 1:

  открывает FIFO (Read only), 
  запускает поток 2, 
  читает FIFO, 
  закрывает FIFO.

 

Суть задачи понятна, но видимо тут выжны детали :)

У меня такой пример не виснет (на Core 2 Duo, одноядерного под рукой нету :))

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

#define FIFO_NAME    "fifo"

int fifo_size;

void read_fifo()
{
int fd;
char *buf;
int result;
int count;

buf = malloc(fifo_size);
if (buf == NULL)
{
	fprintf(stderr, "%s(): malloc failed: %s\n", __FUNCTION__, strerror(errno));
	return;
}
fd = open(FIFO_NAME, O_RDONLY);
if (fd < 0)
{
	fprintf(stderr, "%s(): open failed: %s\n", __FUNCTION__, strerror(errno));
	free(buf);
	return;
}
count = 0;
do {
	result = read(fd, buf, fifo_size);
	if (result < 0)
	{
		fprintf(stderr, "%s(): read failed: %s\n", __FUNCTION__, strerror(errno));
		free(buf);
		close(fd);
		return;
	}
	if (result > 0)
	{
		count += result;
	}
} while (count < fifo_size);
free(buf);
close(fd);
printf("%s(): %d bytes read\n", __FUNCTION__, count);
}

void write_fifo()
{
int fd;
char *buf;
int result;
int count;

buf = malloc(fifo_size);
if (buf == NULL)
{
	fprintf(stderr, "%s(): malloc failed: %s\n", __FUNCTION__, strerror(errno));
	return;
}
fd = open(FIFO_NAME, O_WRONLY);
if (fd < 0)
{
	fprintf(stderr, "%s(): open failed: %s\n", __FUNCTION__, strerror(errno));
	free(buf);
	return;
}
count = 0;
do {
	result = write(fd, buf, fifo_size);
	if (result < 0)
	{
		fprintf(stderr, "%s(): write failed: %s\n", __FUNCTION__, strerror(errno));
		free(buf);
		close(fd);
		return;
	}
	if (result > 0)
	{
		count += result;
	}
} while (count < fifo_size);
free(buf);
close(fd);
printf("%s(): %d bytes writen\n", __FUNCTION__, count);
}

int main(int argc, char * argv[])
{
pid_t child;

switch (argc)
{
	case 1:
	{
		fifo_size = 1;
		break;
	}
	case 2:
	{
		char * ok;

		fifo_size = strtol(argv[1], &ok, 0);
		if (*ok)
		{
			printf("Error in parameter\n");
			return 2;
		}
		break;
	}
	default:
	{
		printf("Usage: fifotest [size]\n");
		return 1;
		break;
	}
}

if (mkfifo(FIFO_NAME, S_IRUSR | S_IWUSR))
{
	perror("mkfifo failed");
	return 3;
}

child = fork();
if (child > 0)
{
	/* Parent */
	read_fifo();
}
if (child == 0)
{
	/* Child */
	write_fifo();
}
if (child < 0)
{
	perror("fork failed");
	return 5;
}
return 0;
}

 

 

Прошу прощения, недоглядел. Уработался :)

Вот с потоком

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

#define FIFO_NAME    "fifo"

int fifo_size;

void * read_fifo(void * arg)
{
int fd;
char *buf = (char *)arg;
int result;
int count;

fd = open(FIFO_NAME, O_RDONLY);
if (fd < 0)
{
	fprintf(stderr, "%s(): open failed: %s\n", __FUNCTION__, strerror(errno));
	return NULL;
}
// 	printf("reading...\n");
count = 0;
do {
	result = read(fd, buf, fifo_size);
	if (result < 0)
	{
		fprintf(stderr, "%s(): read failed: %s\n", __FUNCTION__, strerror(errno));
		close(fd);
		return NULL;
	}
	if (result > 0)
	{
		count += result;
	}
} while (count < fifo_size);
close(fd);
printf("%s(): %d bytes read\n", __FUNCTION__, count);
return NULL;
}

void * write_fifo(void * arg)
{
int fd;
char *buf = (char *)arg;
int result;
int count;

fd = open(FIFO_NAME, O_WRONLY);
if (fd < 0)
{
	fprintf(stderr, "%s(): open failed: %s\n", __FUNCTION__, strerror(errno));
	return NULL;
}
// 	printf("writing...\n");
count = 0;
do {
	result = write(fd, buf, fifo_size);
	if (result < 0)
	{
		fprintf(stderr, "%s(): write failed: %s\n", __FUNCTION__, strerror(errno));
		close(fd);
		return NULL;
	}
	if (result > 0)
	{
		count += result;
	}
} while (count < fifo_size);
close(fd);
printf("%s(): %d bytes writen\n", __FUNCTION__, count);
return NULL;
}

int main(int argc, char * argv[])
{
pthread_t       th;
pthread_attr_t  attr;
void           *th_ret = NULL;
char           *rdbuf  = NULL;
char           *wrbuf  = NULL;

switch (argc)
{
	case 1:
	{
		fifo_size = 1;
		break;
	}
	case 2:
	{
		char * ok;

		fifo_size = strtol(argv[1], &ok, 0);
		if (*ok)
		{
			printf("Error in parameter\n");
			return 2;
		}
		break;
	}
	default:
	{
		printf("Usage: fifotest [size]\n");
		return 1;
		break;
	}
}

rdbuf = malloc(fifo_size);
if (rdbuf == NULL)
{
	perror("rdbuf = malloc() failed");
	return 3;
}
wrbuf = malloc(fifo_size);
if (wrbuf == NULL)
{
	perror("wdbuf = malloc() failed");
	return 3;
}

if (mkfifo(FIFO_NAME, S_IRUSR | S_IWUSR))
{
	perror("mkfifo failed");
	return 4;
}

pthread_attr_init(&attr);
if (pthread_create(&th, NULL, write_fifo, wrbuf) == 0)
{
	read_fifo(rdbuf);
	pthread_join(th, &th_ret);
}
else
{
	perror("pthread_create failed");
}
free(rdbuf);
free(wrbuf);
return 0;
}

Результат тот же - нет зависаний.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...