Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Таймауты ожидания SysV семафоров

279
15 декабря 2007 года
bave
456 / / 07.03.2004
В продолжение вот этой http://forum.codenet.ru/showthread.php?t=43609
темы.
------------------------
Как уже говорил, раньше когда сервер работал под виндой - синхронизацию работы процессов осуществляли Mutex-ы.
 
Код:
//Ждём:         // и смотрим чего дождались:
DWORD dwWaitRezult = WaitForSingleObject(pGate->m_hMutex, timeout);
return ((WAIT_OBJECT_0 == dwWaitRezult)||
(WAIT_ABANDONED == dwWaitRezult)) ? TRUE : FALSE;

Велечина timeout как раз определяла сколько можно дожидаться, пока освободится Mutex.
-------------------
Теперь же у меня используются семафоры, где установив значение
sem_op = 0 можно заставить один процесс ждать завершения
работы другого при операциях c общими ресурсами...

Проблема в том, что мне нужно по истечению некоторого времени -
timeout прекратить ожидание, однако
struct sembuf - позволяет задать над каким семафором выполняем операцию, какую операцию и флаги.... а можно ли как-то задать timeout на ожидание sem_op = 0? Т.е. если через timeout семафор не обнулился
функция semop(...) прекратила ожидание и вернула управление программе...
502
21 декабря 2007 года
Jail
550 / / 30.01.2007
У тебя неверная постановка задачи изначально. Вот допустим классы для управления семафорами кот. я постоянно использую ->
Код:
class Semafors {
    private:
        int sem_id;        //Идентификатор множества семафоров
        int num_sems;
        Semafors(const Semafors&);
        Semafors& operator=(const Semafors&);
        const MAXSETSIZE = 256;
        struct semid_ds semid_ds;
        union semun {
            int val;
            struct semid_ds *buf;
            ushort array [MAXSETSIZE];
        } arg, *parg;
    protected:
        inline int createSemafors_arr(key_t key, int nsems, int semflg)
        { return semget(key, nsems, semflg);}
        inline int cntl_sem(int cmd, int semnum = 0, union semun a = 0)    //Вызов semctl()
        { return semctl(sem_id, semnum, cmd, a);}
    public:
        Semafors(key_t key, int nsems, int semflg)         //Создание множества семафоров или запрос существующего множества через конструктор
        {
            num_sems = nsems;
            parg = new union semun(arg);
            parg->buf = new struct semid_ds(semid_ds);
            if((sem_id = Semafors::createSemafors_arr(key, nsems, semflg)) == -1)
            exit(0);
        }
        virtual ~Semafors()
        { delete parg->buf; delete parg; Semafors::cntl_sem(IPC_RMID);}
        friend class SemaforsLock;     
};

class SemaforsLock {
    private:
        Semafors &_sem;
        struct sembuf *sops;
        SemaforsLock(const SemaforsLock&);
        SemaforsLock& operator=(const SemaforsLock&);
    protected:
        inline int operations_sem(unsigned int nsops)        //Вызов semop()
        { return semop(_sem.sem_id, sops, nsops);}
    public:
        SemaforsLock(Semafors &sem) : _sem(sem)
        { sops = new struct sembuf[_sem.num_sems];}
       
/*Назначение аргумента arg зависит от управляющего действия, которое определяется значением аргумента cmd. Допустимы следующие действия:
 * GETVAL - получить значение семафора и выдать его в качестве результата;
 * SETVAL - установить значение семафора равным arg.val;
 * GETPID - получить идентификатор процесса, выполнявшего операцию над семафором последним , и выдать его в качестве результата;
 * GETNCNT - получить число процессов, ожидающих увеличения значения семафора, и выдать его в качестве результата;
 * GETZCNT - получить число процессов, ожидающих обнуления значения семафора, и выдать его в качестве результата;
 * GETALL - прочитать значения всех семафоров множества и поместить их в массив, на который указывает arg.array;
 * SETALL - установить значения всех семафоров множества равными значениям элементов массива, на который указывает
 *    arg.array;
 * IPC_STAT - поместить информацию о состоянии множества семафоров, содержащуюся в структуре данных, ассоциированной с идентификатором semid, в пользовательскую структуру, на которую указывает arg.buf;
 * IPC_SET - в структуре данных, ассоциированной с идентификатором semid, переустановить значения действующих идентификаторов пользователя и группы, а также прав на операции. Нужные значения извлекаются из структуры данных, на которую указывает arg.buf;
 * IPC_RMID - удалить из системы идентификатор semid, ликвидировать множество семафоров и ассоциированную с ним структуру данных.
 */
        int cntlSemafors(int semnum , int cmd, int v = 0);      //Управление семафорами
        int operationsSemafors(unsigned int nsops);      //Операции над семафорами
        void setSemafors_buf(struct semid_ds *b);
        void setSemafors_array(ushort *arr);
        void setSemafors_sops(struct sembuf *s);
        inline int getSemafors_val(void) { return _sem.parg->val;}
        inline struct semid_ds* getSemafors_buf(void) { return _sem.parg->buf;}
        inline ushort* getSemafors_array(void) { return _sem.parg->array;}
        inline struct sembuf* getSemafors_sops(void) { return sops;}
        virtual ~SemaforsLock(){ delete[] sops;}
};
В операциях с семафорами отсутствует операция с предопределённым таймаутом/(лимитом времени) и во многих случаях они используются для синхронизированного доступа к одному файлу ( с flock() ).
Для этой цели необходимо использовать переменные состояния с мьютексами, определяя их область видимости в пределах всей системы (PTHREAD_PROCESS_SHARED) и помещая их в шарёную память для общего доступа процессов, и потоков из разных процессов. В помощь( int pthread_cond_timedwait(pthread_cond_t *cv, pthread_mutex_t *mp, const struct timespec *abstime);)
А вообще, лучше реализовывать подобные вещи в рамках одного процесса с использованием потоков.
Если понадобиться, могу выложить остальные классы для POSIX "инструментов" (на Си код получается корявым и длинным) :)
361
21 декабря 2007 года
Odissey_
661 / / 19.09.2006
Ну например я бы не прочь поразглядывать подобные классы в целях повышения профессионального уровня =) Ты можешь выложить их в разделе исходников, а здесь просто оставить ссылку.
502
21 декабря 2007 года
Jail
550 / / 30.01.2007
Ок, завтра выложу и кину ссылочку или же сюда архивом . Сегодня деньги на инете заканчиваются, сори ....
502
24 декабря 2007 года
Jail
550 / / 30.01.2007
Мда, пунктуальности мне не занимать :D
Вобщем у меня появилась идея создания библиотеки/интерфейса для С++ программ к средствам стандарта Posix. Так скажем вдохновило меня на это, программирование на Python, где все эти привязки реализованны в качестве управления высокоуровневыми объектами. Программы получаются достаточно короткими, функциональными и удобными в плане изменений и расширяемости. Но многие люди даже не зают что такое питон и в основном кодят на С/С++ ну и Java. На Си код получается ужасно уродливым....а представление элементов Posix в качестве объектов, оперируемых с помощью иных структур данных, скажем односвязанный/двухсвязанный простой и кольцевой список, вектора, матрицы, ассоциативный массив, и т.д и.т.п., а так же построение объектов, реализующих различные алгоритмы сортировки и поиска из готовых библиотечных классов дает возможности построения более элегантного кода.
Раньше я просто использовал ограниченный набор классов в своих программах, кот. находились во вкл. заголовочном файле. Теперь же думаю создать полноценную библиотеку/интерфейс ко всем, ну или многим, инструментариям Posix: как к низкоуровневым средствам межпроцессного взаимодейтсия (в вышепреведённых классах не хватает кое-чего - сокетов, труб, очередей FIFO, очередей сообщений, шарёной памяти и RPC. Так же не хватает динамического контроля ошибок. Над этим я работаю), так и к высокоуровневым, а в частности есть идеи реализации интерфейса к библиотеке распределенных межпроцессных коммуникаций DIPC, MPI, ну и посложнее - к библиотеке научных вычислений PETSc (в Python прекрасно реализованно в качестве Numeric Python) и к PVM (для возможности представления высокоуровнего параллелизма в пользовательских приложениях с помощью объектов С++).
После создания первой работоспособной версии библиотеки думаю опубликовать проект допустим на sourseforge.net и кинуть ссылку в созданную тему на этом форуме (возможно кому-то это покажется интересным, а кому-то забавным....не важно =)
Небольшие наработки классов, кот. я кинул сюда, представляют пока ограниченные возможности. оперировать с ними просто:
1) создаём объекты атрибутов для мьютексов, переменных состояния, потоков в необходимом количестве;
2) создаём объекты ключей, мьютексов, переменных состояния и помещаем указатели на них в связанный список Slist или же в Islist(в этом случае необходимо создать производный от slink класс со своей реализацией);
3) создаем объекты потоков (пользовательские потоки библиотеки Pthread. Класс потоков ядра пока не реализован) и так же можно хранить указатели на них в связанном списке;
4) выбор мьютексов, переменных состояния, ключей, потоков легко производить с помощью итератора, "просматривающего" список (у мьютексов, переменных состояния, ключей имеется свой идентификатор в связанном списке, генерируемый с помощью random). В пользовательской программе реализация проста и эффективна.
Любые идеи, предложения, мнения и критику с удовольствием выслушаю в приват. Думаю библиотека будет полезна и интересна многим начинающим и (не только) программерам под UNIX :)
279
25 сентября 2008 года
bave
456 / / 07.03.2004
Ух ты... а тема то разрослась пока я в неё не заглядывал :) - правдо я уже у себя всё успел переписать так, что в такой необходимости синхронизации процессов нужда отпала (сейчас вообще не осталось ни одного модуля .cgi написанного на С++) - но всё равно информация думаю будет полезной, спасибо.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог