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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Блокировка чтения и записи 
V
    Опции темы
Xonxt
Дата 29.3.2008, 22:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 103
Регистрация: 24.1.2006
Где: Украина / Одесса

Репутация: нет
Всего: 1



Доброе время суток.

Нужна помощь по теме.  Проблема в принципе похожа на "читателя-писателя".

Есть текстовый файл. В нем какая-то информация.  С файлом работает несколько процессов читателей и 1 процесс –писатель. Читатели читают из файла. А писатель с клавиатуры файл "обновляет".  Когда работат писатель, то ни один другой процесс работать не может, но процессы читатели могут работать вместе (параллельно). 

Задачу решить нужно с помощью fcntl().

Нужен приблизительный пример такой конструкции.  smile smile

Заранее благодарю.  smile 
PM MAIL ICQ Skype   Вверх
RasenHerz
Дата 30.3.2008, 02:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 20.3.2008
Где: Санкт-Петербург

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



Функция fcntl() использюется в пяти различных случаях:
1) Создание дубликата существующего дескриптора
2) Получение/установка флагов дескриптора
3) Получение/установка флагов состояния файла
4) Проверка/установка владельца для асинхронных операций IO
5) Получение/установка блокировки на отдельную запись в файле

Решение поставленной тобой задачи использованием одной лишь ф-цией fcntl() хоть и возможно. но думаю излишне мудрено(она ведь всего лишь меняет "св-ва" уже открытого файла.
т.е. тебе надо лишь "грамотно" открыть файл, а там уже дело техники:
Код

int fdes = open("file.txt", O_RDWR | O_TRUNC | O_CREAT | O_SYNC, 0) /*просто синхронизируем операции чтения-записи*/
/*далее просто используй атомарные операции чтения-записи, которые гарантируют, что во время записи(или чтения)
не произойдет чтения(записи) в файл в другом процессе/потоке.
   вот эти операции:
         ssize_t pread(int filedes, void *buf, size_t nbytes, off_t offset);
         ssize_t pwrite(int filedes, void *buf, size_t nbytes, off_t offset);
*/

после выполнения всех этих операций делаешь форк, создаешь порожденные процессы(они унаследуют все дескрипторы открытых файлов) и можешь не беспокоится: файл будет нормально использоваться в многопоточных приложениях. =)
PM MAIL   Вверх
MAKCim
Дата 30.3.2008, 09:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(Xonxt @  29.3.2008,  22:07 Найти цитируемый пост)
Задачу решить нужно с помощью fcntl().

Код

pid_t pids[READERS];
int index = 0;
int fd = open(PATH, O_RDWR);
if (fd < 0) {
    /* error */
}
for (; index < READERS; ++index) {
    if ((pids[index] = fork()) > 0)
        reader(fd);
    else if (pids[index] < 0) {
        /* error */
    }
}
writer(fd);
...
static void reader(int fd) {
    struct flock lock = {
        .l_whence = SEEK_SET,
        .l_start = 0,
        .l_len = 1
    };
    while (1) {
        lock.l_type = F_RDLCK;
        if (fcntl(fd, F_SETLKW, &lock) < 0) {
            if (errno == EINTR) continue;
            /* error */
        }
        /* читаем */
        lock.l_type = F_UNLCK;
        if (fcntl(fd, F_SETLK, &lock) < 0) {
            if (errno == EINTR) continue;
            /* error */
        }
    }
}
...
static void writer(int fd) {
    struct flock lock = {
        .l_whence = SEEK_SET,
        .l_start = 0,
        .l_len = 1
    };
    while (1) {
        lock.l_type = F_WRLCK;
        if (fcntl(fd, F_SETLKW, &lock) < 0) {
            if (errno == EINTR) continue;
            /* error */
        }
        /* пишем */
        lock.l_type = F_UNLCK;
        if (fcntl(fd, F_SETLK, &lock) < 0) {
            if (errno == EINTR) continue;
            /* error */
        }
    }
}


Добавлено через 2 минуты и 30 секунд
RasenHerz, 
O_SYNC испольуется не для синхронизации


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

PM MAIL   Вверх
Xonxt
Дата 30.3.2008, 11:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 103
Регистрация: 24.1.2006
Где: Украина / Одесса

Репутация: нет
Всего: 1



MAKCim, ага, большое спасибо. Я примерно так и пытался сделать, но я не додумался устанавливать блокировку чтения перед собственно чтением smile smile 
PM MAIL ICQ Skype   Вверх
Xonxt
Дата 30.3.2008, 11:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 103
Регистрация: 24.1.2006
Где: Украина / Одесса

Репутация: нет
Всего: 1



Гм..
очень странно, что как только в функцию reader я добавляю какие-либо действия по считыванию из файла, как походу писатель полностью игнорируется. Например:
Код

static void reader(int fd, int pid) 
{
    struct flock lock; 
    char string[200];    
    ...
        /* читаем */

        if(!read(fd, string, 10))
            printf("Reader %d>> %s\n", pid, string);
            ...
}


Т.е. добавление любых действий по чтению или записи (с файлом или с консолью) в reader() отправляет читателя в бесконечный цикл, а "писатель" writer() вообще игнорируется...

Это сообщение отредактировал(а) Xonxt - 30.3.2008, 12:26
PM MAIL ICQ Skype   Вверх
bsa
Дата 30.3.2008, 12:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 16
Всего: 196



Xonxt, а ты lock снять после чтения не забываешь?
PM   Вверх
Xonxt
Дата 30.3.2008, 12:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 103
Регистрация: 24.1.2006
Где: Украина / Одесса

Репутация: нет
Всего: 1



Конечно нет! Я же просто фрагмент привел...
PM MAIL ICQ Skype   Вверх
bsa
Дата 30.3.2008, 12:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 16
Всего: 196



паузу поставь перед тем, как лочить будешь. А потом, добавь опцию O_SYNC в писатель, а то пока буфер не сбросится, данные не обновятся на диске (другие процессы не увидят их).
PM   Вверх
MAKCim
Дата 30.3.2008, 13:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



bsa, 
кэш файла не зависит от процесса (структуры struct file)
страница кэша, в которой храняться данные, будет в любом случае обновляться при любой попытке записи
поэтому чтение будет происходить из кэша
O_SYNC здесь вообще не причем

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


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

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


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 16
Всего: 196



Цитата(MAKCim @ 30.3.2008,  13:09)
bsa, 
кэш файла не зависит от процесса
O_SYNC здесь вообще не причем

странно. Вот запускаю что-то через nohup и смотрю с помощью tail -f, так вывод дается рывками (поблочно). Или это особенность nohup?
PM   Вверх
MAKCim
Дата 30.3.2008, 13:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(bsa @  30.3.2008,  13:11 Найти цитируемый пост)
странно. Вот запускаю что-то через nohup и смотрю с помощью tail -f, так вывод дается рывками (поблочно). Или это особенность nohup? 

что запускаешь?


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

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


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 16
Всего: 196



Цитата(MAKCim @ 30.3.2008,  13:13)
что запускаешь?

Например:
Код
$ nohup ./configure ... &
$ tail -f nohup.out

  smile
Думаю, что раз вывод происходит в файл, а не терминал, то реакции на \n (сброс буфера) характерной для терминалов нет. Поэтому вывод производится по мере заполнения буфера...
PM   Вверх
Xonxt
Дата 30.3.2008, 14:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 103
Регистрация: 24.1.2006
Где: Украина / Одесса

Репутация: нет
Всего: 1



Гмм... 

Ув. MAKCim,  можно ли попросить Вас в приведенном Вами выше примере кода вставить реальные примеры чтения и записи. В reader() текст читается из файла и выводится на экран, а в writer() - считыается с клавиатуры и записыается в файл. 

А то что-то программа на этих моментах тормозит (читай, уходит в бесконечный цикл).  smile 

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

Это сообщение отредактировал(а) Xonxt - 30.3.2008, 14:11
PM MAIL ICQ Skype   Вверх
MAKCim
Дата 30.3.2008, 14:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Xonxt, 
файл вначале пустой или содержит какие-либо данные?


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

PM MAIL   Вверх
Xonxt
Дата 30.3.2008, 14:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 103
Регистрация: 24.1.2006
Где: Украина / Одесса

Репутация: нет
Всего: 1



Изначально содержит данные.

Похоже, что для того, чтобы реализовать еще и ввод текста с клавиатуры, надо делать процессы не fork'ом, а просто отдельными приложениями...

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

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

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


 




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


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

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