我有一个线程循环调用 SourceDataLine.write(...) 直到所有音频数据被写入(播放)。我希望能够提前停止播放(在循环通常被 EOF 类型条件终止之前)并(尝试)使用中断。当我调用playbackThread.interrupt()时,它只会偶尔导致线程的中断和终止。代码中的微小更改或连续调用会产生不同的(看似随机的)结果。我已经调试并尝试使用 Thread.currentThread.isInterrupted() 而不是 Thread.interrupted()。我注意到,如果我用其他东西(例如长计数循环)替换 SourceDataLine.write(...) 调用,线程确实会以可预测且一致的方式终止。
SourceDataLine.write(...) 是否“消耗”中断但不抛出 InterruptedException?意思是,它是否清除中断标志(可能使用 Thread.interrupted()),忽略它,然后继续?这可以解释为什么中断会间歇性地工作:如果它发生在 SDL.write(...) 方法中,则它会被丢弃;否则,它会保持“完整”,直到我使用 Thread.interrupted() 调用进行测试。这将是可怕的,但这是我花了一整天时间后能想到的唯一解释。我找不到 SourceDataLine.write(...) 的任何来源,因为它是一个接口,并且(我想)实现是依赖于机器的。
由于我没有使用 try/catch 并期望在循环中捕获 InterruptedExeption,而是在每次循环的底部调用 Thread.interrupted() (或 Thread.currentThread.isInterrupted()),因此我可以轻松创建我自己的中断标志并测试它。这正是我几个月前在赶时间赶进度时中断 TargetDataLine.read(...) 方法时所做的事情。我花了周末的大部分时间来一劳永逸地调查这个长期存在的谜团的根源,但没有成功。
使用实际的 Java 中断机制似乎更一致/更优雅 - 但如果它不起作用,则不然。这个解释可信吗?
播放线程代码:
public void run() {
int offset = 0;
int remaining = cRawAudioBuffer.length;
int length = WRITE_LENGTH;
int bytesWritten = 0;
cOutputLine.start();
while (remaining>0) {
length = Math.min(length,remaining);
bytesWritten = cOutputLine.write(cRawAudioBuffer,offset,length);
offset += bytesWritten;
remaining -= bytesWritten;
if (Thread.currentThread().isInterrupted()) {
System.out.println("I Was interrupted");
break;
}
} …Run Code Online (Sandbox Code Playgroud) 我正在阅读Oracle 文档中的中断。我无法弄清楚以下部分。它指出
如果线程长时间不调用抛出 InterruptedException 的方法怎么办?然后它必须定期调用 Thread.interrupted,如果收到中断则返回 true。例如:
for (int i = 0; i < inputs.length; i++) {
heavyCrunch(inputs[i]);
if (Thread.interrupted()) {
// We've been interrupted: no more crunching.
return;
}
}
Run Code Online (Sandbox Code Playgroud)
我绞尽脑汁地想理解,如果一个线程长时间没有调用抛出 InterruptedException 的方法,这是什么意思?其次,Thread.interrupted()的用法是什么,它是一种线程可以向自身发送中断的方法?这个场景的实际用途是什么?谢谢。
我正在阅读英特尔手册 3A 第 6 章中断和异常处理。
\n\n中断和异常分别有3个来源。
\n\n对于软件生成的中断,它说:
\n\n\n\n\nINT n 指令允许通过提供中断向量号作为操作数从软件内部生成中断。例如,INT 35 指令强制隐式调用中断 35 的中断处理程序。从 0 到 255 的任何中断向量都可以用作该指令中的参数。然而,如果使用处理器 xe2x80x99 预定义的 NMI 向量,则处理器的响应将与以正常方式生成的 NMI 中断的响应不同。如果在此指令中使用向量号 2(NMI\n 向量),则会调用 NMI 中断处理程序,但不会激活处理器\xe2\x80\x99s NMI 处理硬件。\n 软件中生成的中断INT n 指令不能被 EFLAGS 寄存器中的 IF 标志屏蔽。
\n
对于软件生成的异常,它说:
\n\n\n\n\nINTO、INT 3 和 BOUND 指令允许在软件中生成异常。这些指令允许在指令流中的点处执行异常条件检查。例如,INT 3 会导致生成断点异常。INT\nn指令可用于模拟软件中的异常;但有一个限制。如果 INT n 为架构定义的异常之一提供向量,则处理器会生成正确向量的中断(以访问异常处理程序),但不会将错误代码推送到堆栈上。即使相关的硬件生成的异常通常会产生错误代码,情况也是如此。在处理异常时,异常处理程序仍会尝试从堆栈中弹出错误代码。由于没有推送错误代码,处理程序将弹出并丢弃 EIP(代替丢失的错误代码)。这会将返回值发送到错误的位置。
\n
那么,有什么区别呢?似乎都利用了int n指令。如何判断一段汇编代码中是否产生异常或中断?
我基于 MikeOS 引导加载程序(链接)制作了一个非常基本的引导加载程序。我使用 NASM 和 QEMU 进行组装和测试。我正在尝试为我的操作系统启用保护模式。因此,我开始在网上搜索更多详细信息并了解有关 BIOS 中断的更多信息。我偶然发现了维基百科并阅读了一篇文章......
许多现代操作系统(例如 Linux 和较新版本的 Windows)完全绕过内置 BIOS 中断通信系统,更喜欢使用自己的软件直接控制连接的硬件。最初的原因主要是这些操作系统以保护模式运行处理器,而调用 BIOS 需要切换到实模式并再次返回,而切换到实模式的速度很慢。然而,也有严重的安全原因不切换到实模式,并且 BIOS 代码在功能和速度上都有限制(来源:维基百科(链接))
维基百科上的文章说
.....主要是这些操作系统以保护模式运行处理器,而调用BIOS需要切换到实模式并再次返回,而切换到实模式很慢......
(来源:维基百科(链接))
根据我的理解,在保护模式下的程序中不建议使用太多BIOS中断all,对吗?如果我是对的,那么我的引导加载程序还使用许多 BIOS 中断在屏幕上打印字符......这是好是坏?如果不好,为什么?我需要进行哪些更改才能创建打印字符程序?
由于我想让我的操作系统进入保护模式,我很困惑是否应该使用 BIOS 中断?目前我已经制作了一个仅在屏幕上打印字符串的引导加载程序,目前我的引导加载程序中没有使用任何 BIOS 中断的任何其他功能。如果在保护模式下使用 BIOS 中断不好,那么当我在保护模式下加载内核时(当我创建它时:p),我应该如何处理打印字符串功能?
还,
许多现代操作系统(例如 Linux 和较新版本的 Windows)完全绕过内置 BIOS 中断通信系统,更喜欢使用自己的软件直接控制连接的硬件。(来源:维基百科(链接))
这些开发人员如何能够开发这些软件?这些软件是用汇编语言还是其他语言制作的?他们需要深厚的硬件软件知识吗?如果可以在我的操作系统中制作这些软件,那么我正在考虑添加这些...是否建议这样做,或者我应该只使用 BIOS 中断?
我即将用 CLINT 编写我自己的 RV32I 内核。然而,有一些事情对我来说并不完全清楚。至少我在文档中找不到它。以下是特权 isa 规范对 ecall/ebreak 的说明:
ECALL 和 EBREAK 导致接收特权模式的 epc 寄存器被设置为 ECALL 或 EBREAK 指令本身的地址,而不是后续指令的地址。
所以这意味着,为 mret 设置正确的 mepc 是 SW 处理程序的责任。我认为这种行为也适用于所有其他例外。
异步中断呢?硬件是否自动将 mepc 设置为 PC+4?从我在不同软件处理程序中看到的情况来看,似乎是这样,但实际上我在文档中找不到它。
希望有人能指出我正确的文档。
尝试在测试引导加载程序上实现硬件中断。例外正在工作(因此发现它是 GPF)。当尝试时sti,会发生 GPF。这是我的主要代码:
cli
lgdt [gdt_desc]
lidt [idt_desc]
mov eax, cr0
or eax, 1
mov cr0, eax
jmp 0x8:bit_32
bit_32:
[bits 32]
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov eax, 0x8000
mov esp, eax
mov ebp, esp
sti ; exception raised
Run Code Online (Sandbox Code Playgroud)
这就是我的 GDT 的样子:
start_gdt:
null:
dd 0x0
dd 0x0
code:
dw 0xffff
dw 0x0
db 0x0
db 10011010b
db 01000000b
db 0x0
data:
dw 0xffff …Run Code Online (Sandbox Code Playgroud) 子例程由程序指令调用以执行调用程序所需的功能。而中断是由输入操作或硬件错误等事件启动的。但处理器如何区分它们呢?
我在网上的一些教程中读到,中断的分支地址已经硬连线.他们为什么需要在引导程序中创建IVT?
如果按下外部停止键,我试图逃离主循环.目前,通过RS485通信将AT32UC与ATmega128通信,其中实现了START和STOP键.如果在接收器侧有要处理的数据,则调用RS485接收器中断,其中0x10 =开始,0x11 =停止.
我的问题是启动和停止键被很好地识别并且如果启动则继续主循环,并且如果按下停止键我想终止主循环.所以我相应地设置了开始标志和停止标志.但是,我正在努力停止(逃避)实施.下面是中断例程和主循环的简要片段.
__attribute__((__interrupt__)) static void rs485RxInterrupt(void)
{
uint32_t data;
static char RxDatalength = 98;
data = AVR32_USART2.RHR.rxchr;
if(data & 0x00000100) // rs485 9 bit check
{
if((data & 0x000000ff) == 0x92) //dsp board address = 0x92
{
rxBuf[0] = data;
addr_flag = true;
rxInCtr = 1;
}
else
{
addr_flag = false;
return;
}
}
else if (addr_flag == true) // if 9 bit is checked
{
rxBuf[rxInCtr++] = data;
if(rxInCtr == 2) // command check
{
if(data …Run Code Online (Sandbox Code Playgroud) 我遇到一种情况,即spin_lock()在多个中断之间的间隔太短的情况下,在工作队列中使用它会使系统挂起。更改spin_lock()为down_interruptible()问题后,暂时消失了。
但是,我看到了在内核代码中使用了下半部分的实现,而不是使用spin_lock()了互斥锁/信号量(例如,中的irq-function request_threaded_irq())。那是什么原因呢?我最好的猜测是,在这种情况下,互斥体/ sempahore可能会过大。