Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: работа с FIFO в linux
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы > Программирование
Ivan_Kov
Имеется два потока.
поток 1:
CODE

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


поток 2:
CODE

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


Работа происходит в блокирующем режиме.
Проблема возникает при обмене маленьким обьемом данных.
В этом случае может возникнуть ситуация, когда поток1 блокируется на открытии FIFO, а поток 2 быстро выполняет всю работу и завершается, при этом поток 1 остается заблокированым на открытии.
Как побороть?
amw
Цитата(Ivan_Kov @ Apr 22 2009, 11:40) *
Имеется два потока.
поток 1:
CODE

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


поток 2:
CODE

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

Может так:
поток 1:
CODE

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


Суть задачи понятна, но видимо тут выжны детали smile.gif
У меня такой пример не виснет (на Core 2 Duo, одноядерного под рукой нету smile.gif)
CODE
#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;
}



Прошу прощения, недоглядел. Уработался smile.gif
Вот с потоком
CODE
#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;
}

Результат тот же - нет зависаний.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.