注册

Linux报 “inappropriate ioctl for device” 异常的原因以及解决办法

「inappropriate ioctl for device」表示给设备发送了不适当的ioctl命令,通常出现在打开设备或文件时出现,这个错误主要有两个原因:一是设备或文件不支持这个ioctl命令,二是程序使用了错误的ioctl命令。

解决办法有以下几种:

  1. 程序错误

在程序中使用了错误的ioctl命令,需要检查程序中使用的ioctl命令是否正确,有没有错误的拼写或使用。

示例:

int fd = open("/dev/ttyS0", O_RDWR);
if(fd < 0){
    printf("Open serial device failed!\n");
    return -1;
}

struct termios option;
tcgetattr(fd, &option);

option.c_cflag |= (CLOCAL | CREAD);
option.c_cflag &= ~CSIZE;
option.c_cflag |= CS8;
option.c_cflag &= ~CSTOPB;
option.c_cflag &= ~PARENB;

option.c_iflag &= ~(IXON | IXOFF | IXANY);
option.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG);

option.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

cfsetispeed(&option, B115200);
cfsetospeed(&option, B115200);

option.c_cc[VTIME] = 0;
option.c_cc[VMIN] = 1;

if(tcsetattr(fd, TCSANOW, &option) < 0){
    printf("Set serial option failed!\n");
    return -1;
}

int fl = fcntl(fd, F_GETFL, 0);
if(fl == -1){
    printf("Get file status flags failed!\n");
    return -1;
}

if(fcntl(fd, F_SETFL, fl | O_NONBLOCK) == -1){
    printf("Set file status flags failed!\n");
    return -1;
}

struct termios m_oldTermios;
bool m_bTermiosSaved = false;
if(tcgetattr(fd, &m_oldTermios) != -1)
{
    m_bTermiosSaved = true;
    struct termios newTermios = m_oldTermios;
    if( /* optimization to only make changes if necessary */
        newTermios.c_iflag & ~(IXOFF | IXON))
    {
        newTermios.c_iflag &= ~(IXOFF | IXON);
        if(tcsetattr(fd, TCSANOW, &newTermios) == -1)
        {
            qWarning("GsmModule::disableSoftFlowControl: Couldn't set new termios attributes");
        }
    }
}

if(m_bTermiosSaved)
{
    if(tcsetattr(fd, TCSANOW, &m_oldTermios) == -1)
    {
        qWarning("GsmModule::disableSoftFlowControl: Could not restore original tty attributes in the destructor");
    }
}
  1. 设备或文件错误

检查设备或文件是否正确打开,以及设备或文件是否支持使用ioctl命令。

示例:

$ sudo touch /sys/kernel/debug/kgsl/graphics/fb0/bw_writeback_enabled
touch: cannot touch '/sys/kernel/debug/kgsl/graphics/fb0/bw_writeback_enabled': No such file or directory

$ sudo chmod 644 /sys/kernel/debug/kgsl/graphics/fb0/*
chmod: cannot access '/sys/kernel/debug/kgsl/graphics/fb0/*': No such file or directory
  1. 使用正确的ioctl命令

检查程序代码中使用的ioctl命令是否有误,以及是否传入正确的参数。

示例:

int fd;

fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NONBLOCK);
if (fd < 0) {
    perror("open");
    return errno;
}

struct termios tty;
memset(&tty, 0, sizeof(tty));
if (tcgetattr(fd, &tty) != 0) {
    perror("tcgetattr");
    return errno;
}

cfsetospeed(&tty, B115200);
cfsetispeed(&tty, B115200);

tty.c_cflag |= (CLOCAL | CREAD);
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8; /* 8-bit data */
tty.c_cflag &= ~PARENB; /* no parity */
tty.c_cflag &= ~CSTOPB; /* 1 stop bit */
tty.c_cflag &= ~CRTSCTS; /* no flow control */

if (tcsetattr(fd, TCSANOW, &tty) != 0) {
    perror("tcsetattr");
    return errno;
}

ioctl(fd, TCGETS, &tty);

tty.c_cc[VTIME] = 0;
tty.c_cc[VMIN] = 1;

ioctl(fd, TCSETS, &tty);

以上就是Linux报inappropriate ioctl for device的原因以及解决办法,需要根据具体情况适用。