代码之家  ›  专栏  ›  技术社区  ›  Trevor

用C读写串行口

  •  0
  • Trevor  · 技术社区  · 16 年前

    我正在写一个C程序,它将从串行端口读写。每次写入之后都会有一个读操作,该读操作将包含基于写入操作的数据。我将要执行大约16种不同的写入操作,每种操作后面都有一个读取操作。

    我对串行编程还是个新手,我正在尝试确定如何处理这个问题。程序是否应该在每次写入/读取期间阻塞(基本上有一个大的while(1)写入和读取循环)?

    是否可以让一个线程发送写操作,而另一个线程执行读操作?是否可以创建回调以允许线程知道何时可以从串行端口读取数据?

    谢谢你的帮助。

    编辑:

    操作系统:Linux

    2 回复  |  直到 16 年前
        1
  •  1
  •   mvds    16 年前

    这听起来像是一个简单的循环,读写就足够了。如果你想要更多的控制(比如在没有输入的x秒后写一个keep-alive),使用 select poll ;它们允许您“感知”数据是否可用,因此 read 不会阻塞(但是,如果在select和read之间发生了什么,您仍然应该读取非阻塞)。在这种情况下,多线程是没有意义的。

    选择 民意测验 还允许您测试写入是否会阻塞;同样,要确定是否写入非阻塞。通常,除了 选择 民意测验 ,就是这样。(至少,我没有)

    使用 ioctl 在串行线路上设置各种参数。使用

    $ strace -o /tmp/strace.minicom -f minicom
    

    启动minicom(或任何其他终端程序)并查看它们如何使事情正常工作,如果你被卡住了。和往常一样,看 man select/poll/read/ioctl 更多信息。

        2
  •  0
  •   nategoose    16 年前

    一般来说,有几种方法可以解决这个问题。最佳选择可能取决于您在读取串行端口时查看的数据类型以及如何处理该数据中的错误。

    第一种方法是打开串行文件阻止IO,然后执行以下操作:

    while (question) {
        write(ser_fd, question.data, question.len);
        sleep(1);
        ioctl(ser_fd, FIONREAD, &answer.len);
        answer.data = realloc(answer.data, answer.len);
        read(ser_fd, question.answer, question.answer_len);
        question = next(question);
        answer = next(answer);
    }
    

    虽然我没有做任何错误处理。

    如果你想在串行端口等待回复时超时,那么这会改变很多事情。您应该研究使用select、pselect、poll、ppoll或epoll系列系统调用。这些允许您的程序阻塞(睡眠),直到有数据准备好读取。然后,您可以循环进行投票并阅读,直到您完成了您的答案或时间用完。

    另一种选择是尝试使用sigio,但我不推荐这样做。要正确处理这个问题并不容易,调试也很困难。

    此外,您可以使用sigalrm将您从读取调用中删除,以作为超时。

    如果您试图使用stdio输入和输出例程,那么这就更困难了。您将陷入像第一个方法这样的困境,而无法询问准备了多少数据。