Канал между потоками

Модератор: Модераторы разделов

Firix
Сообщения: 1

Канал между потоками

Сообщение Firix »

Мне нужно организовать безымянный канал между двумя потоками, первый поток должен писать в канал, второй - читать из него. Делаю следующим образом:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>

static pthread_mutex_t mutex;

void* thread1_f(void* arg)
{
close(fds[0]);
int a = 2000;
pthread_mutex_lock(&mutex);
write(fds[1], &a, sizeof(int));
pthread_mutex_unlock(&mutex);
sleep(1);
close(fds[1]);

return NULL;
}

void* thread2_f(void* arg)
{
close(fds[1]);
int a;
pthread_mutex_lock(&mutex);
read(fds[0], &a, sizeof(int));
pthread_mutex_unlock(&mutex);
printf("%d\n", a);
close(fds[0]);

return NULL;
}


int main()
{
int fds[2];
pipe(fds);

pthread_mutex_init(&mutex, NULL);

pthread_t thread1_id;
pthread_t thread2_id;

pthread_create(&thread1_id, NULL, &thread1_f, &fds);
pthread_create(&thread2_id, NULL, &thread2_f, &fds);

pthread_join(thread1_id, NULL);
pthread_join(thread2_id, NULL);

pthread_mutex_destroy(&mutex);

return 0;
}


Но во втором потоке функция read возвращает ошибку EBADF.
Подскажите, пожалуйста, где и что я сделал неправильно?
Спасибо сказали:
Аватара пользователя
elide
Бывший модератор
Сообщения: 2421
Статус: Übermensch
ОС: лялих

Re: Канал между потоками

Сообщение elide »

какой-то совершенно безумный код..... он у тебя даже не скомпилируется (:
во-первых, сначала неплохо бы в каждом потоке сделать что-то вроде

Код: Выделить всё

int *fds = (int*)arg;

во-вторых, либо я не понял высокой идеи, либо ты прямо первой же инструкцией в потоке лишний раз закрываешь пайп еще до попытки чтения/записи (: стоит убрать эти лишние close(fds[0]); и close(fds[1]); и счастье окажется гораздо ближе.
слава роботам!
Спасибо сказали:
Аватара пользователя
KiWi
Бывший модератор
Сообщения: 2521
Статус: статус, статус, статус

Re: Канал между потоками

Сообщение KiWi »

elide писал(а):
27.05.2006 20:39
во-вторых, либо я не понял высокой идеи, либо ты прямо первой же инструкцией в потоке лишний раз закрываешь пайп еще до попытки чтения/записи (: стоит убрать эти лишние close(fds[0]); и close(fds[1]); и счастье окажется гораздо ближе.

Мне сначала это тоже не понравилось, но

Код: Выделить всё

man 2 pipe

открыл глаза, откуда ноги растут :-)

Правда, стоит отменить, что при fork'е программа полностью копируется(то есть в примере закрывается _лишний_ дескриптор), тогда как при использовании pthread этого делать не нужно -- они могут использовать одни и те же ресурсы.
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Канал между потоками

Сообщение Zeus »

Дык в этом отличие и есть: в книжках (ман не видел) pipe'ы объясняются чаще всего на fork'е.
Т.е. при взаимодействии разных процессов.
А тут - это один процесс в котором два потока, каждый из которых закрывает файловый дескриптор, который юзает другой поток.
Спасибо сказали:
ToniX
Сообщения: 11

Re: Канал между потоками

Сообщение ToniX »

Всё правильно. Не надо в потоковых функциях закрывать пайпы. При создании процесса посредством fork - дескрипторы дублируються, т. е. это будут новые дескрипторы, "указывающие" на ресурсы родительского процесса. Поэтому процесс, владеющий этими дескрипторами должен их закрывать, если они ему не нужны. С потоками - ситуация совершенно другая. Так как всё происходит в рамках одного процесса, то и дескрипторы одни и теже. И если ты их один раз закроешь, то больше не сможешь их использовать.

А вообще, пайпы - средство межпроцессного взоимодействия и использовать их для обмена данными между потоками слишком дорого и бессмысленно. Лучше для этих целей использовать простые очереди (с соблюдением правил синхронизации, естественно).
Спасибо сказали: