阻塞和非阻塞(串口自环测试失败原因定位)
串口自环测试失败原因定位
INT32 serial_test()
{
INT32 fd;
INT32 i;
char rbuf[1];
char wrbuf[1];
INT32 count = 0;
INT32 cnt = 0;
rbuf[0] = 0;
int ret;
//VCS_Ctrl_LedConf(SC1_LED,RED,FAST_BLINK); //SC4红灯灭
// printf("serial_test::11111\n");
printflag = 1;
fd = open( "/dev/ttyS0", O_RDWR| O_NOCTTY | O_NONBLOCK);
if (fd < 0)
{
DPRINTF(PRINT_FLAG_ERR,"can't open ttyS0\n");
close(fd);
}
else
{
DPRINTF(PRINT_FLAG_ERR,"open OK...\n");
}
// printf("serial_test::22222\n");
tcflush(fd,TCIOFLUSH);
for(i=0;i<10000;i++)
{
rbuf[0] = 0;
read(fd,rbuf,1);
}
//printf("serial_test::3333\n");
// VCS_Ctrl_LedConf(SC3_LED,RED,FAST_BLINK); //SC4红灯灭
if(0 == tty_raw(fd))
DPRINTF(PRINT_FLAG_ERR,"tty raw set OK \n");
// VCS_Ctrl_LedConf(SC3_LED,GREEN,FAST_BLINK); //SC4红灯灭
#if 0
{
INT32 timeOut = 0;
/* hope to read 10 byte from serial com0*/
while(1)
{
ret = read(fd, rbuf, 1000);
if(ret <= 0)
{
timeOut ++;
if (timeOut > 10)
break;
}
}
}
#endif
while(1)
{
tcflush(fd,TCIOFLUSH);
wrbuf[0] = 'u';
rbuf[0] = 0;
ret=write(fd,wrbuf,1);
if(ret== -1)
{
printf("write error!\n");
perror("wirte failed");
}
if(ret==1)
printf("write success!");
usleep(1000); //lixia add 2010-06-13
ret = 0;
cnt = 0;
while(ret != 1)
{
cnt++;
ret=read(fd,rbuf,1);
if(ret== -1)
{
printf("read error! 0x%x\n",errno); 这里发现经常读错误,而且返回的errno为0xb,
perror("read failed");
}
if(ret==1)
printf("read success! cnt=%d\n",cnt);
usleep(1000);
if(cnt>2000)
break;
}
printf("w:%c %d r:%c %d \n",wrbuf[0],wrbuf[0],rbuf[0],rbuf[0]);
if(wrbuf[0] == rbuf[0])
{
Beep_Warning_On();
sleep(1);
Beep_Warning_Off();
sleep(1);
if (0 == tty_reset(fd))
DPRINTF(PRINT_FLAG_ERR,"tty set RESET ok\n");
// sleep(2);
close(fd);
printflag = 0;
// VCS_Ctrl_LedConf(SC1_LED,GREEN,FAST_BLINK); //SC4红灯灭
return 0;
}
else
{
count ++;
if(count > 1000)
{
if (0 == tty_reset(fd))
{
DPRINTF(PRINT_FLAG_ERR,"tty set RESET ok\n");
}
close(fd);
printflag = 0;
VCS_Ctrl_LedConf(SC1_LED,GREEN,FAST_BLINK); //SC4红灯灭
return -1;
}
}
}
}
发现“标红的read函数”经常会读错误,而且返回的errno为0xb,
0xb对应EAGAIN。
因为open函数使用的是O_NONBLOCK,非阻塞,所以定位到原因,因为是非阻塞模式,所以如果没有数据时read会直接返回失败,导致写入不等于读取的数据,如果超过1000次,就判断串口自环测试失败。优化后的代码见上图compare。
知识点:一定要判断函数的返回值!!!
--------------------------------------------------------------------------------------------------------------------------------------
非阻塞(O_NONBLOCK)
非阻塞I/O使我们的操作要么成功,要么立即返回错误,不被阻塞。
对于一个给定的描述符两种方法对其指定非阻塞I/O:
(1)调用open获得描述符,并指定O_NONBLOCK标志
(2)对已经打开的文件描述符,调用fcntl,打开O_NONBLOCK文件状态标志。
flags = fcntl( s, F_GETFL, 0 ) )
fcntl( s, F_SETFL, flags | O_NONBLOCK )
--------------------------------------------------------------------------------------------------------------------------------------
Linux:非阻塞O_NONBLOCK与O_NDELAY的区别
O_NONBLOCK和O_NDELAY所产生的结果都是使I/O变成非阻塞模式(non-blocking),在读取不到数据或是写入缓冲区已满会马上return,而不会阻塞等待。
它们的差别在于:在读操作时,如果读不到数据,O_NDELAY会使I/O函数马上返回0,但这又衍生出一个问题,因为读取到文件末尾(EOF)时返回的也是0,这样无法区分是哪种情况。因此,O_NONBLOCK就产生出来,它在读取不到数据时会回传-1,并且设置errno为EAGAIN。
O_NDELAY是在System V的早期版本中引入的,在编码时,还是推荐POSIX规定的O_NONBLOCK,O_NONBLOCK可以在open和fcntl时设置。
--------------------------------------------------------------------------------------------------------------------------------------
Linux 设备驱动--- 阻塞型字符设备驱动 --- O_NONBLOCK --- 非阻塞标志
阻塞:
在设计简单字符驱动程序时,要注意一个重要问题.
当一个设备无法立刻满足用户的读写请求时应当如何处理?
例如:调用 read 时没有数据可读,但以后可能会有;
或者一个进程试图向设备写入数据,但是设备暂时没有准备好接收数据.
应用程序通常不关心这种问题,应用程序只是调用 read 或 write 并得到返回值.
驱动程序应当 ( 缺省地 ) 阻塞进程,使它进入睡眠,直到请求可以得到满足.
阻塞操作:
是指在执行设备操作时,若不能获得资源则挂起进程,直到满足可操作的条件后进行操作,
被挂起的进程进入睡眠状态,被从调度器的运行队列移走,直到等待的条件被满足.
非阻塞操作:
进程不能进行设备操作时并不挂起,他或者放弃,或者不停的查询,直到可以进行操作为止.
阻塞方式-read- 实现:
在阻塞型驱动程序中,read 实现方式如下:
如果进程调用 read ,但设备 没有数据 或 数据不足,进程阻塞.
当新数据到达后,唤醒被阻塞进程.
阻塞方式-write- 实现:
在阻塞型驱动程序中,write 实现方式如下:
如果进程调用了 write ,但设备 没有足够的空间供其写入数据, 进程阻塞.
当设备中的数据被读走后,缓冲区中 空出部分空间,则 唤醒进程.
非阻塞方式的读写操作:
阻塞方式是文件读写操作的 默认方式,但是应用程序员可通过使用 O_NONBLOCK 标志来人为
的 设置读写操作为 非阻塞方式 .( 该标志定义在 < linux/fcntl.h > 中,在打开文件时指定 ) .
如果 设置了 O_NONBLOCK 标志,read 和 write 的行为是不同的 ,如果进程没有数据就绪时调用了 read ,
或者在缓冲区没有空间时调用了 write ,系统只是 简单的返回 -EAGAIN,而 不会阻塞进程.
实例 --- 读阻塞的实现:
用 while 是因为可能别的信号唤醒了睡眠,我们要通过while 重新检测是否真有数据了....
实例 --- 按键驱动阻塞实现:
1,在 open 函数 查看看是 阻塞方式 还是 非阻塞方式:
file 结构体中含有 f_flags 标志位,看是 阻塞方式 还是 非阻塞方式:
O_NONBLOCK 为 非阻塞方式;
if (file->f_flags & O_NONBLOCK) /* 非 阻塞操作 */{if (down_trylock(&button_lock)) /* 无法获取信号量,down_trylock 立马返回 一个 非零值 */return -EBUSY;}else /* 阻塞操作 */{/* 获取信号量 */down(&button_lock); /* 获取不到 睡眠 */}
2,在 read 函数中同样查看:
if (file->f_flags & O_NONBLOCK) /* 非 阻塞操作 */{if (!ev_press) /* ev_press 为 1 表示有按键按下,为 0 if 成立 ,没有按键按下, */return -EAGAIN; /* 返回 -EAGAIN 让再次来执行 */}else /* 阻塞操作 */{/* 如果没有按键动作, 休眠 */wait_event_interruptible(button_waitq, ev_press);}
<table><tr><td bgcolor=#7FFFD4>这里的背景色是:Aquamarine, 十六进制颜色值:#7FFFD4, rgb(127, 255, 212)</td></tr></table>
3,应用程序中:
1,以阻塞方式运行:
后台执行应用程序,进程处于睡眠状态,按下按键,立马打印按键号;
int main(int argc, char **argv)
{unsigned char key_val;int Oflags;fd = open("/dev/buttons", O_RDWR );if (fd < 0){printf("can't open!\n");return -1;}while (1){read(fd, &key_val, 1);printf("key_val: 0x%x\n", key_val);}return 0;
}
2,以非阻塞方式运行:
open 驱动程序的时候,传入标志 O_NONBLOCK 非阻塞;
后台执行应用程序:
int main(int argc, char **argv)
{unsigned char key_val;int ret;int Oflags;fd = open("/dev/buttons", O_RDWR | O_NONBLOCK);if (fd < 0){printf("can't open!\n");return -1;}while (1){ret = read(fd, &key_val, 1);printf("key_val: 0x%x, ret = %d\n", key_val, ret);sleep(5);}return 0;
}
非阻塞方式,没有按键值按下,程序立马返回;
read 返回值 为 -1;
https://blog.csdn.net/yikai2009/article/details/8653697#t7
阻塞和非阻塞(串口自环测试失败原因定位)相关推荐
- Linux 使用fcntl c_cc[VMIN] c_cc[CTIME]设置串口阻塞与非阻塞读取数据
一.概述 Linux串口非常灵活,可以根据需要配置成标准串口和自定义串口模式,就Linux 串口读取数据来说,有有两种主要方式:阻塞与非阻塞. 阻塞:一直等待数据,直到退出条件成立: 非阻塞:及时返回 ...
- ESP3 + ESP-IDF | 串口1 - 简单的串口回环测试
文章目录 一.前言 二.VSCODE + ESP-IDF 2.1.快速创建项目 2.2.选择串口通道,ESP芯片型号 三.代码 3.1.头文件 3.2.全局变量 3.3.app_main( )函数 3 ...
- 阻塞、非阻塞、多路复用、同步、异步、BIO、NIO、AIO 一锅端
承接上文的操作系统,关于IO会涉及到阻塞.非阻塞.多路复用.同步.异步.BIO.NIO.AIO等几个知识点.知识点虽然不难但平常经常容易搞混,特此Mark下,与君共勉. 1 阻塞跟非阻塞 1.1 阻塞 ...
- IO:同步,异步,阻塞,非阻塞
IO - 同步,异步,阻塞,非阻塞 都是老生常谈的东西,多通读几遍,理解透彻! 实际上同步与异步是针对应用程序与内核的交互而言的.同步过程中进程触发IO操作并等待(也就是我们说的阻塞)或者轮询的去查看 ...
- 同步通信与异步通信以及阻塞和非阻塞之我见 [原]
一.硬件层次上的同步与异步 1.异步通信 在异步通信中,CPU与外设之间有两项约定: (1)字符格式---字符的编码形式及规定,每个串行字符由以下四个部分组成: ⑴ 1个起始位 ...
- 设备的阻塞与非阻塞操作
阻塞操作是指,在执行设备操作时,若不能获得资源,则进程挂起直到满足可操作的条件再进行操作.非阻塞操作的进程在不能进行设备操作时,并不挂起.被挂起的进程进入sleep状态,被从调度器的运行队列移走,直到 ...
- Socket阻塞与非阻塞,同步与异步、I/O模型
[原文链接] 1. 概念理解 在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式: 同步: 所谓同步,就是在发出一 ...
- recv send 阻塞和非阻塞
int send( SOCKET s, const char FAR *buf, int len, int flags ); 不论是客户还是服务器应用程序都用send函数来向TCP连接的另一端发送数据 ...
- Linux 阻塞和非阻塞IO 实验
目录 阻塞和非阻塞IO 阻塞和非阻塞简介 等待队列 轮询 Linux 驱动下的poll 操作函数 阻塞IO 实验 硬件原理图分析 实验程序编写 运行测试 非阻塞IO 实验 硬件原理图分析 实验程序编写 ...
- 通俗系列之同步、异步、阻塞和非阻塞
前言 在日常的开发中,经常出现同步.异步.阻塞和非阻塞等概念.有些人搞不清楚什么代码是同步,什么代码是异步.有些人说我用异步了啊,为什么效率还是没提高呢?也许你是用异步了,但是可能是异步阻塞了.有些人 ...
最新文章
- linux /etc/profile和/etc/bashrc
- VTK:图片之ImageMathematics
- Java黑皮书课后题第2章:*2.23(驾驶费用)编写一个程序,提示用户输入驾驶的距离、每加仑多少英里的汽车燃油性能值,以及每加仑的价格,然后显示旅程的费用
- php对外发包引发服务器崩溃的终极解决方法分享
- 美国劳工部揭露中国女人大数据,看完彻底傻眼了……
- Kotlin入门(4)声明与操作数组
- python_统计数组中指定范围的数据占的比例
- 读Thinking in Java(1~4)
- windows sesrver2003下搭建DHCP服务器
- 最简单的pdf加水印方法,五个步骤很详细
- ps文件太大无法保存?
- Thinkpad X201i笔记本电脑开机Fan Error
- 「雕爷学编程」Arduino动手做(13)——触摸开关模块
- 互联网创业公司是否需要技术外包?
- USB连接默认更改为传输文件
- Javascript 判断一个数是否为素数的三种解法
- 抗去除花指令(一)——花指令基础
- 英文论文画图常用软件
- glTF学习笔记(0)——概述
- 丁香园开放医疗数据平台,覆盖药、病、诊、科研等7大应用场景
热门文章
- 科研不是比赛,而是一种对未知和完美的自我追求——跟邢波(Eric Xing)面对面聊科研...
- 运用.net工厂编写数据库类
- matlab 纵坐标 科学计数法,echarts纵坐标使用科学计数法表示
- Java随机生成_0--2π_使用随机数计算PI
- ios 通知接收两次_苹果健康体系又进一步,iOS 14.3支持有氧适能通知
- spark使用KryoRegistrator java代码示例
- 数商云:B2C商城网站建设功能框架大解析
- TOMCAT报错解决
- WebSocket+HTML5实现在线聊天室
- DigitalOcean发布弹性块存储服务