Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Программирование под Unix/Linux > как можно это реалтзовать


Автор: 4eJIoBekMoJIekyJIa 25.12.2007, 19:50
есть n одинаковых процессов, нужно с помощью семафоров сделать так чтобы в критическую секцию зашел только нужный процесс(например процесс с номером p).
т.е какойто другой процесс решает какому из n процессов зайти и каким-то образом с помощью семафоров сообщает нужному чтобы тот прошел дальше.

Добавлено через 8 минут и 55 секунд
забыл добавить, можно использовать только 1 семафор

Автор: MAKCim 26.12.2007, 14:49
4eJIoBekMoJIekyJIa, 
я так полагаю, используется System V IPC
здесь есть небольшая трудность
чтобы реализовать такую схему нужно, чтобы каждый из N процессов обладал неким уникальным ресурсом для его идентификации
причем этот ресурс должен быть типа short (или преобразовываться к нему без потери разрядов)
тогда алгоритм работы примерно следующий
инициализируем семафор нулем
синхронизирующий процесс посредством semctl() устанавливает значение семафора равным значению уникального ресурса процесса
каждый из N процессов делает следующее
Код

struct sembuf op[2] = {
    {number, -resource, IPC_NOWAIT},
    {number, 0, IPC_NOWAIT}
};
do {
    if (semop(id, op, 2) < 0) {
        if (errno == EAGAIN) {
            /* не тот процесс */
        }
        /* ошибка не из-за синхронизации *
    }
    /* нужный процесс */
    break;
} while (1);


Автор: 4eJIoBekMoJIekyJIa 28.12.2007, 03:00
Значение resource предпологается равным порядковому номеру процесса.
Только один вопрос, ведь возможна такая ситуация: Пусть должен пройти 80 процесс, и пусть первым операцию над семафором выполнит 100-й процесс, т.е он изменит значение семафора на 20, после чего вернется в начало цикла, а потом управление передастся 20-му процессу(в это время значение семафора будет равно 20), тот изменит значение семафора 0 и пройдет в критичесскую секцию...
Возможно я не правильно что-то понял, не мог ты пояснить.

Автор: MAKCim 28.12.2007, 10:55
4eJIoBekMoJIekyJIa, 
последовательность операций, передаваемых в semop()
либо выполниться атомарно, либо вообще не выполняется
т. е если после уменьшения на величину resource
значение семафора будет ненулевым, произойдет откат до первоначального значения семафора

Добавлено через 3 минуты и 38 секунд
Цитата(4eJIoBekMoJIekyJIa @  28.12.2007,  03:00 Найти цитируемый пост)
Пусть должен пройти 80 процесс, и пусть первым операцию над семафором выполнит 100-й процесс, т.е он изменит значение семафора на 20

он вообще ничего не изменит, т. к 100 > 80 и задан флаг IPC_NOWAIT
100 - порядковый номер процесса
Цитата(4eJIoBekMoJIekyJIa @  28.12.2007,  03:00 Найти цитируемый пост)
после чего вернется в начало цикла, а потом управление передастся 20-му процессу(в это время значение семафора будет равно 20), тот изменит значение семафора 0 и пройдет в критичесскую секцию...

значение семафора останется равным 80 (см. выше)

Автор: 4eJIoBekMoJIekyJIa 28.12.2007, 13:30
ой, точно ступил
А каким образом происходит откат к первоначальному значению семафора?

Автор: MAKCim 28.12.2007, 13:54
Цитата(4eJIoBekMoJIekyJIa @  28.12.2007,  13:30 Найти цитируемый пост)
А каким образом происходит откат к первоначальному значению семафора?

детали реализации
если очень хочется
смотри http://www.linux-m32r.org/lxr/http/source/ipc/sem.c#L1280
sys_semop()

Добавлено @ 14:08
Код

static int try_atomic_semop (struct sem_array * sma, struct sembuf * sops,
340                              int nsops, struct sem_undo *un, int pid)
341 {
342         int result, sem_op;
343         struct sembuf *sop;
344         struct sem * curr;
345 
346         for (sop = sops; sop < sops + nsops; sop++) { /* проходим по всем операциям */
347                 curr = sma->sem_base + sop->sem_num; /* получаем семафор по номеру из операции */
348                 sem_op = sop->sem_op; /* операция над семафором */
349                 result = curr->semval; /* текущее значение семафора */
350   
351                 if (!sem_op && result) /* наш случай: операция = 0, значение != 0 */
352                         goto would_block; /* переход (см. ниже) */
353 
354                 result += sem_op; /* операция над семафором */
355                 if (result < 0)
356                         goto would_block;
357                 if (result > SEMVMX)
358                         goto out_of_range;
359                 if (sop->sem_flg & SEM_UNDO) {
360                         int undo = un->semadj[sop->sem_num] - sem_op;
361                         /*
362                          *      Exceeding the undo range is an error.
363                          */
364                         if (undo < (-SEMAEM - 1) || undo > SEMAEM)
365                                 goto out_of_range;
366                 }
367                 curr->semval = result;
368         }
369 
370         sop--;
371         while (sop >= sops) {
372                 sma->sem_base[sop->sem_num].sempid = pid;
373                 if (sop->sem_flg & SEM_UNDO)
374                         un->semadj[sop->sem_num] -= sop->sem_op;
375                 sop--;
376         }
377         
378         sma->sem_otime = get_seconds();
379         return 0;
380 
381 out_of_range:
382         result = -ERANGE;
383         goto undo;
384 
385 would_block:
386         if (sop->sem_flg & IPC_NOWAIT) /* наш случай: установка EAGAIN в качестве возвращаемого значения */
387                 result = -EAGAIN;
388         else
389                 result = 1;
390 
391 undo: /* откат */
392         sop--; /* текущая операция не выполнилась, поэтому начинаем откат с последней выполнившейся операции */
393         while (sop >= sops) { /* находим все семафоры, над которыми уже были произведены операции */
394                 sma->sem_base[sop->sem_num].semval -= sop->sem_op; /* собственно откат, т. е обратное действие по отношению к действию в строке 354 */
395                 sop--;
396         }
397 
398         return result;
399 }

Автор: Rickert 7.1.2008, 07:16
Пардон, народ, а что такое семафор?

Автор: MAKCim 7.1.2008, 10:37
Цитата(Rickert @  7.1.2008,  07:16 Найти цитируемый пост)
Пардон, народ, а что такое семафор? 

неужели так трудно в гугле/википедии посмотреть?  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)