【问题标题】:open function doesn't return for serial port打开功能不返回串行端口
【发布时间】:2019-08-05 01:46:15
【问题描述】:

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

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

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

我该怎么办?你有什么想法吗?

谢谢

【问题讨论】:

    标签: c linux serial-port


    【解决方案1】:

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

    您需要添加标志O_NONBLOCK

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

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

    *
        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 的行为未指定。

    【讨论】:

    • 设备不忙,因为我可以使用 minicom 打开 ttyUSB0,但 O_NONBLOCK 解决了问题。我不在乎为什么会这样。有用。谢谢。
    • 现在读取函数总是返回成功,即使串行电缆断开。是因为这个阻塞标志吗?
    • 这是因为串行设置错误。现在好了。
    【解决方案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 */ }
    

    【讨论】:

      猜你喜欢
      • 2013-03-29
      • 1970-01-01
      • 1970-01-01
      • 2019-12-23
      • 1970-01-01
      • 1970-01-01
      • 2015-08-24
      • 1970-01-01
      • 2017-10-04
      相关资源
      最近更新 更多