Реализуйте ассемблерный код, который ждет вечно

Я хочу написать простой и короткий ассемблерный код на Arm Linux, который будет ждать вечно.

label:
b label

Это работает, но требует много процессорного времени.

Я думал об использовании nanosleep и переходе к метке каждые X секунд, но как мне использовать это в ассемблере?

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

Есть ли простой способ сделать это?

Да, вам нужен системный вызов, и да, чтение с TTY может работать, если на нем никогда не будет отображаться никаких символов. Если ARM Linux имеет 64-битную time_t, то да, nanosleep может ждать 2 ^ 64-1 секунды, что должно быть достаточно долго. В противном случае вам понадобится что-то, что действительно блокирует. Что касается того, как вызывать системные вызовы, переполнение стека поиска (например, google с site:stackoverflow.com) для системных вызовов ARM или просто google в целом. Учитывая справочную страницу и общий метод отображения аргументов C в регистры (соглашение о вызовах), вы можете вызывать что угодно.

Peter Cordes 21.12.2020 03:13

Также есть системный вызов pause.

Jester 21.12.2020 03:20

@Jester: Спасибо, я думал, что помнил Linux с таким системным вызовом, но не мог сразу вспомнить название. Искал справочные страницы раздела 2, когда увидел ваш комментарий: P

Peter Cordes 21.12.2020 03:40

Забавный факт, strace sleep infinity показывает, что он также использует pause, я только что нашел и попробовал это тоже.

Peter Cordes 21.12.2020 04:51
strace sleep infinity использовали pause ? Это странно, потому что sleep не нужно возвращать нам сигнал был получен, а pause возвращается, пока сигнал получен
yfr24493AzzrggAcom 21.12.2020 07:12

Справочные страницы sleep(3) и nanosleep документируют иное: sleep() заставляет вызывающий поток спать либо до тех пор, пока не истечет количество секунд реального времени, указанное в секундах, либо пока не прибудет сигнал, который не будет проигнорирован. Оболочка libc может повторить попытку / перезапустить его автоматически на EINTR?

Peter Cordes 21.12.2020 07:17

@ yfr24493AzzrggAcom Обычно вы решаете эту проблему, вызывая pause в бесконечном цикле. Таким образом, процесс выполняется ненадолго при поступлении сигнала, чтобы сразу после этого заснуть. В качестве альтернативы вы можете использовать маски сигналов или sigsuspend, чтобы приостановить и избежать доставки сигналов.

fuz 21.12.2020 13:35
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
1
7
305
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Да, вам нужен системный вызов, и да, обе ваши идеи жизнеспособны. (Хотя nanosleep ограничен максимальным количеством секунд, которое может представлять time_t. Это может быть «всего» 2 ^ 31-1 в ARM Linux, что, как известно, составляет около 68 лет, интервал от 1970 до 32-битного переполнения времени в 2038 году)

Однако в Linux есть специальный системный вызов для этого, pause(2):

pause() заставляет вызывающий процесс (или поток) спать до тех пор, пока не будет доставлен сигнал, который либо завершает процесс, либо вызывает вызов функции захвата сигнала

Если у вас не установлены обработчики сигналов, пауза не может вернуться, вы можете только выйти (по-прежнему нажимая Control-C, что доставляет SIGINT), или убивая его (SIGTERM), или другими обычными способами.

Если у вас установлен обработчик сигналов и вы хотите продолжать делать паузу, то, очевидно, вы можете просто вызвать его в цикле. (Возможно, лучше сделать это вместо того, чтобы вызывать паузу внутри обработчика сигнала, а не возвращаться из него). Вы будете использовать процессорное время только во время этого краткого пробуждения, чтобы запустить обработчик сигнала и перезапустить выполнение основного потока, который немедленно вызовет ядро ​​​​для еще одной паузы.

Sleep и nanosleep также возвращают обработанные сигналы, возвращая -EINTR согласно справочным страницам. (Функции оболочки libc могут повторить/перезапустить системный вызов для вас, но если вы хотите использовать необработанные вызовы ядра, вам придется сделать это самостоятельно.)


Что касается того, как вызывать системные вызовы, переполнение стека поиска (например, google с site:stackoverflow.com) для системных вызовов ARM или просто google в целом. Учитывая справочную страницу и общий метод отображения аргументов C в регистры (соглашение о вызовах), вы можете вызывать что угодно. Что такое интерфейс для системных вызовов ARM и где он определен в ядре Linux?

Пауза не принимает аргументов, поэтому вам просто нужен номер вызова (__NR_pause) в правом регистре:

@ arm_pause.S   - build with gcc -nostdlib arm_pause.S
#include <asm/unistd.h>   // contains only C preprocessor macros,  no C stuff.

.globl _start
_start:
  mov  r7, #__NR_pause
  swi  0x0
  b   _start        @ rerun if interrupted by a signal

(не проверено; у меня установлено только arm-none-eabi-gcc, а не arm-linux-eabi-gcc. Но подтверждено, что заголовки ARM Linux действительно имеют __NR_pause и используют встроенный ассемблер для проверки сборки синтаксиса: https://godbolt.org/z/PerGTx).

Конечно, нет необходимости использовать asm для этого, вы могли бы также использовать while(1){ pause(); } в C, хотя это вызвало бы оболочку libc для системного вызова.

Благодарить . Поток, который я хочу приостановить, имеет обработчик сигнала.

yfr24493AzzrggAcom 21.12.2020 07:06

@ yfr24493AzzrggAcom: Тогда, очевидно, вам следует вызывать pause или nanosleep в цикле. Обработчик сигнала также заставит nanosleep вернуться раньше, с помощью -EINTR.

Peter Cordes 21.12.2020 07:10

Другие вопросы по теме