You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

cu可读取串口但自研C程序读取阻塞的问题排查与解决

解决方案(感谢评论者)

部分终端默认设置与原始无过滤的串口传输不兼容,添加以下代码即可解决问题,其中有些设置可能是多余的:

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

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

options.c_iflag &= ~(IXOFF | IXANY | BRKINT | ICRNL | INLCR | PARMRK | INPCK | ISTRIP | IXON);
options.c_cflag &= ~(CRTSCTS | CLOCAL | CSIZE | PARENB | CSTOPB);
options.c_cflag |= CREAD | CS8;
options.c_lflag &= ~(ICANON | ISIG | ECHO | ECHOE | ECHONL | IEXTEN);
options.c_oflag &= ~(OPOST);
options.c_cc[VMIN]  = 1;
options.c_cc[VTIME] = 0;

tcsetattr(fd, TCSANOW, &options);
原始问题

我使用运行Ubuntu 20.04的Nvidia Jetson Orin Nano设备,需要通过TTL电平串口连接某设备,已使用合适的USB转串口线,且用户已加入串口设备访问组。

目前使用cu命令可成功访问串口,命令如下:

cu -f -s 115200 -l /dev/ttyUSB0

于是我尝试编写自己的C程序来访问同一设备:

#include <iostream>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <stdio.h>

int main() {
    int r;

    int fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY);
    if (fd == -1) {
        perror("tty ");
        return 1;
    }

    // Get current serial port options
    struct termios options;
    r = tcgetattr(fd, &options);
    if (r < 0) {
        perror("tcgetattr ");
        return 1;
    }

    // Set baud rate to 115200
    cfsetispeed(&options, B115200);
    cfsetospeed(&options, B115200);

    // Disable flow control (CTS and RTS)
    options.c_cflag &= ~CRTSCTS;

    // Set new serial port options
    r = tcsetattr(fd, TCSANOW, &options);
    if (r < 0) {
        perror("tcsetattr ");
        return 1;
    }

    char buf;
    while (1) {
        r = read(fd, &buf, 1);
        if (r < 0) {
            perror("read ");
            return 1;
        }
        printf("%02x\n", 255 & buf);
    }

    close(fd);
    return 0;
}

遗憾的是,该程序无法正常工作:打开串口、执行tcgetattr和tcsetattr均成功,但read操作始终阻塞无响应。

我通过strace分析cu的执行流程(以下为部分跟踪内容),仅发现其检查了锁文件(该文件不存在),未找到其他关键差异,请问我哪里出错了?

谢谢!

[Mostly what precedes this is things like dynamically linking shared object libraries, setting signal handlers, closing already-closed fd's, and trying to access various files that don't exist.]
getpid()                                = 17612
openat(AT_FDCWD, "/var/lock/TMP00000044cc", O_WRONLY|O_CREAT|O_TRUNC, 0644) = 3
write(3, "     17612\n", 11)            = 11
close(3)                                = 0
linkat(AT_FDCWD, "/var/lock/TMP00000044cc", AT_FDCWD, "/var/lock/LCK..ttyUSB0", 0) = 0
unlinkat(AT_FDCWD, "/var/lock/TMP00000044cc", 0) = 0
geteuid()                               = 1000
getuid()                                = 1000
getegid()                               = 1000
getgid()                                = 1000
setregid(1000, 1000)                    = 0
setreuid(1000, 1000)                    = 0
openat(AT_FDCWD, "/dev/ttyUSB0", O_RDWR|O_NONBLOCK) = 3
geteuid()                               = 1000
getuid()                                = 1000
getegid()                               = 1000
getgid()                                = 1000
setregid(1000, 1000)                    = 0
setreuid(1000, 1000)                    = 0
fcntl(3, F_GETFD)                       = 0
fcntl(3, F_SETFD, FD_CLOEXEC)           = 0
faccessat(AT_FDCWD, "/dev/ttyUSB0", R_OK|W_OK) = 0
fcntl(3, F_GETFL)                       = 0x20802 (flags O_RDWR|O_NONBLOCK|O_LARGEFILE)
fcntl(3, F_SETFL, O_RDWR|O_LARGEFILE)   = 0
ioctl(3, TCGETS, {B115200 -opost -isig -icanon -echo ...}) = 0
ioctl(3, TCFLSH, TCIFLUSH)              = 0
ioctl(3, TCGETS, {B115200 -opost -isig -icanon -echo ...}) = 0
ioctl(3, SNDCTL_TMR_START or TCSETS, {B115200 -opost -isig -icanon -echo ...}) = 0
ioctl(3, TCGETS, {B115200 -opost -isig -icanon -echo ...}) = 0
ioctl(3, TIOCSCTTY, 0)                  = -1 EPERM (Operation not permitted)
ioctl(3, TCGETS, {B115200 -opost -isig -icanon -echo ...}) = 0
ioctl(3, SNDCTL_TMR_START or TCSETS, {B115200 -opost -isig -icanon -echo ...}) = 0
ioctl(3, TCGETS, {B115200 -opost -isig -icanon -echo ...}) = 0
ioctl(3, TCGETS, {B115200 -opost -isig -icanon -echo ...}) = 0
ioctl(3, SNDCTL_TMR_STOP or TCSETSW, {B115200 -opost -isig -icanon -echo ...}) = 0
ioctl(3, TCGETS, {B115200 -opost -isig -icanon -echo ...}) = 0
faccessat(AT_FDCWD, "/dev/ttyUSB0", R_OK|W_OK) = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x2), ...}) = 0
write(1, "\7Connected.\n", 12)          = 12
ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(0, SNDCTL_TMR_START or TCSETS, {B38400 -opost -isig -icanon -echo ...}) = 0
ioctl(0, TCGETS, {B38400 -opost -isig -icanon -echo ...}) = 0
pipe2([4, 5], 0)                        = 0
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xffffa25c8d00) = 17613
close(5)                                = 0
read(0, 0xffffe67adad6, 1)              = ? ERESTARTSYS (To be restarted if SA_RESTART is set)
--- SIGTERM {si_signo=SIGTERM, si_code=SI_USER, si_pid=17614, si_uid=1000} ---
rt_sigreturn({mask=[]})                 = -1 EINTR (Interrupted system call)
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=17613, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
ioctl(0, TCGETS, {B38400 -opost -isig -icanon -echo ...}) = 0
ioctl(0, SNDCTL_TMR_START or TCSETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0
write(2, "cu: Got termination signal\n", 27) = 27
ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(0, SNDCTL_TMR_START or TCSETS, {B38400 -opost -isig -icanon -echo ...}) = 0
ioctl(0, TCGETS, {B38400 -opost -isig -icanon -echo ...}) = 0
close(4)                                = 0

内容的提问来源于stack exchange,提问作者Timothy Miller

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 16:27:03