linux串口编程read为什么不阻塞

fiy 其他 184

回复

共3条回复 我来回复
  • fiy的头像
    fiy
    Worktile&PingCode市场小伙伴
    评论

    Linux串口编程中的read函数之所以不阻塞,是因为在默认情况下,串口设备的I/O操作是非阻塞的。下面我将详细解释为什么read函数不阻塞。

    1. 阻塞与非阻塞IO操作
      阻塞和非阻塞是IO操作的两种不同方式。在阻塞IO操作中,当程序执行IO操作时,如果数据还未准备好或无法立即读取,程序将会被阻塞,直到数据准备好或者超时。而非阻塞IO操作则不会阻塞程序的执行,当数据未准备好时,程序会立即返回一个错误代码。

    2. 串口设备的特点
      串口设备在数据传输方面具有较低的速率和较高的时延,这与其他设备(如磁盘、网络)相比有较大的差异。为了提高串口的性能,Linux内核为串口设备的I/O操作设置了非阻塞的默认属性。

    3. 非阻塞串口读取操作
      当我们使用read函数从串口设备读取数据时,如果没有数据可读,read函数会立即返回,并返回0作为读取的字节数。这样,程序就可以继续执行其他任务,而不需要一直等待数据的到来。

    如果我们希望read函数在串口没有数据可读时阻塞,可以通过设置串口设备的属性来实现。可以使用ioctl函数来设置串口的阻塞属性,具体可以参考相关的文档和例程。

    总结:
    在Linux串口编程中,read函数默认是非阻塞的,这是为了提高串口设备的性能。如果需要阻塞式的读取串口数据,可以通过设置串口属性来实现。

    1年前 0条评论
  • 不及物动词的头像
    不及物动词
    这个人很懒,什么都没有留下~
    评论

    在Linux串口编程中,read函数为什么不阻塞是因为以下几个原因:

    1. 非阻塞模式:在打开串口时,可以设置串口为非阻塞模式。在非阻塞模式下,read函数会立即返回已经接收到的数据,如果没有数据可读取,则返回错误码。这样可以提高程序的响应速度,避免因等待数据而阻塞其他操作。

    2. 设置超时时间:除了非阻塞模式外,还可以通过设置超时时间来控制read函数的阻塞行为。可以使用select或poll函数监视串口文件描述符,当串口有数据可读时,再调用read函数进行读取。通过设置合适的超时时间,可以在一定时间内等待数据到达,如果超过指定时间仍未接收到数据,则可以继续执行其他操作。

    3. 串口驱动:Linux内核的串口驱动程序会对串口进行缓冲处理。当数据到达时,驱动程序会将数据放入接收缓冲区中,应用程序调用read函数时,只需要从缓冲区读取数据即可,不需要等待数据的实时到达。这样可以减少read函数的阻塞时间。

    4. 缓冲区大小:串口驱动程序会为每个串口分配接收缓冲区,该缓冲区的大小可以通过设置来调整。如果接收缓冲区已满,新到达的数据将会被丢弃。因此,应用程序需要及时读取串口接收缓冲区中的数据,以避免数据丢失。

    5. 数据流控制:在串口通信中,可以使用数据流控制的方式来控制数据的传输速率。当接收方无法及时处理接收到的数据时,可以通过发送控制信号来暂停发送方的数据。这样可以避免数据溢出和丢失,同时也能减少read函数的阻塞时间。

    总而言之,Linux串口编程中的read函数不阻塞是因为非阻塞模式、设置超时时间、串口驱动程序的缓冲处理、合理的缓冲区大小以及数据流控制等因素的综合作用。这些机制可以使read函数在接收到数据时立即返回,而不会阻塞程序的执行。

    1年前 0条评论
  • worktile的头像
    worktile
    Worktile官方账号
    评论

    在Linux串口编程中,read函数默认是阻塞的,即当没有数据可读时,read函数会一直等待直到有数据可读为止。但是,有时候我们希望read函数在没有数据可读时立即返回,而不是一直阻塞等待。这种非阻塞的读取方式可以通过设置文件描述符的属性来实现。

    在Linux中,每个打开的文件都有一个对应的文件描述符,通过文件描述符可以对文件进行读写操作。对串口设备进行读写操作时,也需要使用文件描述符。在串口编程中,我们可以使用Linux系统提供的函数来设置串口文件描述符的属性,从而实现非阻塞的读取。

    一般来说,设置串口文件描述符为非阻塞的操作包括以下几个步骤:

    1. 打开串口设备:使用open函数打开串口设备文件,获取对应的文件描述符。例如,可以使用以下代码打开串口设备/dev/ttyS0:
    int fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NONBLOCK);
    
    1. 设置串口属性:使用tcgetattr和tcsetattr函数来获取和设置串口文件描述符的属性。通过设置串口的属性,可以控制串口的波特率、数据位、停止位等参数。同时,我们还需要将串口文件描述符设置为非阻塞模式。例如,可以使用以下代码设置串口属性和非阻塞模式:
    struct termios options;
    tcgetattr(fd, &options);
    
    cfsetispeed(&options, B9600); // 设置波特率为9600
    cfsetospeed(&options, B9600);
    
    options.c_cflag |= CLOCAL; // 忽略调制解调器控制信号
    options.c_cflag |= CREAD; // 启用接收器
    
    options.c_cflag &= ~CSIZE; // 清除数据位设置
    options.c_cflag |= CS8; // 设置数据位为8位
    
    options.c_cflag &= ~PARENB; // 禁用奇偶校验
    options.c_cflag &= ~CSTOPB; // 设置停止位为1个
    
    tcsetattr(fd, TCSANOW, &options);
    
    fcntl(fd, F_SETFL, FNDELAY); // 设置为非阻塞模式
    
    1. 使用read函数进行非阻塞读取:现在,我们可以使用read函数来进行串口数据的读取了。在非阻塞模式下,read函数会立即返回,不管串口中是否有数据可读。如果没有数据可读,read函数返回-1,并且设置errno为EAGAIN。如果有数据可读,read函数返回实际读取的字节数。
    char buf[100];
    int n = read(fd, buf, sizeof(buf));
    if (n > 0) {
        // 处理读取到的数据
    } else if (n == -1 && errno == EAGAIN) {
        // 没有数据可读
    } else {
        // 读取错误
    }
    

    通过上述步骤,我们可以实现在Linux串口编程中使用非阻塞的方式进行读取。需要注意的是,非阻塞读取需要在设置文件描述符属性时将其设置为非阻塞模式,并且在read函数返回-1并且errno为EAGAIN时判断没有数据可读。

    1年前 0条评论
注册PingCode 在线客服
站长微信
站长微信
电话联系

400-800-1024

工作日9:30-21:00在线

分享本页
返回顶部