请在 msdn 中查找 “Serial Communications in Win32”, 这是篇介绍串口通讯很好的文章。
对于 什么是重叠操作(overlapped), 可以看
http://blog.csdn.net/metasearch/archive/2008/03/05/2148226.aspx 的介绍。以下是转载。
--------转载开始----------
在windows中有一个api叫readfile
bool readfile(
handle hfile, // handle to file
lpvoid lpbuffer, // data buffer
dword nnumberofbytestoread, // number of bytes to read
lpdword lpnumberofbytesread, // number of bytes read
lpoverlapped lpoverlapped // overlapped buffer
);
如果我们在createfile的时候没有使用file_flag_overlapped 标志,同时在调用readfile的时候把lpoverlapped lpoverlapped 这个参数设置的是null,那么readfile这个函数的调用一直要到读取完数据指定的数据后才会返回,如果没读取完,就会阻塞在这里。同样 ,writefile和readfile都是这样的。这样在读写大文件的时候,我们很多时间都浪费在等待readfile和writefile的返回上面。如果readfile和writefile是往管道里读写数据,那么有可能阻塞得更久,导致程序性能下降。为了解决这个问题,windows引进了重叠io的概念,同样是上面的readfile和writefile,如果在createfile的时候设置了file_flag_overlapped ,那么在调用readfile和writefile的时候就可以给他们最后一个参数传递一个overlapped结构。这样readfile或者writefile的调用马上就会返回,这时候你可以去做你要做的事,系统会自动替你完成readfile或者writefile,在你调用了readfile或者writefile后,你继续做你的事,系统同时也帮你完成readfile或writefile的操作,这就是所谓的重叠。使用重叠io还有一个好处,就是你可以同时发出几个readfile或者writefile的调用,然后用waitforsingleobject或者waitformultipleobjects来等待操作系统的操作完成通知,在得到通知信号后,就可以用getoverlappedresult来查询io调用的结果。
基本上就这样,。不知道你清楚了没有,,,
至于socket里的重叠io,和这个差不错,不同的是readfile writefile被wsarecv和wsasend所代替了。这其中牵涉到的东西很多,其实有关windows的异步io机制,是很高深的,所以开始我才推荐你去看《windows2000编程内幕》,也可以去看《inside windows2000》
当cpu执行你的代码时遇上一个i/o请求[诸如读写文件之类的],系统产生一个中断,让cpu去完成这个i/o请求,等到完成了以后,系统再次产生一个中断让原先的程序继续运行。也就说通过中断保持这两者间的同步。可以将终端理解为硬件化的信号量。
这就是所谓的同步概念,一个线程中只可能同时处理一个i/o请求
你要知道,一个i/o操作是非常耗时的,当你的代码挂起后等待i/o完成的这段时间内,你的这个线程浪费了n个指令周期。
如果同时要反复读写大文件,用同步的效率是很低的。
为了解决这个问题,当cpu执行你的代码时遇上一个i/o请求后,系统这是为你开一根内部线程去处理i/o请求,并且你的线程并不挂起,但你可能会觉得如果i/o还没完成,后续的代码就算他让我执行,我也执行不下去了嘛?
如果下面的代码和这个i/o操作有关的话,那么它就要等一等,等到这个i/o操作完成,通过在一个线程中调用waitformultiobject()和getoverlappedresult()就可以得到i/o完成的消息,然后再对其作相应的处理。
但如果后续的代码和这个i/o操作无关,你就可以以更快的速度之行下去了,而无需等待io请求的完成了
这也就是异步了
你想当你有这样一个请求,就是
readfile(...) -1
writefile(...) -2
readfile(...) -3
你在程序中如果使用同步的话,那只有当你完成1以后2才会继续执行,2执行完以后3才会继续执行。这就是同步。
当如果使用异步的话,当系统遇到1时,ok,开一线程给它去完成该io请求,然后系统继续运行2,3,分别开两线程。
1-2-3如果是比较耗时的操作,尤其是运用在网络上,那么1-2-3这三个io请求是并行的,也就是重叠的。
重叠i/o就是能够同时以多个线程处理多个i/o,其实你自己开多个线程也可以处理多个i/o,当然系统内部优化以后肯定性能要比你的强,呵呵。
我只是简单的说了一下重叠[overlapped]没从代码的角度给你分析。希望你能对重叠io有所理解。看看windows网络编程,上面不是有模型嘛
最后提一下重叠模型的缺点,他为每一个io请求都开了一根线程,当同时有1000个请求发生,那么系统处理线程上下文[context]切换也是非常耗时的,所以这也就引发了完成端口模型iocp,用线程池来解决这个问题,我就不多说了。
--------转载结束----------
我的看法:使用多线程设计的串口通讯程序,优先考虑使用重叠操作。
==========================================
串口通信协议介绍
串口通信协议分为同步协议和异步协议。
1、面向字符的同步协议
这种协议的典型代表是IBM公司的二进制同步传输(BSC)协议。
SYN | SYN | SOH | 标题 | STX | 数据块 | ETB/EXT | 校验 |
说明
缩写 | 全称 | HEX | 含义 |
SYN | Synchronous Character | 0x16 | 每一帧开始处都有SYN,加一个SYN的称单同步,加两个SYN的称双同步。设置同步字符是起联络作用,传送数据时,接收端不断检测,一旦出现同步字符,就知道是一帧开始。 |
SOH | Start of Header | 0x01 | 报头起始字符,它表示标题的开始。 |
标题 | 标题中包含源地址、目的地址和路由指示等信息。 | ||
STX | Start of Text | 0x02 | 正文的起始字符,它标志着传送的正文(数据块)开始。 |
数据块 | 就是传送的正文内容,有多个字符组成 | ||
ETB | End of Transmission Block | 0x17 | 数据块终结符,用在正文很长,需要分成若干个小数据块,分别在不同帧中发送的场合。 |
ETX | End of Text | 0x03 | 正文终结符。 |
校验 | 它对SOH开始到ETX(或ETB)字段进行校验,校验方式可以是奇偶校验或CRC。 | ||
EOT | End of Transmission | 0x04 | 送毕。 |
ENQ | Enquiry | 0x05 | 询问。 |
ACK | Acknowledge Character | 0x06 | 确认。 |
NAK | NegativeAcknowledge | 0x15 | 否定应答。 |
DLE | Data Link Escape | 0x10 | 转义。 |
2、面向比特的同步协议
3、起止式异步协议