Я пишу программу на C, в которой мне приходится периодически (каждую секунду) выполнять множество задач. Доступных потоков ЦП может быть меньше, чем количество задач. Я могу просто создать отдельный поток для каждой задачи, но... мы учимся, переусердствуя с чем-то, и поэтому я хочу сделать задержку как можно меньшей и сэкономить циклы процессора. Это предполагает ручное вытесняющее планирование.
У меня будет очередь задач в глобальной памяти, расположенная в порядке возрастания их приоритета. Каждый поток захватит задачу для выполнения (атомарно синхронизированный поток). Как только задача потребует приостановки до следующего интервала, мы начнем выполнять другие задачи. Функция main будет периодически выдавать сигнал всем потокам, указывая, что началась (или запустится) новая секунда и все задачи необходимо перевыполнить от высшего к низшему приоритету. Каждый поток получит сигнал, а ядро переключит контекст на обработчик сигнала. Все наши задачи представляют собой сопрограммы без стека, управляемые операторами переключения и вручную увеличивающие переменную в каждом блоке кода, поэтому не имеет значения, прерываются ли они на уровне инструкций, поскольку этот выход может быть запущен снова (будет обеспечивать асинхронную безопасность). Теперь в обработчике сигнала мы можем начать перезапускать задачи в соответствии с их приоритетом. Если все задачи завершены до следующего интервала, все потоки спят до доставки сигнала.
Если один поток возобновляет задачу, наполовину выполненную другим потоком, нам потребуется перенести локальное хранилище. Все это создает копию хранилища всех задач в стеке каждого потока. Мы могли бы прикрепить к цепочке только избранные задачи, но это противоречит всей цели. Есть ли способ освободить память стека потока после полного выполнения задачи?
Я использую сигналы, потому что они обеспечивают асинхронное прерывание. Что-то вроде timerfd или signalfd требует опроса, которого я хочу избежать.
У этого подхода есть несколько проблем. Обратите внимание, что я не использовал технические термины, такие как функции и указатели на функции. Если бы я использовал функции, они никогда бы не возвращались. Продолжая переключаться между различными функциями, мы продолжаем создавать новые кадры стека. По сути, я никогда не смогу вызвать функцию задачи. Что мы можем использовать, так это просто операторы goto и указатели меток для прямого перехода к инструкциям задачи.
Теперь проблема, с которой я столкнулся, заключается в том, что когда поток получает сигнал, ядро принудительно переключает контекст, сохраняя состояние процессора в стеке, а также вызывая функцию обработчика сигнала, которая также попадает в стек. Но если в функции обработчика сигнала я собираюсь перейти оттуда к блоку кода и никогда не возвращаться, стек будет продолжать накапливаться. Обычно, как только мы выходим из функции-обработчика, ядро снова переключает контекст, восстанавливая регистры ЦП, и выполнение начинается с того места, где оно было первоначально. Это то, что я знаю и могу ошибаться. Но здесь мы никогда не выходим из функции-обработчика. Поскольку наши задачи представляют собой сопрограммы без стека, мне даже не нужно сохранять состояние процессора.
Поэтому по сути я хочу перейти к метке вместо вызова функции в качестве обработчика сигнала.
Подробнее здесь: https://stackoverflow.com/questions/798 ... tead-of-pe
<Низкоуровневый C, специфичный для Linux> Необходимо выполнить переход сигнала на метку вместо выполнения вызова функции ⇐ Linux
1771644742
Anonymous
Я пишу программу на C, в которой мне приходится периодически (каждую секунду) выполнять множество задач. Доступных потоков ЦП может быть меньше, чем количество задач. Я могу просто создать отдельный поток для каждой задачи, но... мы учимся, переусердствуя с чем-то, и поэтому я хочу сделать задержку как можно меньшей и сэкономить циклы процессора. Это предполагает ручное вытесняющее планирование.
У меня будет очередь задач в глобальной памяти, расположенная в порядке возрастания их приоритета. Каждый поток захватит задачу для выполнения (атомарно синхронизированный поток). Как только задача потребует приостановки до следующего интервала, мы начнем выполнять другие задачи. Функция main будет периодически выдавать сигнал всем потокам, указывая, что началась (или запустится) новая секунда и все задачи необходимо перевыполнить от высшего к низшему приоритету. Каждый поток получит сигнал, а ядро переключит контекст на обработчик сигнала. Все наши задачи представляют собой сопрограммы без стека, управляемые операторами переключения и вручную увеличивающие переменную в каждом блоке кода, поэтому не имеет значения, прерываются ли они на уровне инструкций, поскольку этот выход может быть запущен снова (будет обеспечивать асинхронную безопасность). Теперь в обработчике сигнала мы можем начать перезапускать задачи в соответствии с их приоритетом. Если все задачи завершены до следующего интервала, все потоки спят до доставки сигнала.
Если один поток возобновляет задачу, наполовину выполненную другим потоком, нам потребуется перенести локальное хранилище. Все это создает копию хранилища всех задач в стеке каждого потока. Мы могли бы прикрепить к цепочке только избранные задачи, но это противоречит всей цели. Есть ли способ освободить память стека потока после полного выполнения задачи?
Я использую сигналы, потому что они обеспечивают асинхронное прерывание. Что-то вроде timerfd или signalfd требует опроса, которого я хочу избежать.
У этого подхода есть несколько проблем. Обратите внимание, что я не использовал технические термины, такие как функции и указатели на функции. Если бы я использовал функции, они никогда бы не возвращались. Продолжая переключаться между различными функциями, мы продолжаем создавать новые кадры стека. По сути, я никогда не смогу вызвать функцию задачи. Что мы можем использовать, так это просто операторы goto и указатели меток для прямого перехода к инструкциям задачи.
Теперь проблема, с которой я столкнулся, заключается в том, что когда поток получает сигнал, ядро принудительно переключает контекст, сохраняя состояние процессора в стеке, а также вызывая функцию обработчика сигнала, которая также попадает в стек. Но если в функции обработчика сигнала я собираюсь перейти оттуда к блоку кода и никогда не возвращаться, стек будет продолжать накапливаться. Обычно, как только мы выходим из функции-обработчика, ядро снова переключает контекст, восстанавливая регистры ЦП, и выполнение начинается с того места, где оно было первоначально. Это то, что я знаю и могу ошибаться. Но здесь мы никогда не выходим из функции-обработчика. Поскольку наши задачи представляют собой сопрограммы без стека, мне даже не нужно сохранять состояние процессора.
Поэтому по сути я хочу перейти к метке вместо вызова функции в качестве обработчика сигнала.
Подробнее здесь: [url]https://stackoverflow.com/questions/79892322/low-level-linux-specific-c-need-to-make-a-signal-jump-to-a-label-instead-of-pe[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия