• 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);
      

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

  • 相关阅读:
    Jzoj4822 完美标号
    Jzoj4822 完美标号
    Jzoj4792 整除
    Jzoj4792 整除
    Educational Codeforces Round 79 A. New Year Garland
    Good Bye 2019 C. Make Good
    ?Good Bye 2019 B. Interesting Subarray
    Good Bye 2019 A. Card Game
    力扣算法题—088扰乱字符串【二叉树】
    力扣算法题—086分隔链表
  • 原文地址:https://www.cnblogs.com/bluettt/p/15416661.html
Copyright © 2020-2023  润新知