Как да избегнем множество писатели в наименована тръба?

Пиша програма с наименуван канал с множество читатели и множество писатели. Идеята е да се използва този наименуван канал за създаване на двойки четец/записвач. Това е:

  • A чете тръбата
  • B пише в тръбата (обратно)
  • Създадена е двойка A-B!

За да гарантирам, че само един процес чете и един пише, използвах 2 ключалки с flock. Просто така.

Код на читателя:

echo "[JOB $2, Part $REMAINING] Taking next machine..."
    VMTAKEN=$((
    flock -x 200;
    cat $VMPIPE;
    )200>$JOINQUEUELOCK)

echo "[JOB $2, Part $REMAINING] Machine $VMTAKEN taken..."

Код на писателя:

((
flock -x 200;
echo "[MACHINE $MACHINEID] I am inside the critical section"
echo "$MACHINEID" > $VMPIPE;
    echo "[MACHINE $MACHINEID] Going outside the critical section"
)200>$VMQUEUELOCK)

echo "[MACHINE $MACHINEID] Got new Job"

Понякога получавам следния проблем:

[MACHINE 3] I am inside the critical section
[JOB 1, Part 249] Taking next machine...
[MACHINE 3] Going outside the critical section
[MACHINE 1] I am inside the critical section
[MACHINE 1] Going outside the critical section
[MACHINE 1]: Got new Job
[MACHINE 3]: Got new Job
[JOB 1, Part 249] Machine 3
1 taken...

Както можете да видите, друг писател е написал, преди читателят да приключи с четенето. Какво мога да направя, за да се отърва от този проблем? Трябва ли да използвам ACK тръба или нещо подобно?

Благодаря ви предварително


person Javier J. Salmeron Garcia    schedule 29.12.2010    source източник
comment
Каква е семантиката на командата flock? Кой файл заключва? Кой го е написал? Сигурен ли си, че прави това, което трябва да прави? (Мога да намеря само страници с ръководство за извикването на функцията flock(), но не и за команда, която я обвива.)   -  person Jonathan Leffler    schedule 29.12.2010
comment
Изглежда, че проблемът не е във флок, а в писането в наименуваната тръба. Както можете да видите в резултата, двете машини не са в критичната секция едновременно.   -  person Javier J. Salmeron Garcia    schedule 29.12.2010


Отговори (1)


Това би било типично използване на семафори:

  1. Създайте 2 семафора - един за обработка на четене, а другият за процеси на запис. задайте всеки семафор на стойност 1

  2. Четенето обработва sem_wait(2) на семафора за читатели, докато semphore > 0 и го намали до нула, ако го получат.

  3. Процесите на писане ще направят същото със семафора, предназначен за тях

  4. Контролен процес (който също може да настрои семафорите първоначално) може да провери дали и двата семафора са нула и да присвои двойката

  5. reader/writer освобождава семафорите (като ги увеличава отново с 1), така че следващият readr или writer ще получи семафора.

За предаване на информация между четец/записвач може да се използва споделена памет...

person ktf    schedule 16.09.2011