Синхронизация с помощью мутекса.

ivan84

Здравствуйте.
Помогите пожалуйста разобраться с инхронизацией с помощью мутекса:
Задача в следующем:
Есть две программы:
1-я циклически производит запись в разделяемую память массива данных из 100 элементов, при этом в i-м цикле всем элементам массива присваивается число i.
2-я считывает этот массив по состоянию на момент запуска 2-й програмы.
Если не ользовать механизмы синхронизации, то 2-я програма считывает массив состоящий из i и i+1 (если конечно случайно не совпадет что в нее запишутся только i ). Чтобы этого избежать я создаю мутекс в разделяемой памяти, но т.к. с мутексами я только начал знакомиться, видимо, делаю я это неправильно.
Ниже привожу коды 2-х програм, подскажите что не так?
1-я програма:
 
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <inttypes.h>
#include <unistd.h>
#include <pthread.h>
#define SIZE 100

pthread_mutexattr_t mutex_attr;
pthread_mutex_t *mutex;

void shmem(int);

int main
{
int i;
printf("IN file\n");
for (i=0;i<1000;i++)
{
printf("i=%2d\n", i);
shmem(i);
sleep(1);
}
return EXIT_SUCCESS;
}

void shmem(int i)
{
int fd, status, j;
int * massiv;
pthread_mutexattr_init( &mutex_attr );
pthread_mutexattr_setpshared( &mutex_attr, PTHREAD_PROCESS_SHARED );
fd = shm_open("/swd_es", O_RDWR|O_CREAT, 0777);
status = ftruncate(fd, sizeof(massiv;
massiv = mmap(0, sizeof(massiv PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
mutex = (pthread_mutex_t *)massiv;
pthread_mutex_init( mutex, &mutex_attr );
pthread_mutex_lock( &mutex );
for(j=0;j<SIZE;j++)
{
*(massiv + j) = i;
printf("N%2d=%2d\t", j, *(massiv + j;
delay( 5 );
}
printf("\n");
pthread_mutex_unlock( &mutex );
}

2-я програма:
 
#include <stdlib.h>
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <pthread.h>
#define SIZE 100

pthread_mutexattr_t mutex_attr;
pthread_mutex_t *mutex;

void shmemout;

int main
{
//int i;
printf("OUT\n");
//for (i=0;i<10;i++)
//{
shmemout;
//}
return EXIT_SUCCESS;
}
void shmemout
{
int fd, i;
int buffer[SIZE];
int * massiv;
pthread_mutexattr_init( &mutex_attr );
pthread_mutexattr_setpshared( &mutex_attr, PTHREAD_PROCESS_SHARED );
printf("SHMEMOUT\n");
fd = shm_open("/swd_es", O_RDONLY, 0777);
massiv = mmap(0, sizeof(massiv PROT_READ, MAP_SHARED, fd, 0);
mutex = (pthread_mutex_t *)massiv;
pthread_mutex_init( mutex, &mutex_attr );
pthread_mutex_lock( &mutex );
for(i=0;i<SIZE;i++)
{
buffer[i] = *(massiv + i);
printf("N%2d=%2d\t", i, buffer[i]);
}
printf("\n");
pthread_mutex_unlock( &mutex );
munmap(massiv, sizeof(massiv;
}
Заранее спасибо!

Vlad77

Тебе же в прошлом треде объясняли, что нельзя в shared mem класть pthread mutex
юзай posix 1003.1d именованные семафоры

ivan84

Тебе же в прошлом треде объясняли, что нельзя в shared mem класть pthread mutex
юзай posix 1003.1d именнованные семафоры
Если я правильно понимаю то что написано в книге Realtime Programming for the QNX Neutrino RTOS, то это делать можно, проблема в том что тут написано очень кратко и я не понимаю как это сделать.

kokoc88

Во-первых, ты перезаписываешь свой mutex:
mutex = (pthread_mutex_t *)massiv;
...
for(j=0;j<SIZE;j++)
...
*(massiv + j) = buffer[j];
Во-вторых, не понятно, зачем первой программе int buffer[SIZE];
В-третьих, первая программа закрывает доступ к массиву на всё время, пока он заполняется.
В-четвёртых, тебе сначала надо научиться программировать на Си, а уж потом думать про параллельное выполнение.

ivan84

Во-первых, ты перезаписываешь свой mutex:
mutex = (pthread_mutex_t *)massiv;
...
for(j=0;j<SIZE;j++)
...
*(massiv + j) = buffer[j];
Да в этом месте я какраз понимаю хуже всего.
Во-вторых, не понятно, зачем первой программе int buffer[SIZE];
это рудимент, не обратил внимания. Сейчас исправлю в первом сообщении, но на сколько я понимаю это не играло никакой роли.
В-третьих, первая программа закрывает доступ к массиву на всё время, пока он заполняется.
Это непонятно. Я проверял эти програмы запустив первую и несколько раз запустив вторую во время работы первой, получил описанный выше результат.
В-четвёртых, тебе сначала надо научиться программировать на Си, а уж потом думать про параллельное выполнение.
С эти абсолютно согласен, но, к сожалению, у меня нету на это времени и приходится изучать походу =)

pitrik2

Да в этом месте я какраз понимаю хуже всего.
блин
ну ты же сам привел картинку где написано как надо делать
так трудно прочитать несколько строчек?
там правда "пропущен код взятия памяти", но он у тебя и так есть
могу совсем на пальцах обяснить:
в первом процессе ты в шару кладешь мутекс
во втором процессе ты из шары мутекс должен забрать и использовать
как его забрать у тебя написано в 2-х последних строчках скриншота

kokoc88

Да в этом месте я какраз понимаю хуже всего.
Поэтому я и советую тебе сначала выучить основы Си.
Это непонятно. Я проверял эти програмы запустив первую и несколько раз запустив вторую во время работы первой, получил описанный выше результат.

Вышеописанный результат ты получил, потому что в первой программе сразу же перезаписываешь mutex.

Vlad77

Вот тебе работающий вариант, разбирайся.

#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <inttypes.h>
#include <unistd.h>
#include <pthread.h>
#define SIZE 100

pthread_mutexattr_t mutex_attr;
pthread_mutex_t *mutex;
int *massiv;

void shmem(int);

int main
{
int fd, i;
int status;
pthread_mutexattr_init( &mutex_attr );
pthread_mutexattr_setpshared( &mutex_attr, PTHREAD_PROCESS_SHARED );
fd = shm_open("/swd_es", O_RDWR|O_CREAT, 0777);
status = ftruncate(fd, SIZE*sizeof(int) + sizeof(pthread_mutex_t;
massiv = mmap(0, SIZE*sizeof(int) + sizeof(pthread_mutex_t PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
mutex = (pthread_mutex_t *) void*)massiv + SIZE*sizeof(int;
pthread_mutex_init( mutex, &mutex_attr );
printf("IN file\n");
for (i=0;i<1000;i++)
{
printf("i=%2d\n", i);
shmem(i);
sleep(1);
}
munmap(massiv, SIZE*sizeof(int) + sizeof(pthread_mutex_t;
return EXIT_SUCCESS;
}

void shmem(int i)
{
int j;
int buffer[SIZE];
pthread_mutex_lock( mutex );
for(j=0;j<SIZE;j++)
{
buffer[j]=i;
*(massiv + j) = buffer[j];
printf("N%2d=%2d\t", j, *(massiv + j;
sleep( 1 );
}
printf("\n");
pthread_mutex_unlock( mutex );
}


#include <stdlib.h>
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <pthread.h>
#define SIZE 100

pthread_mutexattr_t mutex_attr;
pthread_mutex_t *mutex;

void shmemout;

int main
{
//int i;
printf("OUT\n");
//for (i=0;i<10;i++)
//{
shmemout;
//}
return EXIT_SUCCESS;
}
void shmemout
{
int fd, i;
int buffer[SIZE];
int * massiv;
pthread_mutexattr_init( &mutex_attr );
pthread_mutexattr_setpshared( &mutex_attr, PTHREAD_PROCESS_SHARED );
printf("SHMEMOUT\n");
fd = shm_open("/swd_es", O_RDWR, 0777);
massiv = mmap(0, SIZE*sizeof(int) + sizeof(pthread_mutex_t PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if (massiv == MAP_FAILED)
printf("map failed\n");
mutex = (pthread_mutex_t *) void*)massiv + SIZE*sizeof(int;
//pthread_mutex_init( mutex, &mutex_attr );
pthread_mutex_lock( mutex );
for(i=0;i<SIZE;i++)
{
buffer[i] = *(massiv + i);
printf("N%2d=%2d\t", i, buffer[i]);
}
printf("\n");
pthread_mutex_unlock( mutex );
munmap(massiv, SIZE*sizeof(int) + sizeof(pthread_mutex_t;
}

ivan84

Вот тебе работающий вариант, разбирайся.
Спасибо огромное, все работает и, похоже, разобрался. =)

Werdna

1-я циклически производит запись в разделяемую память массива
семафорами это делается.
пиши в личку, дам исходники. то что ты хочешь — обычная очередь на разделяемой памяти и семафорах.
Оставить комментарий
Имя или ник:
Комментарий: