打开功能不返回串行端口

时间:2019-03-14 08:24:59

标签: c linux serial-port

我有一个USB串行端口模块,我想在我的C应用程序中使用它。问题是 open 系统调用未返回!

  

int serialDevice = open(“ / dev / ttyUSB0”,O_RDWR | O_NOCTTY); //不返回

我将用户添加到了拨出组,并且可以使用终端中的minicom来访问端口而无需root访问。因此,这不是许可问题。即使是这样,它也应该立即返回并给出权限错误。但是open函数根本不会返回。

我该怎么办?你有什么主意吗?

谢谢

2 个答案:

答案 0 :(得分:2)

我相信如果设备繁忙等情况,可能会发生这种情况。

您需要添加标志 O_NONBLOCK

  

O_NONBLOCK       使用O_RDONLY或O_WRONLY设置打开FIFO时:   *       如果设置了O_NONBLOCK,则只读的open()将立即返回。如果没有,open()仅用于写操作将返回错误   进程当前已打开文件以供读取。   *       如果清除了O_NONBLOCK,则只读的open()将阻塞调用线程,直到线程打开要写入的文件为止。一个open()   仅用于写将阻塞调用线程直到线程打开   要读取的文件。

     

打开支持的特殊块或字符特殊文件时   非阻塞打开:

*
    If O_NONBLOCK is set, the open() function shall return without blocking for the device to be ready or available. Subsequent behavior
     设备的

是特定于设备的。       *           如果清除了O_NONBLOCK,则open()函数将阻塞调用线程,直到设备准备就绪或可用之前   返回。

     

否则,未指定O_NONBLOCK的行为。

答案 1 :(得分:2)

  

int serialDevice = open(“ / dev / ttyUSB0”,O_RDWR | O_NOCTTY);

除了@darune的答案和O_NONBLOCK,您也可以考虑使用O_SYNC。另请参见How to open, read, and write from serial port in C?

您可能还考虑将文件描述符设为互斥的,以便其他程序(如调制解调器管理器)不会打开设备和muck with your state。由于O_RDWR,排他性很好。另请参阅内核新手邮件列表上的How to make /dev/ttyACM0 (and friends) exclusive?

要使文件描述符互斥,您需要使用ioctlTIOCEXCLO_EXCL不能按预期方式工作,因为它不适合字符设备使用(内核人士说-ENOPATCH)。

int term_config(int fd, int speed)
{
    struct termios tty;
    memset(&tty, 0, sizeof(tty));

    if (tcgetattr(fd, &tty) != 0) {
        log_error("term_config: tcgetattr: %s\n", strerror(errno));
        return -1;
    }

    cfmakeraw(&tty);
    tty.c_cflag |= CLOCAL;   /* ignore status lines   */
    tty.c_cflag |= CRTSCTS;  /* hardware flow control */

    cfsetospeed(&tty,(speed_t)speed);
    cfsetispeed(&tty,(speed_t)speed);

    if (tcsetattr(fd, TCSANOW, &tty) != 0) {
        log_error("term_config: tcsetattr: %s\n", strerror(errno));
        return -1;
    }

    if (ioctl(fd, TIOCEXCL, NULL) != 0) {
        log_error("term_config: ioctl_tty: %s\n", strerror(errno));
        return -1;
    }

    return 0;
}

您会给term_config打电话,例如:

int serialDevice = open("/dev/ttyUSB0", ...);
if (serialDevice == -1) { /* error */ }

int result = term_config(serialDevice, B115200);
if (result != 0) { /* error */ }