zoukankan      html  css  js  c++  java
  • Linux串口设备的Canonical and noncanonical mode

    Canonical and noncanonical mode

    可能翻译为规范/非规范模式?

    通过termios结构体的c_lflag成员来设置Canonical or noncanonical mode.

    这两种模式是串口输入相关的配置。

    Canonical模式中:

    • 串口读取的单位是行,行定义为包含行结束符:NL, EOL, EOL2; or EOF at the start of line。read()收到结束符后即返回,其中除了EOF之外(回车符等)与普通字符一样会被read()函数读到缓冲区中。
    • 如何read在没有读到结束符之前意外终止,缓存的数据将被保留。下次read调用将包含这些数据。

    noncanonical模式中:

    • 串口读取的单位是字节,不需要等待任何的结束符,而是由MIN (c_cc[VMIN])和TIME (c_cc[VTIME])的设置来决定read何时返回。


    VMIN和VTIME

    给出定义:

    • VMIN:noncanonical mode中规定read()返回的的最小字节数。
    • VTIME:noncanonical mode中规定read()返回的超时时间(100ms为单位)。

    比如说,存在以下几种情况:

    MIN == 0, TIME == 0 (polling read)

    有数据就返回,返回值是min{当前可用数据长度, 请求数据长度},若没有数据则返回0,不等待。

    请求数据长度:count in ssize_t read(int fd, void *buf, size_t count);


    MIN > 0, TIME == 0 (blocking read)

    直到接受MIN个字节时,read才返回。

    但是若请求数据长度<MIN,read会在读到请求数据长度时提前返回。


    MIN == 0, TIME > 0 (read with timeout)

    调用read()时开始计时,在TIME时间内,若收到数据就返回。


    MIN > 0, TIME > 0 (read with interbyte timeout)

    在收到字节的数据后开始计时。read()返回的原因包括:

    1. TIME时间内,MIN长度的数据已到达。
    2. TIME计时时间到。
    3. TIME时间内,请求数据长度的数据已到达。(POSIX未规定此情况,所以有可能其他系统未实现!)

    所以此类情况下,造成read()返回的返回值必然>0,否则计时器不会开启,read()阻塞在那。


    补充:Linux中标准输入/输出的行缓存

    在linux中有时调用printf()打印却不显示,可能是因为没有加换行符(\n)导致的,这就是Linux中关于标准输入/输出默认是启用行缓存的。其实是与我们上面提到的Canonical mode同样的原理。

    解决的方案有三个:

    1. 手动添加换行符(\n);这种方式具有局限性,因为有的时候换行符会对原始数据造成干扰。

    2. 刷新标准输出缓冲区;

      执行fflush(stdout)将目前缓冲区中的数据发送给输出设备,来刷新缓冲区。

    3. 关闭行缓存;

      setvbuf(stdout,NULL,_IONBF,0);
      

      暴力的关闭输出缓冲区,这样接受到的数据就会直接发送给输出设备了。

  • 相关阅读:
    iOS开发——高级篇——iOS抽屉效果实现原理
    iOS开发——高级篇——FMDB 数据库简单使用
    iOS开发——高级篇——多线程dispatch_apply
    iOS开发——基础篇——get和post请求的区别
    iOS开发——高级篇——线程同步、线程依赖、线程组
    谈谈程序员最讨厌做的事
    iOS开发——高级篇——iOS 项目的目录结构
    iOS开发——高级篇——Runtime实际应用
    程序猿如何“智斗”产品经理
    iOS开发——基础篇——iOS开发 Xcode8中遇到的问题及改动
  • 原文地址:https://www.cnblogs.com/bluettt/p/15416661.html
Copyright © 2011-2022 走看看