реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Поделимся опытом, Несколько процессов - общие переменные
SasaVitebsk
сообщение Mar 12 2006, 12:47
Сообщение #1


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Вопрос чисто риторический и не очень. smile.gif
Я думаю с этим вопросом в той или иной степени сталкивался каждый разработчик. Так давайте же братцы поделимся опытом, так сказать облегчим душу. smile.gif

Итак имеется прерывание и голова, или два прерывания, - короче несколько независимых процессов. Имеется переменная которая используется (модифицируется, сравнивается) в обоих (нескольких) процессах. В худшем случае переменная многобайтовая.

Итак кто как борится с вызыванием прерывания во время модификации переменной. Приведу пример (Пример абстракный. Привожу его для понимания картины).
Имеется кольцевой буфер. Переменная EndInBuf двухбайтная. При переходе по кольцу осуществляются след. действия.
if (EndInBuf > (BEGIN_IN_BUF + LENGTH_IN_BUF)) EndInBuf = BEGIN_IN_BUF;
Очевидно что операция присваивания будет происходить в несколько ассемблерных команд. Если между этими командами происходит вызов прерывания и в этом прерывании используется переменная EndInBuf, то произойдёт ошибка. Я в своей практике (на ассемблере) использовал следующие способы предотвращения данных ситуаций.
1) Самый простой. Сокращаешь до минимума число критических операций. На время данной операции запрещаешь прерывания.
2) Синхронизация процессов. В прерывании устанавливаешь флаг. В голове сбрасываешь и дожидаешься установки. Это означает что прерывание пришло и у тебя есть некоторое время для модификации, до прихода следующего прерывания.
3) Разделяешь процессы во времени так, чтобы они никогда не перекрывались. (Так сказать мини ОС smile.gif )
4) В некоторых случаях помогает написание програмного контролера прерываний. (Модификация пункта 1)

Меня интересует как к этому подходят другие? Имеются ли "общепринятые решения по данному вопросу"? smile.gif Особенно меня это интересует в плане применения на C. Так как я сейчас перехожу на данный язык.
Дело в том что я сейчас нахожусь на распутьи. Мне надо осуществить операцию типа "чистка мусора". Как к этому подойти по грамотному, пока не знаю. Ни одно решение пока мне не понравилось.
Go to the top of the page
 
+Quote Post
beer_warrior
сообщение Mar 12 2006, 13:31
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 1 065
Регистрация: 8-10-05
Из: Kiev, UA
Пользователь №: 9 380



Существуют стандартне методы синхронизации:
например (1) называеться critical section, (2) - mutex.
Обо всем этом можно почитать в хороших книжках по системному программированию. Мне например очень помог Вильямс "Системное программирование для Win2000",Кертен "Введение в QNX Neutrino",
различные руководства по RTOS, например на www.FreeRTOS.org.
Я думаю список продолжат.
На проблему стоит смотреть шире - дело не только в защите конкретных переменных, а в организации системы приоритетов и межпроцесного взаимодествия (IPC).


--------------------
Вони шукають те, чого нема,
Щоб довести, що його не існує.
Go to the top of the page
 
+Quote Post
defunct
сообщение Mar 12 2006, 17:00
Сообщение #3


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(SasaVitebsk @ Mar 12 2006, 14:47) *
Если между этими командами происходит вызов прерывания и в этом прерывании используется переменная EndInBuf, то произойдёт ошибка.

Очевидно самый простой способ - не обращаться к этой переменной в прерывании. Для AVR да и вообще для многих МК в которых используется одноуровневый КПП вообще нет никакой диллемы, т.к. код выполняемый в обработчике прерывания никем не может быть прерван.

Однако если имеют место вытесняемые потоки тогда, не имея ОС, придется самостоятельно делать объекты синхронизации. Наиболее прост в реализации семафор (известный как CriticalSection) с функциями Wait/Enter() и Pass/Leave() соответственно на входе и выходе из критического участка. Коды функций Wait() и Pass() могут быть например такими:

Код
volatile UINT Flag;

void Wait()
{
    while (Flag /* and !(Flag==ThreadId) */) {};
    Flag=1;    // в идеале заносится номер потока ThreadId
}

void Pass()
{
   // if (Flag == ThreadId)
   Flag = 0;
}


использование семафора сводится к вызову функции Wait() перед входом в критический участок и функции Pass() после прохождения критического участка.
Код
Wait();
if (EndInBuf > (BEGIN_IN_BUF + LENGTH_IN_BUF)) EndInBuf = BEGIN_IN_BUF;
Pass();


Однако необходимое требование для того чтобы такой механизм синхронизации работал - потоки должны быть вытесняемыми или параллельными! Следовательно в вашем случае такой подход не годится... Для вашего случая функции Wait() и Pass() могут иметь такой вид:

Код
__regvar static char sreg;

void Wait()
{
   sreg = SREG;
   CLI();
}

void Pass()
{
   SREG = sreg;
}
Go to the top of the page
 
+Quote Post
_artem_
сообщение Mar 12 2006, 18:55
Сообщение #4


учащийся
*****

Группа: Свой
Сообщений: 1 065
Регистрация: 29-10-05
Из: города контрастов
Пользователь №: 10 249



SasaVitebsk, ОС почти таким же макаром и действует ка и вы описали . Просто названия немного заумные для этого мютекс, семафор, атомарные операции (запрешение прерывания )) )...


--------------------
Зачем лаять на караван , когда на него можно плюнуть?

Go to the top of the page
 
+Quote Post
dxp
сообщение Mar 13 2006, 07:15
Сообщение #5


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(defunct @ Mar 12 2006, 23:00) *
Однако если имеют место вытесняемые потоки тогда, не имея ОС, придется самостоятельно делать объекты синхронизации. Наиболее прост в реализации семафор (известный как CriticalSection)

Прошу прощения, но критическая секция - это не семафор. Это именно секция кода, при выполнении которой прерывания запрещены, т.е. это не прерываемая секция.

Цитата(defunct @ Mar 12 2006, 23:00) *
Код
__regvar static char sreg;

void Wait()
{
   sreg = SREG;
   CLI();
}

void Pass()
{
   SREG = sreg;
}

А вот это и есть в чистом виде критическая секция. smile.gif

Если уж пользоваться IAR EWAVR, то имеет смысл использовать класс-"обертку" (wrapper), которая позволяет не забывать выполнить на выходе парную функцию. Например:
Код
typedef usigned char TStatusReg;

class TCritSect
{
public:
    TCritSect () : StatusReg(__save_interrupt()) { __disable_interrupt(); }
    ~TCritSect() { __restore_interrupt(StatusReg); }

private:
    TStatusReg StatusReg;

};

void f()
{
    {  // !!! Критическая секция: начало !!!
         TCritSect cs;
         ...               // код критической секции
    } // !!! Критическая секция: конец !!!

}

Здесь при выходе из блока, где объявлен объект cs, автоматически будет вызван деструктор объекта cs, который (деструктор) восстановит состояние глобального разрешения прерываний.


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
vet
сообщение Mar 13 2006, 07:51
Сообщение #6


Знающий
****

Группа: Свой
Сообщений: 550
Регистрация: 16-06-04
Из: Казань
Пользователь №: 32



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


--------------------
Главная линия этого опуса ясна мне насквозь!
Go to the top of the page
 
+Quote Post
dxp
сообщение Mar 13 2006, 08:59
Сообщение #7


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(vet @ Mar 13 2006, 13:51) *
dxp,
Критическая секция - это часть программы, в которой осуществляется доступ к разделяемым данным. Проще всего реализовать это запретом прерываний, эмбеддеры так часто и делают. Но по теории реализация к.с. опирается на семафоры, и в многозадачках это основной способ.

Но критическая секция - не семафор! Не будем путать "палец, указующий на Луну" с самой Луной. smile.gif


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
defunct
сообщение Mar 13 2006, 15:36
Сообщение #8


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(dxp @ Mar 13 2006, 10:59) *
Прошу прощения, но критическая секция - это не семафор.

Скажем так в виндовс, из объектов синхронизации нет семафора. Наиболее близок к нему RTLCriticalSection по свойствам и по способу применения..
Go to the top of the page
 
+Quote Post
beer_warrior
сообщение Mar 13 2006, 15:47
Сообщение #9


Профессионал
*****

Группа: Свой
Сообщений: 1 065
Регистрация: 8-10-05
Из: Kiev, UA
Пользователь №: 9 380



Цитата
Скажем так в виндовс, из объектов синхронизации нет семафора. Наиболее близок к нему RTLCriticalSection по свойствам и по способу применения..

Стоп, стоп батенька...
А к чему относиться CreateSemapore ?


--------------------
Вони шукають те, чого нема,
Щоб довести, що його не існує.
Go to the top of the page
 
+Quote Post
defunct
сообщение Mar 13 2006, 17:41
Сообщение #10


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(beer_warrior @ Mar 13 2006, 17:47) *
А к чему относиться CreateSemapore ?

Признаю - моя неправда..
Спасибо за наводку, полезно иногда "сесть в лужу" иначе бы я так и не открывал раздел MSDN Synchronization Functions.. тем не менее наличие объекта синхронизации "семафор" в виндовс не отменяет второе, сказанное мной ранее предложение: "Наиболее близок к нему RTLCriticalSection по свойствам и по способу применения.."
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 04:58
Рейтинг@Mail.ru


Страница сгенерированна за 0.01444 секунд с 7
ELECTRONIX ©2004-2016