使用 cdaudio 的 cd_eject () 方法弹出音频 CD 如何产生 errno #5?

Posted

技术标签:

【中文标题】使用 cdaudio 的 cd_eject () 方法弹出音频 CD 如何产生 errno #5?【英文标题】:How can ejecting an audio CD by using cdaudio's cd_eject () method produce errno #5? 【发布时间】:2019-05-01 20:16:44 【问题描述】:

我正在尝试使用 cdaudio 库 + 连接到 Raspi 3B 的 USB DVD 驱动器从我的应用程序中播放音频 CD。播放后尝试弹出 CD 总是 让我以 errno #5 告终。这是我的代码:

void sound::Eject ()

  struct disc_status cd_stat;

  if (sound::current_sound_source == CD) 
    sound::Stop ();
    cd_poll (sound::cd_drive_handler, &cd_stat);

    if (sound::is_cd_stopped && cd_stat.status_present == 1) 
      if ((cd_eject (sound::cd_drive_handler)) < 0) cout << "Ejecting CD failed! Error: " << strerror (errno) << endl;
    
  

这是我得到的输出:

ioctl returned -1
Ejecting CD failed! Error: Input/output error

在尝试弹出 CD 时,我听到驱动器中有噪音,好像它要访问 CD 一样,持续了大约半秒钟。这是我正在使用的驱动器:

pi@autoradio:~ $ ls -al /dev/sr*
brw-rw----+ 1 root cdrom 11, 0 Mai  1 21:38 /dev/sr0

不过,从命令行 (eject /dev/sr0) 弹出 CD 确实有效。

有人知道什么可能导致这个错误吗?谢谢。

更新 #1: 我尝试了 cdcd(音频 CD 的命令行工具),我也可以在那里重现错误(即使在 sudo 下):

cdcd> eject
ioctl returned -1

更新 #2: 我发现 cdaudio 使用 CDAUDIO_EJECT 命令调用 ioctl(请参阅 sourcecode),但我在linux/cdrom.h 文件。 根据one of the developers of the cdaudio library,这只是CDROMEJECT 的别名,而不是错误。

更新 #3: strace 给我这个输出。我希望这就足够了:

ioctl(3, CDROM_DISC_STATUS, 0)          = 100
ioctl(3, CDROMSUBCHNL, 0x7e93e308)      = 0
ioctl(3, CDROMEJECT, 0x1)               = -1 EIO (Input/output error)
write(1, "ioctl returned -1\n", 18)     = 18

相比之下,在跟踪 eject 实用程序时,我得到了一些稍微不同的东西:

geteuid32()                             = 1000
open("/dev/sr0", O_RDWR|O_NONBLOCK)     = 3
ioctl(3, CDROMEJECT, 0x1)               = 0
close(3)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++

open () 调用的比较显示cdaudio 库显然以只读模式打开驱动器(理论上这是正确的,但另一方面,似乎阻塞了eject 命令):

open("/dev/sr0", O_RDONLY|O_NONBLOCK)   = 3

另见:问题#26240195

【问题讨论】:

您的系统日志中有任何内容吗? 不!我什么也没找到。 您可能想使用strace 来查看eject 和您的代码的不同之处。 感谢您的提示。查看我的问题的更新,了解我的发现。 那么,如果你改变你的代码来打开设备读/写,它会起作用吗? 【参考方案1】:

好的,在研究eject 实用程序几周后,我发现至少有一些CD 驱动器不能通过ioctl () 接受CDROMEJECT 命令,而是需要一堆SCSI 命令。事实上,eject 包含一个方法,在这种情况下用作备用方法:eject_scsi ()。我将此方法植入cdaudio。测试成功。所以我向cdaudio 的维护者询问了各自的patch.

【讨论】:

以上是关于使用 cdaudio 的 cd_eject () 方法弹出音频 CD 如何产生 errno #5?的主要内容,如果未能解决你的问题,请参考以下文章

秒表的使用方法和技巧(秒表的使用方法)

使用“使用严格”作为“使用强”的备份

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

Sqlmap的使用

Kettle java脚本组件的使用说明(简单使用升级使用)

PageHelp的使用getParameter的使用zpage-nav的使用QRcode的使用wxpay微信支付的使用jackson-xml数据的转换