Напомнить: Как установить напоминание каждые 3 месяца

Это сильно зависит от платформы. Если вы не привязаны к определенной платформе (даже разница между x86-32 и x86-64 является принципиальной), на это невозможно ответить. Но, если ограничиться x86, согласно вашему последнему комментарию, я мог бы предложить некоторую информацию.

Существует два основных стиля служебных запросов («syscall») от пользователя к ядру: стиль прерывания и стиль sysenter. (Эти термины придуманы мной для этого описания.) Запросы в стиле прерывания - это запросы, которые обрабатываются процессором точно так же, как и внешнее прерывание. В защищенном режиме x86 это вызывается с помощью int 0x80 (новее) или lcall 7,0 (самый старый вариант, SysV-совместимый) и реализуется с использованием так называемого шлюза . s (ворота задачи, ворота прерывания и т. Д.), Сконфигурированные как дескрипторы специальных сегментов. Переключение задач выполняется процессором. Во время этого переключения старые регистры задачи, включая указатель стека, сохраняются в старом TSS задачи, а новые регистры задачи, включая указатель стека, загружаются из нового TSS задачи. Другими словами, все «обычные» регистры сохраняются и загружаются (так что это очень долгое действие). (Существует отдельная проблема с состоянием FPU / SSE / и т. Д., Изменение которого откладывается - подробности см. В документации.)

Для обработки таких запросов на обслуживание ядро ​​подготавливает отдельный стек для каждого потока (также известного как LWP - облегченный процесс), потому что поток можно переключить во время любого блокируемого вызова функции. Такой стек обычно имеет небольшой размер (например, 4 КБ).

Поскольку переключение задач x86 всегда изменяет указатель стека, нет возможности повторно использовать стек пользовательской среды для ядра. С другой стороны, такое повторное использование вообще не должно быть разрешено (за исключением небольшого количества данных текущего потока), потому что страница пользовательского процесса может быть небезопасной: другой активный поток может изменить или даже отменить отображение. Вот почему просто запрещено использовать стек пользовательской среды для работы в ядре, поэтому каждый поток должен иметь разные стеки для своего пользователя и уровня ядра; это остается верным для современной обработки в стиле sysenter. (С другой стороны, как уже отмечалось выше, каждый поток должен иметь стек для своего ядра, отличный от другого потока.)

Обработка в стиле Sysenter была разработана намного позже и реализована с помощью инструкций процессора SYSENTER и SYSCALL. Они отличаются тем, что они не были разработаны с учетом старого (слишком жесткого) ограничения, что системный вызов должен сохранять все регистры. Вместо этого они были разработаны более близко к обычному вызову функции ABI, который позволяет функции произвольно изменять некоторые регистры (в большинстве ABI это называется «временными» регистрами), изменяется только несколько регистров, и необходимо сохранять старые значения. доставляется обработчиками. Пара инструкций SYSENTER / SYSEXIT (как для 32, так и для 64-битных) портит старое содержимое RDX и RCX (странным образом - пользовательская среда заполняет их соответствующими значениями), а новые RIP и RSP загружаются из соответствующих MSR, поэтому стек сразу переключился на ядро.В отличие от этого, SYSCALL / SYSRET (только 64-разрядная версия) используют RCX и R11 для адреса возврата и флагов и сами по себе не изменяют стек , а . Позже ядро ​​использует часть этого стека для сохранения нескольких регистров, а затем переключается на собственный стек, потому что 1) нет гарантии, что стек пользовательского уровня достаточно велик, чтобы хранить все необходимые значения, и 2) по соображениям безопасности (см. Выше) . С этого момента у нас снова есть стек ядра для каждого потока.

Помимо потоков пользовательской среды, существует множество потоков только ядра (вы можете увидеть их в выводе ps как имена в квадратных скобках). У каждого такого потока есть свой стек. Они реализуют 1) периодические процедуры, запускаемые по какому-либо событию или таймауту, 2) переходные действия или 3) обрабатывают действия, запрошенные от реальных обработчиков прерываний. (В случае 3 они назвали «bh» в старых ядрах и «ksoftirqd» в новых.) Большая часть этих потоков прикреплена к одному логическому процессору. Как только у них нет земли пользователя, у них нет стека земли пользователя.

Внешние обработчики прерываний ограничены в Linux, AFAIK, не более чем одним одновременно выполняемым обработчиком для каждого логического процессора; во время выполнения такого обработчика прерывания ввода-вывода не допускаются. (NMI - ужасное исключение из-за подверженной ошибкам обработки.) Они приходят с использованием шлюза прерывания переключения задач и имеют собственный стек для каждого логического ЦП по тем же причинам, что и описанные выше.

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

Некоторые детали в этом ответе могут быть устаревшими из-за высокой скорости разработки ядра. Считайте это только общим предложением и сравните его с конкретной версией, которую вы исследуете. Дополнительные сведения об обработке прерываний x86 и переключении задач см.см. «Руководство разработчика программного обеспечения для архитектур Intel® 64 и IA-32, том 3A: Руководство по системному программированию, часть 1» (свободно доступно на веб-сайте Intel).

1
09.11.2018, 09:00
3 ответа

напомнить знает о днях, буднях, месяцах и годах, поэтому каждый месяц можно, но каждые 2 недели или 3 месяца нужно несколько утверждений:

REM 24 Jan MSG My reminder
REM 24 Apr MSG My reminder
REM 24 Jul MSG My reminder
REM 24 Oct MSG My reminder

Если вы сделаете это один раз и не укажете год,у вас есть то, что вам нужно до вечности

1
27.01.2020, 23:31

Если вы не хотите думать о «трех календарных месяцах», вы можете просто указать дату начала и 90-дневный интервал повторения:

REM 2018-11-15 *90 MSG Another 90 days have passed
1
27.01.2020, 23:31

Это «кратко» дает напоминание в исходном вопросе:

REM 24 SATISFY [(monnum(trigdate()) -1 ) % 3 == 0]
IF trigvalid()
    REM [trigdate()] MSG test 3 month
ENDIF

Вот мое понимание логики, но оно может быть не совершенным. REM 24вызывает напоминание 24 числа каждого месяца. Затем SATISFYпроверяет, верно ли условие в квадратных скобках. 'trigdate ()' - это дата, в которую мы находимся, а monnum()возвращает номер текущего месяца из даты срабатывания. Вычтите 1 из возвращенного monthnum , разделите на 3 и посмотрите, равен ли остаток 0 (по модулю оператора % ). Если это правда, продолжайте. Затем remindвводит, еслиIF(может и не быть необходимым, но я следовал примеру на справочной странице )и переходил к фактическому напоминанию.

0
04.12.2021, 20:52

Теги

Похожие вопросы