Модераторы: xvr
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> проблема синхронизации 
V
    Опции темы
kirjanov
Дата 5.11.2007, 12:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 326
Регистрация: 22.1.2006
Где: Dark wood of erro r

Репутация: 3
Всего: 15



Всем привет.

Есть проблема с синхронизацией в программе. Надо было пофиксить в ней проблемы с конкурентным доступом.  Одна из проблем в ней - олновременный доступ к буферу. Я добавил 2 семафора, вроде это работает. Но происходит еще какой-то race condiotion. (Скорее всего с глобальной переменной counter).  Нашел  про некий тип sig_atomic_t, но че-т оне компилится с ним.

Код

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

#include "common.h"

static void s_child (int s);
int counter;
sem_t *sem_prod;
sem_t *sem_consm;

int main(int argc, char *argv[])
{
    int i;
    int fd_in, *fd_out, fd_bn;
    char buf[256];
    struct sigaction sa;

    /* Allocate the file descriptor array. */
    fd_out = (int*) malloc ((argc - 1) * sizeof (int));
    /* The bottleneck file. */
    fd_bn = open (BN_FILE, O_CREAT | O_RDWR | O_TRUNC,
            FILE_MODE);
    if (fd_bn < 0) {
        printf ("Error opening %s: %s\n", BN_FILE,
            strerror (errno));
        exit (1);
    }
    sem_prod = sem_open(SEM_NAME_PROD, O_CREAT | O_EXCL,
                SEM_MODE, SEM_VAL_ULOCKED);
    if (sem_prod == SEM_FAILED) {
        perror("sem_open()");
        exit(1);
    }
    sem_consm = sem_open(SEM_NAME_CONSM, O_CREAT | O_EXCL,
                SEM_MODE, SEM_VAL_LOCKED);
    if (sem_consm == SEM_FAILED) {
        perror("sem_open()");
        exit(1);
    }
    if (sem_unlink(SEM_NAME_PROD) == -1 || sem_unlink(SEM_NAME_CONSM) == -1) {
        perror("sem_unlink()");
        exit(1);
    }
    /* Child will signal when terminated. */
    sa.sa_flags = 0;
    sa.sa_handler = s_child;
    sigemptyset (&sa.sa_mask);
    sigaction (SIGCHLD, &sa, NULL);
    /* Traverse the command-line args. */
    for (i = 1; i < argc; i++) {
        fd_in = open (argv[i], O_RDONLY);
        if (fd_in < 0) {
            printf ("Error opening %s: %s\n",
                argv[i],
                strerror (errno));
            exit (1);
        }
        snprintf (buf, sizeof(buf), "%s%s", argv[i], TAIL);
        fd_out[i-1] = open (buf,
                O_CREAT | O_WRONLY | O_TRUNC,
                FILE_MODE);
        if (fd_out[i-1] < 0) {
            printf ("Error creating %s: %s\n",
                buf, strerror (errno));
            exit (1);
        }
        switch (fork ()) {
            case -1:
                printf ("Error in fork(): %s",
                    strerror (errno));
                break;
            case 0:
                mx_input (i, fd_bn, fd_in);
            default:
                counter++;
                close (fd_in);
        }
    }
    demx_input (fd_bn, fd_out);
    close (fd_bn);
    unlink (BN_FILE);
    for (i = 1; i < argc; i++)
        close (fd_out[i-1]);
    free (fd_out);
    return 0;
}

static void s_child (int s)
{
    counter--;
}


Код

#include <stdlib.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <semaphore.h>
#include <stdio.h>

#include "common.h"

void mx_input (int i, int fd_bn, int fd_in)
{
    char byte;
    struct timespec ts;
    ts.tv_sec = 0;
    /* Read one byte, sleep random amount of time, loop. */
    while (read (fd_in, &byte, 1) > 0) {
        ts.tv_nsec = 0xFFL & random ();
        nanosleep (&ts, NULL);
        sem_wait(sem_prod);
        lseek (fd_bn, 0, SEEK_SET);
        write (fd_bn, &i, sizeof (int));
        write (fd_bn, &byte, sizeof (char));
        if (fflush(NULL) == EOF) {
            perror("fflush()");
            exit(1);
        }
        sem_post(sem_consm);
    }
    close (fd_bn);
    close (fd_in);
    exit (0);    
}


Код

#include <sys/types.h>
#include <unistd.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>

#include "common.h"

void demx_input(int fd_bn, int *fd_out)
{
    int size = sizeof (int) + sizeof (char);
    char buf[size];
    int num;
    while (counter) {
        sem_wait(sem_consm);
        lseek (fd_bn, 0, SEEK_SET);
        read (fd_bn, buf, size);
        num = *((int*) buf);
        write (fd_out[num-1], buf + sizeof (int),
            sizeof (char));
        if (fflush(NULL) == EOF) {
            perror("fflush()");
            exit(1);
        }
        sem_post(sem_prod);
    }
}


Код

#ifndef _COMMON_H
#define _COMMON_H

#define TAIL        ".copy"
#define    FILE_MODE    (S_IRUSR | S_IWUSR)
#define    BN_FILE        "/tmp/bn.tmp"

#define SEM_MODE    (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
#define SEM_NAME_PROD    "/bneck.prod"
#define SEM_NAME_CONSM    "/bneck.consm"
#define SEM_VAL_ULOCKED    1
#define SEM_VAL_LOCKED    0

void mx_input (int i, int fd_bn, int fd_in);
void demx_input (int fd_bn, int *fd_out);

extern int counter;
extern sem_t *sem_prod;
extern sem_t *sem_consm;

#endif



PM MAIL   Вверх
MAKCim
Дата 5.11.2007, 13:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 84
Всего: 207



сделай так
Код

int current = 0;
while (current < count) { /* count - общее число порожденных процессов */
    if (current < (volatile int)counter) {
...
        ++current;
    }
/* какой-нибудь sleep() */
}
...
static void s_child (int s) {
    counter++;
}


Это сообщение отредактировал(а) MAKCim - 5.11.2007, 13:34


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
kirjanov
Дата 7.11.2007, 18:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 326
Регистрация: 22.1.2006
Где: Dark wood of erro r

Репутация: 3
Всего: 15



Пофиксил с помощью блокировки SIGCHLD
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Программирование под Unix/Linux"
xvr
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • Не забывайте пользоваться кнопкой "Код".
  • Вопросы мобильной разработки тут
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к разделу форума. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, xvr.

 
 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Программирование под Unix/Linux | Следующая тема »


 




[ Время генерации скрипта: 0.0434 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.