我试着通过C代码弹出我的光驱,但它不想工作ioctl返回“5”I/O错误,哪里可能有问题?
#include <stdio.h>
#include <fcntl.h>
#include <linux/cdrom.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
int eject_cdrom()
{
char path_to_cdrom[20]="/dev/cdrom";
int fd = open("/dev/cdrom", O_RDONLY| O_NONBLOCK);
printf("%d\n",fd );
int lala = ioctl(fd, CDROMEJECT);
printf("%d\n",lala);
close(fd);
return lala;
}
int main(int argc, char* argv[])
{
//eject_cdrom_system();
int value = eject_cdrom();
printf("%d\n",value );
if (value == -1)
{
int errsv = errno;
printf("somecall() failed\n");
printf("%d\n",errsv );
}
return 0;
}
当我尝试这个功能时
void eject_cdrom_system()
{
system("/usr/bin/eject");
}
它工作得很好但我想通过第一个函数(弹出光盘)来完成。
strace的输出:
strace-f./光盘
execve("./cdrom", ["./cdrom"], [/* 76 vars */]) = 0
brk(0) = 0xf9c000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fcb50cd7000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=131512, ...}) = 0
mmap(NULL, 131512, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fcb50cb6000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\320\37\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1845024, ...}) = 0
mmap(NULL, 3953344, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fcb506f1000
mprotect(0x7fcb508ad000, 2093056, PROT_NONE) = 0
mmap(0x7fcb50aac000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bb000) = 0x7fcb50aac000
mmap(0x7fcb50ab2000, 17088, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fcb50ab2000
close(3) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fcb50cb5000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fcb50cb3000
arch_prctl(ARCH_SET_FS, 0x7fcb50cb3740) = 0
mprotect(0x7fcb50aac000, 16384, PROT_READ) = 0
mprotect(0x600000, 4096, PROT_READ) = 0
mprotect(0x7fcb50cd9000, 4096, PROT_READ) = 0
munmap(0x7fcb50cb6000, 131512) = 0
open("/dev/cdrom", O_RDONLY|O_NONBLOCK) = 3
ioctl(3, CDROMEJECT, 0) = -1 EIO (Input/output error)
close(3) = 0
exit_group(0) = ?
+++ exited with 0 +++
最佳答案
为了让那些在谷歌之外闲逛的人受益,我将列出所有可能的原因:
您在代码中显式指定了/dev/cdrom
,但允许eject
自动检测。
有些发行版不将/dev/cdrom
设置为/dev/sr0
或等效的符号链接有点像“插上电源了吗?”问题,但包括完整性。
我不确定原始ioctl是否能解析符号链接
可能是/usr/bin/eject
必须进行额外的API调用才能获得成功。
你只是假设eject
将使用这个API
根据man eject
,/usr/bin/eject
实用程序支持至少四种不同的弹出api,其中两种api(CDROM和SCSI)可以应用于光学设备。
实际上,我在我的系统上测试了这个,当我通过使用eject
选项运行-r
来强制使用您正在使用的API时,它失败了,并出现了相同的错误。
$ eject -r /dev/cdrom
eject: unable to eject, last error: Input/output error
但是,强制使用SCSI API(它被扩展到还包括SATA和PATA)对我来说是可行的。
$ eject -s /dev/cdrom