实现永远等待的汇编代码
Posted
技术标签:
【中文标题】实现永远等待的汇编代码【英文标题】:Implement assembly code that waits forever 【发布时间】:2021-03-30 20:33:09 【问题描述】:我想在 Arm Linux 中编写简单而简短的汇编代码,永远等待。
label:
b label
这可行,但会占用大量 CPU 时间。
我考虑过使用nanosleep
并每隔X 秒跳转到标签,但是我如何在汇编中使用它?
pause
syscall(在 cmets 中建议)不好,因为该进程有一个信号处理程序。
有简单的方法吗?
【问题讨论】:
是的,你需要一个系统调用,是的,如果没有字符出现在 TTY 上,从 TTY 读取是可以工作的。如果 ARM Linux 有 64 位time_t
,那么 nanosleep 可以等待 2^64-1 秒,这应该足够长了。否则你会想要真正阻塞的东西。至于如何调用系统调用,搜索堆栈溢出(例如 google 与 site:***.com
)以获得 ARM 系统调用,或者只是一般的 google。鉴于手册页和将 C args 映射到寄存器的通用方法(调用约定),您可以调用任何内容。
还有一个pause 系统调用。
@Jester:谢谢,我记得我记得 Linux 有一个这样的系统调用,但马上想不起名字了。当我看到您的评论时正在搜索第 2 节手册页:P
sleep(3) 和 nanosleep 手册页另有说明: sleep() 导致调用线程休眠,直到经过以秒为单位的实时秒数,或者直到一个信号到达,不被忽略。。 libc 包装器可能会在 EINTR 上自动重试/重新启动它?
@yfr24493AzzrggAcom 通常你可以通过在无限循环中调用pause
来解决这个问题。这样,该过程仅在信号到达时短暂运行,然后立即进入睡眠状态。您也可以使用信号掩码或sigsuspend
来暂停并避免传递信号。
【参考方案1】:
是的,您需要一个系统调用,是的,您的两个想法都是可行的。 (虽然nanosleep
被限制为time_t
可以表示的最大秒数。这可能“仅”是 ARM Linux 上的 2^31-1,这是著名的大约 68 年,间隔从 1970 年until 32-bit time overflows in 2038)
不过,Linux 有一个专门用于此的系统调用,pause(2)
:
pause() 导致调用进程(或线程)休眠,直到发出终止进程或导致调用的信号 信号捕捉功能
如果您没有安装信号处理程序,则暂停无法返回,您只能退出(仍然通过按 control-C 来传递 SIGINT),或者通过终止它 (SIGTERM) 或其他正常方式。
如果您确实安装了信号处理程序并希望继续暂停,那么显然您可以在循环中调用它。 (最好这样做,而不是在信号处理程序中调用暂停而不是从它返回)。您只会在短暂的唤醒期间使用 CPU 时间来运行信号处理程序并重新启动主线程的执行,主线程将立即调用内核进行另一次暂停。
sleep 和 nanosleep 也会返回已处理的信号,根据手册页返回 -EINTR
。 (libc 包装函数可能会为您重试/重新启动系统调用,但如果您想使用原始内核调用,则必须自己进行。)
至于如何调用系统调用,搜索堆栈溢出(例如 google 与 site:***.com
)以查找 ARM 系统调用,或者一般只搜索 google。给定手册页和将 C args 映射到寄存器的一般方法(调用约定),您可以调用任何东西。 What is the interface for ARM system calls and where is it defined in the Linux kernel?
暂停不需要任何参数,因此您只需要正确寄存器中的呼叫号码 (__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
(未经测试;我只安装了arm-none-eabi-gcc
,没有安装arm-linux-eabi-gcc
。但确认ARM Linux 头文件确实有__NR_pause,并使用内联asm 检查语法是否组装:https://godbolt.org/z/PerGTx)。
【讨论】:
谢谢。我要暂停的线程有信号处理程序.. @yfr24493AzzrggAcom:那么显然你应该循环调用pause
或nanosleep
。信号处理程序也会使 nanosleep 提前返回,-EINTR
。以上是关于实现永远等待的汇编代码的主要内容,如果未能解决你的问题,请参考以下文章