Кажется, я начинаю понимать, о чем вы.
Но какой смысл в такой процедуре, зачем вам вообще значение «TimerCounter», если ваша система не гарантирует точность меньше max(TimerCounter), достаточно значения High. А если вы гарантируете такую точность, то входными данными для данной процедуры должно быть — во время ее выполнение возможно только одно прерывание таймера.
И это надо проверять на случай сбоя.
Если сравнивать вашу процедуру с процедурой из книжки, в случае одного прерывания во время выполнения они эквивалентны. А в случае нескольких прерываний, более эффективна, т.к. возвращает первое подходящее значение.
Но во втором случае это означает, что ваша система не гарантирует точность меньше max(TimerCounter). И ее (процедуру) можно упростить.
unsigned long int GetTimer(void) {
return (High<<sizeof(int))+0;
}
1) выставляем (к примеру) 1 на выходе,
2) считываем текущее время (реально сейчас, на момент возврата из функции, 12.02, а мы считываем 11.02), но единица установлена уже не меньше чем 1.00,
3) прибавляем к нему требуемую задержку (к примеру 0.30, получаем 11.32),
… делаем что-то
4) читаем текущее время и сравниваем с границей (реально сейчас 12.14, и мы считываем 12.14),
5) если граница перейдена, снимаем 1 с выхода (12.14 > 11.32, снимаем 1 с задержкой как минимум 0.12+1.00=1.12 вместо 0.30).
Но позвольте, какое отношение это имеет к ОСРВ. Если вас устраивает такая точность, тогда весь код должен быть(повторюсь):
unsigned long int GetTimer(void) {
return (High<<sizeof(int))+0;
}
Не, мой вариант не правильный.
Кстати, первый «правильный», тоже не правильный.
unsigned long int GetTimer(void) {
DisableInt();
unsigned long TmpH=High;
if (TimerOvBit()) TmpH++; //Это условие не сработало здесь.
//А Здесь происходит переполнение и следующей строкой "ReadReg", вместо значения близкого к максимуму, считает близкое к нулю.
TmpH=(TmpH<<sizeof(int))+ ReadReg(TimerCounter);
EnableInt();
return Tmp;
}
Единственный правильный вариант:
unsigned long int GetTimer(void) {
unsigned long TmpH,TmpL;
do {
TmpH=High;
TmpL= ReadReg(TimerCounter);
while (TmpH!=High);
return (TmpH<<sizeof(int))+TmpL;
}
А если нужно предотвратить зависание, нужно ввести счетчик циклов.
Да не работает ваш алгоритм в определенных условиях. Например, если значение High может измениться более чем один раз во время вызова функции (см. мои комментарии и мой вариант ниже):
unsigned long int GetTimer(void) {
unsigned long TmpHFirst,TmpH,TmpL;
TmpHFirst=High;
TmpL= ReadReg(TimerCounter);
if (TmpHFirst!=(TmpH=High)) {
//Вот тут произошло прерывание, изменилось значение High, а вы уже считали старое.
TmpL= ReadReg(TimerCounter); // Считываете значение соответствующее новому значению High.
}
return (TmpH<<sizeof(int))+TmpL;
}
unsigned long int GetTimer(void) {
unsigned long TmpH,TmpL;
TmpH=High;
TmpL=ReadReg(TimerCounter);
if ( TmpH+1 == High ) TmpL=ReadReg(TimerCounter);
if ( TmpH != High || TmpH++ != High ) exit(error);
return (TmpH<<sizeof(int))+TmpL;
}
Многовато if, но вроде должно работать. Заодно своеобразный watchdog получился.
А если значение High во время вызова функции может увеличится более чем один раз, и это нормально, тогда функция должна быть такой:
unsigned long int GetTimer(void) {
return (High<<sizeof(int))+0;
// Или просто
return High;
}
Но это мое мнение. И вполне могу предположить что оно не верное.
Если в вашей системе возможно что-то отличное от следующего:
unsigned long int GetTimer(void) {
unsigned long TmpH,TmpL;
TmpH=High;
TmpL= ReadReg(TimerCounter);
if ( TmpH != High || TmpH++ != High ) exit(error);
return (TmpH<<sizeof(int))+TmpL;
}
то значение «TimerCounter» для вас не должно иметь смысла(ИМХО). И вы его можете просто не учитывать (выполнять округление).
чтобы он для каждого интерфейса дефолтный роут (и все остальные роуты) засовывал в эту таблицу.
Легко. Надо только свой доп. скриптик положить в директорию dhclient.d.Если надо, могу опубликовать у меня для СентОС6 и Демьяна6 где-то было, там все просто, сделано на основе Демьяновского debug скрипта. Кстати, если вы не увеличите приоритет правила для таблицы main (ip rule add table main pref 3050). То скорее всего из локальной сети вам будет доступен только шлюз. Если вас не интересуют другие машины в локальной сети, например из диапазона 188.188.188.2-187,189-254, то можно не заморачиваться.
А почему вы про приоритеты не упомянули? На мой взгляд, их лучше указывать вручную. Очень гибкая вещь. И про встроенные таблицы тоже сказать нужно, в какой последовательности они обрабатываются ядром.
Приятная новость: policy routing имеет более высокий приоритет, чем dhcp'шный default route, так что обновление аренды не сломает маршрутизацию.
Тут как раз не нужно default route получать по dhcp и прописывать его в таблицу «main», вы же его уже настроили для каждого интерфейса, получайте по dhcp только адрес. А если у вас в главной таблице не будет маршрута по умолчанию. То можно сделать так:
ip rule add table main pref 3050
Главное чтобы приоритет был ниже (по номеру), чем у правил для таблиц по умолчанию (в вашем случае, скорее всего, у них 3276{5,4,3}).
ip rule будет выдавать что-то наподобие:
0: from all lookup local
3050: from all lookup main
32763:…
32764:…
32765: from 188.188.188.188 lookup eth0-route
32766: from all lookup main
32767: from all lookup default
Не большое замечание по безопасности.
Как вы правильно упомянули в примечание. Крайне не желательно расширять это правило на сеть (from 188.188.188.0/24). И даже если указан только ваш IP. Возможен такой сценарий:
Кто-то из сети 188.188.188. пошлет от вашего имени (подменив свой IP адрес на 188.188.188.188) вам пакет на любой другой адрес в Интернет, то ваш комп., согласно вашим правилам маршрутизации (32765: from 188.188.188.188 lookup eth0-route), в зависимости от настроек iptables, может переслать его по назначению.
А я думал что для конфиденциальности нужно использовать PKI: Инфраструктура открытых ключей.
Если хотите отправить мне конфиденциальное сообщение зашифруйте его с помощью моего открытого ключа. И никто не сможет, кроме меня прочитать, даже если случайно получит. Для надежности подпишите его своим ключом. И я буду уверен что это письмо от вас.
Добавьте пользователя a@example1.com в /etc/dovecot/users. В принципе без разницы, какой домен использовать для локальной доставки. В данном случае важно, что все пользователи, обслуживаемых доменов второго уровня, настраиваются в одном файле. И обслуживаются одним агентом доставки — virtual. Локальная почта – отправитель наш сервер и службы запущенные на нем, обслуживается другим агентом доставки local.
Еще способ по старинке, без форматирования:
1. На флешку отформатированную в FAT32 установим grub4dos (если уже установлен, то этот пункт не нужен).
2. Распакуем куда-нибудь iso, скопируем на usb из папки LiveOS оба файла, например, в /BOOT/LIVEOS/CENT70x64,
а из папки isolinux файлы — initrd0.img, vmlinuz0, boot.cat.
3. В загрузочном меню grub сделаем следующий пункт:
где UUID=88AE-DFD0 это UUID нашего раздела на USB.
Таким образом, можно получить usb с различными установочными образами, без необходимости форматировать usb для смены записанного на ней образа. Плюс, можно использовать usb как обычно.
Похожее уже было для Cent6. Для Cent7 добавилось пара параметров.
А о каком интерфейсе идет речь? В коробке при установке можно выбрать: «социальная сеть» и классический — «корпоративный портал», если я не ошибаюсь. Или в контексте статьи это не важно?
Очень печальный результат для теста в тепличных условиях. Без перезаписи, без фрагментации, и таблица не повреждена. Но даже в этом случае результат плохой. Поэтому никогда с флешки не удаляю файлы, а когда заполняется, затираю нулями и по новой форматирую. Так больше вероятность что кластеры для файла будут идти подряд, и удастся что-нибудь восстановить, в случае чего.
Но какой смысл в такой процедуре, зачем вам вообще значение «TimerCounter», если ваша система не гарантирует точность меньше max(TimerCounter), достаточно значения High. А если вы гарантируете такую точность, то входными данными для данной процедуры должно быть — во время ее выполнение возможно только одно прерывание таймера.
И это надо проверять на случай сбоя.
Если сравнивать вашу процедуру с процедурой из книжки, в случае одного прерывания во время выполнения они эквивалентны. А в случае нескольких прерываний, более эффективна, т.к. возвращает первое подходящее значение.
Но во втором случае это означает, что ваша система не гарантирует точность меньше max(TimerCounter). И ее (процедуру) можно упростить.
2) считываем текущее время (реально сейчас, на момент возврата из функции, 12.02, а мы считываем 11.02), но единица установлена уже не меньше чем 1.00,
3) прибавляем к нему требуемую задержку (к примеру 0.30, получаем 11.32),
… делаем что-то
4) читаем текущее время и сравниваем с границей (реально сейчас 12.14, и мы считываем 12.14),
5) если граница перейдена, снимаем 1 с выхода (12.14 > 11.32, снимаем 1 с задержкой как минимум 0.12+1.00=1.12 вместо 0.30).
Но позвольте, какое отношение это имеет к ОСРВ. Если вас устраивает такая точность, тогда весь код должен быть(повторюсь):
Кстати, первый «правильный», тоже не правильный.
Единственный правильный вариант:
А если нужно предотвратить зависание, нужно ввести счетчик циклов.
Многовато if, но вроде должно работать. Заодно своеобразный watchdog получился.
А если значение High во время вызова функции может увеличится более чем один раз, и это нормально, тогда функция должна быть такой:
Но это мое мнение. И вполне могу предположить что оно не верное.
то значение «TimerCounter» для вас не должно иметь смысла(ИМХО). И вы его можете просто не учитывать (выполнять округление).
Тут как раз не нужно default route получать по dhcp и прописывать его в таблицу «main», вы же его уже настроили для каждого интерфейса, получайте по dhcp только адрес. А если у вас в главной таблице не будет маршрута по умолчанию. То можно сделать так:
ip rule add table main pref 3050
Главное чтобы приоритет был ниже (по номеру), чем у правил для таблиц по умолчанию (в вашем случае, скорее всего, у них 3276{5,4,3}).
ip rule будет выдавать что-то наподобие:
0: from all lookup local
3050: from all lookup main
32763:…
32764:…
32765: from 188.188.188.188 lookup eth0-route
32766: from all lookup main
32767: from all lookup default
Не большое замечание по безопасности.
Как вы правильно упомянули в примечание. Крайне не желательно расширять это правило на сеть (from 188.188.188.0/24). И даже если указан только ваш IP. Возможен такой сценарий:
Кто-то из сети 188.188.188. пошлет от вашего имени (подменив свой IP адрес на 188.188.188.188) вам пакет на любой другой адрес в Интернет, то ваш комп., согласно вашим правилам маршрутизации (32765: from 188.188.188.188 lookup eth0-route), в зависимости от настроек iptables, может переслать его по назначению.
Криптография — необходимое, но не достаточное условие конфиденциальности.
Если хотите отправить мне конфиденциальное сообщение зашифруйте его с помощью моего открытого ключа. И никто не сможет, кроме меня прочитать, даже если случайно получит. Для надежности подпишите его своим ключом. И я буду уверен что это письмо от вас.
отправительполучатель1. На флешку отформатированную в FAT32 установим grub4dos (если уже установлен, то этот пункт не нужен).
2. Распакуем куда-нибудь iso, скопируем на usb из папки LiveOS оба файла, например, в /BOOT/LIVEOS/CENT70x64,
а из папки isolinux файлы — initrd0.img, vmlinuz0, boot.cat.
3. В загрузочном меню grub сделаем следующий пункт:
где UUID=88AE-DFD0 это UUID нашего раздела на USB.
Таким образом, можно получить usb с различными установочными образами, без необходимости форматировать usb для смены записанного на ней образа. Плюс, можно использовать usb как обычно.
Похожее уже было для Cent6. Для Cent7 добавилось пара параметров.