LINUX.ORG.RU

procs queue


0

0

Подскажите пожалуйста как мне сделать очередь процессов, где каждый процесс ждет завершения предыдущего

0 (parent): childs: 1 <--- 2 <--- 3 <--- 4 <--- 5 <-..

parent поочереди рождает 1, 2, 3, 4 и 5 процессы, соответственно 5-й должен ждат ь завершения 4-го, 4-й 3-го ит.д.

★★

см info:libc:Posix Thread:Condition Variables:

A condition (short for "condition variable") is a synchronization device that allows threads to suspend execution until some predicate on shared data is satisfied. The basic operations on conditions are: signal the condition (when the predicate becomes true), and wait for the condition, suspending the thread execution until another thread signals the condition.

anonymous
()

threads то тут причем? (эти процессы threads free) семафоры вообще так же не подходят так как не будет гарантирован порадок после освобождения семафора 1-м процессом а допустим его ждут 2-й и 3-й захватить может как 2-й так и 3-й это как будет удобнее операционке.

lg ★★
() автор топика

1. Очевидно, поскольку дочки НЕ связаны родственными отношениями друг с другом,
синхронизоваться они должны через толстого папу ("процесс 0").
2. Как это сделать - тысячи способов. Очевидно одно - толстый папа
должен вязать очередь дочек и на каждый SIGCHLD по ней проходиться,
проверяя waitpid. Уж как он их будет блокировать/освобождать - зависит
от фантазии. Например, SIGSTOP/SIGCONT, или через пайпы, или теми же семафорами...

Die-Hard ★★★★★
()

О, придумал:

Папа перед каждым форком делает новый семафор и сохраняет key_t предыд.
Дочка взводит этот новый семафор при старте и освобождает перед смертью.
После взведения первого семафора суется на предыдущий, в декременте которого
ей будет отказано, пока он не будет освобожден предыдущей дочкой.

Одно "Но": возможны деадлоки, если какая-лидо дочка помрет не своей
смертью. Надежнее поручить инкремент семафоров толстому папе. Пусть он на
каждый SIGCHLD просматривает PIDы дочек, пока не найдет свежего покойника,
после чего инкрементит соответств. семафор.

Второе "Но": semctl() несколько непортабильна, в HP/SunOS/xBSD/Lunuxе
она несколько различается последним аргументом.

Die-Hard ★★★★★
()

2die-hard: Фишка в том что есть 2 вида рождаемых папой процессов - одни после некоторого события должны блокироваться на предмет завершения другого, а некоторые в зависимости от их состояния не должны - это деление происходит не сразу после fork() а после некоторой _общей_(одинаковой) работы childa. Поэтому мне думаеться что единственный способ это 1 семафор на shared memory и второй семафор состояния. Но как это галимо получается :(

lg ★★
() автор топика

PS: папа может(зачем?) умереть после рождения своих перцев.

lg ★★
() автор топика
Ответ на: комментарий от lg


> Фишка в том что есть 2 вида рождаемых папой процессов ... это деление происходит не
> сразу после fork()
Тогда - тем более, единственный разумный способ - отдать синхронизацию папе с поторхами.
Пусть он с дочками через пайпы общается. Когда дочка затеяла синхронизоваться с
предыд., она посылает папе мессагу через пайп (или через IPC очередь) и засыпает, а папа
вставляет ее в FIFO. На SIGCHLD папа чистит FIFO и будит первую живую дочку.

Если папа хочет умереть - нЕ хрена, пусть сначала форкнется. Вообще,
передавать дочек initу IMHO - дурной тон.

> 1 семафор на shared memory и второй семафор состояния.
Никак! Дочек много, и они упорядочены. А семафор - по определению
целое число, т.е. просто счетчик ресурсов. Если хочешь с семафорами связываться - их
(семафоров) должно быть столько же, сколько и дочек.


Die-Hard ★★★★★
()

BTW, все можно сделать безо всяких IPC, стандартными POSIX средствами.

Дочка, затеявшая синхронизоваться, тупо засыпает.
После получения SIGCHLD папа проходится по всем (связанным в FIFO)
своим дочкам на предмет waitpid(#,&status,WNOHANG | WUNTRACED).
Кто не 0, того проверяем на вшивость:
Если WIFSTOPPED(status), то дочка хочет синхронизоваться, ставим ее
в другую FIFO. Потом чистим эту другую FIFO (через waitpid(WNOHANG))&&
kill) и будим первую оставшуюся дочку.

Die-Hard ★★★★★
()

Еще алгоритмы, с семафорами.

1. Допустим, дочек будет не больше N.
Папа в самом начале передает дочкам N объединиченных семафоров.
Когда n-я дочка затеет синхронизоваться, она обнуляет n-й семафор и
пытается декркментить (n-1)-й, после чего благополучно засыпает.
А потом, перед смертью, опять инкрементит n-й. (только, учти, типичное
макс. число семафоров в SETе - 512)


2. Допустим, общее кол-во дочек заведомо меньше 15 (точнее, 2^N< SEMVMX,
где N- макс. кол-во дочек, а SEMVMX - максимальная величина семафора,
определяемая при построении ядра, обычно 32767, определяется в <linux/sem.h>
Тогда можно обойтись одним семафором и дергать n-й и (n-1)-й биты.

3. Если дочек много, комбинируем - дергаем (n % NMAX) и ( (n-1) % NMAX) биты
у (n/NMAX) и ( (n-1)/NMAX) семафоров, где NMAX безопасно положить равным 7
( уж 255 для семафора всяко допустимо быть должно!)

Die-Hard ★★★★★
()

Я, может, чего не понял, но не слабо ли детям порождать друг друга
последовательно, не перегружая папу, и висеть себе спокойно каждый
на своем waitpid?

anonymous
()

был вопрос:

> как мне сделать очередь процессов,
> где каждый процесс ждет завершения предыдущего
> 0 (parent): childs: 1 <--- 2 <--- 3 <--- 4 <--- 5 <-..
>
> parent поочереди рождает 1, 2, 3, 4 и 5 процессы, соответственно
> 5-й должен ждат ь завершения 4-го, 4-й 3-го ит.д.
>
> lg (*) (2002-07-29 11:50:29.203)

насколько мне не изменяет память, функцию getppid() никто не отменял.
зачем так сильно усложнять задачу с синхронизацией дочек с помощью родителя, когда дочка сама может его подождать?

всего-лишь в родителе форкаешь новый процесс, отписываешься от него с помощью waitpid(..., WNOHANG | WUNTRACED) и забываешь о нем, т.к. дочка сама побеспокоется о синхронизации.

на мой взгляд типичный случай конвеерной синхронизации.

proff
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.