首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

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

基础概念

Linux串口编程是指通过编程方式与串行端口进行通信。串口是一种常见的硬件接口,用于设备间的数据传输。在Linux系统中,串口通常被表示为设备文件,如/dev/ttyS0

为什么read不阻塞

在Linux中,read系统调用默认是阻塞的,即如果没有数据可读,read会一直等待直到有数据到达。然而,在某些情况下,read可能不会阻塞,这通常是由于以下原因:

  1. 非阻塞模式:如果文件描述符被设置为非阻塞模式(使用fcntl函数设置O_NONBLOCK标志),read将立即返回,而不是等待数据到达。
  2. 超时设置:如果使用了带有超时参数的read系统调用(如selectpollepoll),在超时时间内没有数据到达,read也会返回。
  3. 信号中断:如果在等待数据的过程中接收到信号,read可能会被中断并返回错误代码EINTR

示例代码

以下是一个简单的示例,展示如何在Linux中使用select来实现非阻塞的串口读取:

代码语言:txt
复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/select.h>
#include <errno.h>

#define SERIAL_PORT "/dev/ttyS0"
#define BUFFER_SIZE 1024

int main() {
    int fd;
    char buffer[BUFFER_SIZE];
    fd_set readfds;
    struct timeval timeout;

    // 打开串口设备
    fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY);
    if (fd == -1) {
        perror("Failed to open serial port");
        return 1;
    }

    // 设置非阻塞模式
    fcntl(fd, F_SETFL, FNDELAY);

    while (1) {
        FD_ZERO(&readfds);
        FD_SET(fd, &readfds);

        // 设置超时时间为1秒
        timeout.tv_sec = 1;
        timeout.tv_usec = 0;

        int ret = select(fd + 1, &readfds, NULL, NULL, &timeout);
        if (ret == -1) {
            perror("select error");
            break;
        } else if (ret == 0) {
            printf("Timeout occurred, no data after 1 second.\n");
        } else {
            if (FD_ISSET(fd, &readfds)) {
                int bytesRead = read(fd, buffer, BUFFER_SIZE);
                if (bytesRead > 0) {
                    buffer[bytesRead] = '\0';
                    printf("Received data: %s\n", buffer);
                } else if (bytesRead == 0) {
                    printf("End of file or device disconnected.\n");
                    break;
                } else {
                    perror("read error");
                    break;
                }
            }
        }
    }

    close(fd);
    return 0;
}

参考链接

应用场景

非阻塞的串口读取在需要实时处理数据或避免程序长时间等待的场景中非常有用,例如:

  1. 嵌入式系统:在资源受限的环境中,需要高效地处理串口数据。
  2. 自动化测试:在自动化测试过程中,需要实时读取设备输出并进行处理。
  3. 网络通信:在某些网络通信协议中,需要通过串口进行数据传输。

解决问题的方法

如果read不阻塞但你不希望它这样,可以检查以下几点:

  1. 检查文件描述符模式:确保文件描述符没有被设置为非阻塞模式。
  2. 检查超时设置:确保没有使用带有超时参数的read系统调用。
  3. 处理信号中断:如果read被信号中断,可以捕获EINTR错误并重试读取操作。

通过以上方法,可以更好地理解和控制Linux串口编程中的read行为。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

Linux基础(串口编程)

虽然以太网接口和USB接口也是以一个串行流进行数据传送的,但是串口连接通常特指那些与RS-232标准兼容的硬件或者调制解调器的接口。废话少讲,今天来解剖使用串口时的编程代码细节。...上面的代码是使用串口的第一步,来解释下都是啥意思。...来瞧瞧: 第21-22行,定义了一个用来配置串口属性的结构体: struct termios serial; bzero(&serial, sizeof(serial)); 第24行,将串口设置为raw...cfsetispeed(&serial, B9600); cfsetospeed(&serial, B9600); 第28-32行,设置串口控制属性(c_cflag),其中: serial.c_cflag...: tcsetattr(fd,TCSANOW,&serial); 当然,上面的 fd 就是系统中的某一个你想要设置的成上面那样的属性参数的串口,比如就拿粤嵌GEC210开发板来说,他有四个串口,其中第一个就已经被用于终端控制了

12.9K20
  • 【高级编程】Linux read系统调用

    比如 fork、clone、execve、exit等 那为什么一定要用系统调用来访问操作系统的内容呢,其实这可以看做对内核的保护,linux分为用户空间和内核空间,而用户空间是不允许访问内核空间的数据的...引入 cache 层的目的是为了提高 linux 操作系统对磁盘访问的性能。 Cache 层在内存中缓存了磁盘上的部分数据。...对于第二次读请求,如果所读页面不在Cache中,即不在前次预读的group中,则表明文件访问不 是顺序访问,系统继续采用同步预读;如果所读页面在Cache中,则表明前次预读命中,操作系统把预读group...一个物理页可能由多个不连续的物理磁盘块组成。也正是由于页面中映射的磁盘块不一定连续,所以在页高速缓存中检测特定数据是否已被缓存就变得不那么容易了。另外linux页高速缓存对被缓存页的范围定义的非常宽。...为了满足普遍性要求,linux使用定义在linux/fs.h中的结构体address_space结构体描述页高速缓存中的页面。

    6.2K110

    Linux编程(阻塞的概念)

    阻塞。 好吧,再来一点营养。阻塞是啥意思呢? 就是水管堵住了!扭开水龙头没有水出来。...这个道理跟Linux下读取慢速设备(主要指管道和套接字)数据的情形非常相似,例如当我们在读取一个管道时,如果管道里面没有数据,那么我们什么都读不出来,于是就进入了所谓的“阻塞”状态了,说白了阻塞就是使得当前进程或者线程睡眠了的意思...那么再进一步,什么时候会阻塞呢?下面的表格简单描述了这些清空: ? 其中,读者指的是对管道文件拥有读权限的进程或线程(注意不是正在读),写者指的是对管道文件拥有写权限的进程或线程(注意不是正在写)。...除此之外,其实open()函数也会发生阻塞,比如用只读或者只写open一个管道文件的时候。因为一根只有出口或者只有入口的水管,是无法使用的呀!其实就是生活常识。嘿嘿!

    2.2K30

    php 纯socket编程核心的东西!socket_read阻塞的问题!

    网上的代码大都是官方的例子,不直观、不彻底。 结合网上的东西花了一周的时间。...,没有按照PHP的思维习惯,在莫名其妙的请款下就停止了【阻塞】,阻塞的本质是在底层操作系统、网络接口等用c语言封装后暴露出来的一个PHP函数(看c的socket总结出来的) 2、socket_accept...、socket_read、socket_recv默认都会阻塞,但也可以用socket_set_nonblock()、socket_set_block()设置 3、PHP不关心buffer缓存,在这:...== false){//PHP_NORMAL_READ 不够length就阻塞,PHP_BINARY_READ不会 // var_dump($buf_read_data."...、socket_recv、socket_accept三个默认都是阻塞的,不阻塞就是:不会'卡死'在这些函数上 //不开启不能反向写入数据:报错:Warning: socket_recv(): unable

    2.2K20

    为什么不建议看直播学编程

    为什么不建议你看直播花时间学编程呢?首先的一个点就是浪费你的时间。 我敢说那些开直播的,不管是老师还是培训机构,花了两三个小时给你直播的目的,绝对不是教你知识和技能。百分之五十的目的就是卖你课。...如果你不是对编程感兴趣,而只是想靠它吃口饭,那么请看完这个之后再做决定。...如果没有破釜沉舟的勇气,或者坐等培训机构承诺的人我不建议你去学习编程,这个真的不适合你! ---- 其次,由于此次疫情,当前市面上的培训机构几乎都面临着生死危机!...培训机构又不是慈善机构,如果不卖课,那还叫培训机构吗?直播是希望得到你的认可,让你物超所值,同时也是为了让企业可以再次持续!...3、并不是所有人都适合学编程。 4、免费的才是最贵的。

    1.1K30

    嵌入式Linux系列第7篇:操作UART

    1 引言 串口是我们实际工作中经常使用的一个接口,比如我们在Linux下使用的debug串口,它用来登录Linux系统,输出log。...所以千万不要直接用cat去判断串口是否有数据接收,为什么有时能收到呢,那是因为串口设备在某个地方被打开(调用了open函数)了。...上述程序工作过程是串口先发送一串数据,然后一直停在read函数处不动,直到接收到数据后返回退出。此时串口工作在阻塞模式下。...所谓阻塞和非阻塞的含义如下: 阻塞: 对于read,指当串口输入缓存区没有数据的时候,read函数将会阻塞在这里,直到串口输入缓存区中有数据可读取,read读到了需要的字节数之后,返回值为读到的字节数;...非阻塞: 对于read,指当串口输入缓冲区没有数据的时候,read函数立即返回,返回值为-1。

    3.2K20

    Linux下Socket编程(三)——非阻塞select的使用简介

    简介 什么叫阻塞和非阻塞 select fd_set类型的变量相关宏定义 fcntl 实例 select总是返回1的问题。...什么叫阻塞和非阻塞 阻塞方式block,顾名思义,就是进程或是线程执行到这些函数时必须等待某个事件的发生,如果事件没有发生,进程或线程就被阻塞,函数不能立即返回。...使用Select就可以完成非阻塞(所谓非阻塞方式non- block,就是进程或线程执行此函数时不必非要等待事件的发生,一旦执行肯定返回,以返回值的不同来反映函数的执行情况,如果事件发生则与阻塞方式相同...NULL以形参传入,即不传入时间结构,就是将select置于阻塞状态。...SELECT_fncl.png 示例 客户端创建socket 调用fcntl设置阻塞模式 调用connect开始连接。

    4.3K10

    RS232串口的Windows编程纪要

    USB外置的串口则绝大多数都需要另外安装驱动,Windows/Linux/macOS都是如此,依据适配器的芯片不同,所使用的驱动也不一样。这个在采购的时候就需要了解好。...比如我测试的这款是PL2302芯片,使用win10内置的微软2017版驱动(不不不,不是你想的那样免驱动,继续看)。...连接USB串口适配器,再次到上述相应位置,查看是否增加了串口设备,如果没有增加,返回检查驱动程序甚至适配器硬件。如果有增加,记录下来端口号,以供后续编程使用。...//读取串口的时候,如果对方尚未发送指定长度的数据,会导致读取串口阻塞 //这里使用线程同步的事件响应方式,防止读取数据阻塞 //所以读取串口可能返回0表示没有读取到数据 //或者小于期望读取的字节表示数据尚未完全到来...只有串口的设置部分(本程序中是跟打开串口放在一起)是同传统文件操作不相同的。 第二个不同则是,通常的硬盘文件读写,速度都很快,不需要考虑阻塞问题。

    1.6K40

    RS232串口的Windows编程纪要

    USB外置的串口则绝大多数都需要另外安装驱动,Windows/Linux/macOS都是如此,依据适配器的芯片不同,所使用的驱动也不一样。这个在采购的时候就需要了解好。...比如我测试的这款是PL2302芯片,使用win10内置的微软2017版驱动(不不不,不是你想的那样免驱动,继续看)。...连接USB串口适配器,再次到上述相应位置,查看是否增加了串口设备,如果没有增加,返回检查驱动程序甚至适配器硬件。如果有增加,记录下来端口号,以供后续编程使用。...//读取串口的时候,如果对方尚未发送指定长度的数据,会导致读取串口阻塞 //这里使用线程同步的事件响应方式,防止读取数据阻塞 //所以读取串口可能返回0表示没有读取到数据 //或者小于期望读取的字节表示数据尚未完全到来...只有串口的设置部分(本程序中是跟打开串口放在一起)是同传统文件操作不相同的。 第二个不同则是,通常的硬盘文件读写,速度都很快,不需要考虑阻塞问题。

    4.6K90

    linux系统编程之信号(三):信号的阻塞与未决

    进程可以选择阻塞(Block)某个信号,SIGKILL 和 SIGSTOP 不能被阻塞。被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。...int sigismember(const sigset_t *set, int signo); 函数sigemptyset初始化set所指向的信号集,使其中所有信号的对应bit清零,表示该信号集不包含任何有效信号...sigismember是一个布尔函数,用于判断一个信号集的有效信号中是否包含某种信号,若包含则返回1,不包含则返回0,出错返回-1。...;         flag = 1;     } } 如果将程序中的37,57,58,75关于flag变量的语句注释掉,则输出如下: simba@ubuntu:~/Documents/code/linux_programming...参考:《APUE》、《linux c 编程一站式学习》

    2.3K00

    Linux系统开发基础知识

    Shell语言基础 shell脚本,也就是使用Linux系统下的一系列命令,有机组合在一起,而完成预期的功能。Linux设计思想是“小即是美”,这一思想是shell脚本编程的完美体现。...常用Linux系统编程知识 文件IO Linux系统下,所有的资源都是以文件的形式访问的,设备被抽象为设备文件,放于/dev目录下。...,做驱动的同学应该很了解 fcntl 属性设置函数 对已经打开的设备,设置属性,比如可以设置串口读数据的阻塞和非阻塞属性 lseek 改变偏移量 一般用于对已打开的文件读写位置的偏移量修改 文件与目录操作...高级IO里主要是讲的IO操作的方式:阻塞、非阻塞控制,最主要的是通过select和poll实现IO多路复用,这样可以实现程序的异步执行。...系统编程 在Linux下,特别是做嵌入式系统,这个可能是少不了的,比较常用。其实串口编程也很简单,可能200行代码就可以把串口通信建立起来了。

    1.5K10

    linux网络编程系列(七)--如何将socket设置成非阻塞的,非阻塞socket与阻塞的socket在收发数据上的区别

    生成socket时设置 socket函数创建socket默认是阻塞的,也可以增加选项将socket设置为非阻塞的: int s = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK...非阻塞和阻塞在收发数据时有什么区别 3.1 发送时的区别 3.1.1 TCP发送(即send函数) send函数在阻塞模式下,会等待所有数据都被拷贝到发送缓冲区才会返回,也就是说,阻塞模式下,send函数返回值必定是参数中发送长度的大小...UDP发送(即sendto函数) 即使在阻塞模式下,sendto也不会阻塞,因为UDP并没有真正的发送缓冲区,它所做的只是将应用缓冲区数据拷贝给下层协议栈,加上UDP头、IP头等,实际是不存在阻塞的,...非阻塞模式也一样。...3.2 接收时的区别 3.2.1 TCP接收(即recv函数) 在阻塞模式下, recv将会阻塞,直到缓冲区里有至少一个字节才返回,当没有数据到来时,recv会一直阻塞或者直到超时,不会返回; 在非阻塞模式下

    3.4K30

    fcntl系统调用

    linux下串口的阻塞和非阻塞操作  有两个可以进行控制串口阻塞性(同时控制read和write):一个是在打开串口的时候,open函数是否带O_NDELAY;第二个是可以在打开串口之后通过fcntl(...阻塞的定义:  对于read,block指当串口输入缓冲区没有数据的时候,read函数将会阻塞在这里,移植到串口输入缓冲区中有数据可读取,read读到了需要的字节数之后,返回值为读到的字节数; 对于...write,block指当串口输出缓冲区满,或剩下的空间小于将要写入的字节数,则write将阻塞,一直到串口输出缓冲区中剩下的空间大于等于将要写入的字节数,执行写入操作,返回写入的字节数。...非阻塞的定义: 对于read,no block指当串口输入缓冲区没有数据的时候,read函数立即返回,返回值为0。...\n"); } printf("fd-open=%d\n",fd); return fd; } 所以,linux的串口的阻塞性通过fcntl

    1.4K30
    领券