- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试在 Windows 7/8 X64 上使用重叠 IO 模式来模拟 Linux 的开放标志支持的非阻塞模式 (IO_NONBLOCK) 行为。此处的代码是跨平台串行 API 的窗口部分的一部分。
我可以使用 SerialCommWnt 对象的构造函数参数以阻塞或非阻塞 (OVERLAPPED) 模式打开 COMM 端口。就这个问题而言,我的所有问题都与何时以 OVERLAPPED 模式打开 COMM 端口有关(由流量控制构造函数参数指定)。对于 Read 方法,我指定了一个超时参数,该参数在从串行端口成功检索至少 1 个字节的数据后,应指示数据在串行通信的输入缓冲区中时 rTimeout 参数的剩余时间(我相信串行驱动程序在收到任何数据时通知重叠结构中的手动重置事件。
我阅读了很多关于如何处理这些 API 的 StackOverflow 帖子,其中很多都提到了 Microsoft Win32 API。到目前为止我能找到的最好的信息是
http://msdn.microsoft.com/en-us/library/ff802693.aspx这个 API 对 Overlapped IO 造成混淆(特别是当涉及到在重叠模式下调用 ReadFile 时传递指向接收到的字节数的指针),但据我所知,它们都没有解决如何正确使用重叠 IO 的问题模式结合 COMMTIMEOUTS。在过去的几天里,我试验了 COMMTIMEOUTS 和与 ::WaitForSingleObject 一起使用的超时参数的设置组合。最后显示了似乎最有效的组合。关于与重叠 IO 结构和 COMMTIMEOUTS 关联的手动重置事件对象关联的超时,我有一些可靠性问题。我不完全确定,但似乎为了在从串行端口读取时超时正常工作,必须在 COMMTIMEOUTS 中指定超时。我尝试了一种组合,我在 SetCommTimeouts 中禁用了超时,而是在 ::WaitForSingleObject 的超时参数中使用了显式超时,但这没有用,相反我做了反过来,通过在 COMMTIMEOUTS 中指定超时并使用 ::WaitForSingleObject 方法调用指定 INFINITE。但是,我不确定是否存在这种情况会永远挂起的情况,如果是这样,我该如何处理。如果能提供有关如何正确处理此处可能挂起的任何信息,我将不胜感激。
这是我用来打开 COMM 端口的方法 - 在这种情况下,我有超时问题,我指定了 FILE_FLAG_OVERLAPPED。
/**
* Open the serial port using parameters set in theconstructor.<p>
* The Port Number, Speed, Overlapped IO mode, #data bits &
* async mode etc. are specified as constructor arguments.
*
* @return OS_FAILED, OS_SUCCESS
*/
OsStatus
SerialCommWnt::open()
{
// Critical Section
std::lock_guard<std::recursive_mutex> lock (mMutexGuard);
OsStatus result = OS_FAILED;
std::ostringstream os;
os << "\\\\.\\COM" << mCommPort;
std::string deviceName = os.str();
DWORD dwFlagsAndAttrs = (mFlowControl ==
SerialCommBase::FCTL_OVERLAPPED)?
FILE_FLAG_OVERLAPPED : 0;
// open the underlying device for read and write
mOsFileHandle = CreateFile (
deviceName.c_str(),
GENERIC_READ | GENERIC_WRITE,
0, //(share) 0:cannot share the COM port
NULL, // no security attributes
OPEN_EXISTING, // COMM devices must use OPEN_EXISTING
dwFlagsAndAttrs, // optional FILE_FLAG_OVERLAPPED
NULL); // hTemplate must be NULL for comm devices
if ( mOsFileHandle != INVALID_HANDLE_VALUE ) {
// reserve an 8k communications channel buffer (both directions)
BOOL isOK = SetupComm(mOsFileHandle, 8200, 8200);
// Omit the call to SetupComm to use the default queue sizes.
// Get the current configuration.
DCB dcb;
SecureZeroMemory(&dcb, sizeof(DCB));
isOK = GetCommState (mOsFileHandle, &dcb);
if (isOK) {
// Fill in the DCB: baud=125000, 8 data bits, even parity, 1 stop bit.
// This is the standard baud rate. The card we have has a custom crystal
// changing this baud rate to 125K.
dcb.BaudRate = static_cast<DWORD>(mBaudRate);
dcb.ByteSize = static_cast<BYTE>(mByteSize);
// enum values are ame as dcb.Parity defines
dcb.Parity = static_cast<BYTE>(mParity);
dcb.fParity = (mParity == SerialCommBase::PRTY_NONE)? FALSE : TRUE;
dcb.StopBits = ONESTOPBIT;
// ----------------------------------------------------
// When running in win32 loopback with the simulator
// in loopback mode, we must enable the RTS/CTS handshake
// mode as there seems to be a 4K limit in the input
// buffer when the DBU Simulator performs reads.
// ----------------------------------------------------
if (mFlowControl == SerialCommBase::FCTL_RTS_CTS) {
dcb.fOutxCtsFlow = 1;
dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
}
// Not absolutely necessary as the DTR_CONTROL_DISABLE is default
dcb.fDtrControl = DTR_CONTROL_DISABLE;
isOK = SetCommState (mOsFileHandle, &dcb);
if (isOK) {
COMMTIMEOUTS commTimeouts;
SecureZeroMemory(&commTimeouts, sizeof(COMMTIMEOUTS));
// These settings will cause ReadFile to return
// immediately if there is no data available at the port
// A value of MAXDWORD, combined with zero values for both the
// ReadTotalTimeoutConstant and ReadTotalTimeoutMultiplier members,
// specifies that the read operation is to return immediately with
// the bytes that have already been received, even if no bytes
// have been received.
//isOK = GetCommTimeouts (mOsFileHandle, &CommTimeouts);
commTimeouts.ReadIntervalTimeout = MAXDWORD;
// ReadTotalTimeoutConstant - when set with a ms timeout value
// in conjunction with will ReadIntervalTimeout == MAXDWORD &&
// ReadTotalTimeoutMultiplier set to 0 be used to control the
// timeout for the read operation. Each time the read with a
// timeout is called, we compare the existing timeouts in CommTimeouts
// before changing it.
commTimeouts.ReadTotalTimeoutConstant = 0;
commTimeouts.ReadTotalTimeoutMultiplier = 0;
// timeouts not used for write operations
commTimeouts.WriteTotalTimeoutConstant = 0;
commTimeouts.WriteTotalTimeoutMultiplier = 0;
isOK = SetCommTimeouts (mOsFileHandle, &commTimeouts);
if (isOK) {
// test for asynchronous mode
if (mFlowControl == SerialCommBase::FCTL_OVERLAPPED) {
// allocate & initialize overlapped
// structure support for rx & tx
mpOverlappedTx.reset(new(OVERLAPPED));
mpOverlappedRx.reset(new(OVERLAPPED));
if (mpOverlappedTx && mpOverlappedRx) {
SecureZeroMemory(mpOverlappedTx.get(), sizeof(OVERLAPPED));
SecureZeroMemory(mpOverlappedRx.get(), sizeof(OVERLAPPED));
// create an unsignaled manual reset (2nd Param TRUE)
// event used for GetOverlappedResult. This event will
// be signaled by the ReadFile to indicate when
// IO operations are complete or encounter errors
mpOverlappedTx->hEvent = CreateEvent(
NULL, TRUE, FALSE, NULL);
if (mpOverlappedTx->hEvent != NULL) {
// now do the same for the RX side
mpOverlappedRx->hEvent = CreateEvent(
NULL, TRUE, FALSE, NULL);
if (mpOverlappedRx->hEvent != NULL) {
setState(COMM_OPENED);
result = OS_SUCCESS;
} else {
result = handleError(deviceName);
}
} else {
result = handleError(deviceName);
}
// close the handle and set error
if (result != OS_SUCCESS) {
close();
setState(COMM_OPEN_FAILED);
}
} else {
// close the handle and overlapped event
close();
setState(COMM_OPEN_FAILED);
result = OS_NO_MEMORY;
}
} else { // blocking mode
setState(COMM_OPENED);
result = OS_SUCCESS;
}
} else {
result = handleError(deviceName);
close();
}
} else { // unable to set the baud rate or something
result = handleError(deviceName);
close();
}
}
} else {
result = handleError(deviceName);
close();
}
return result;
}
下面是执行定时读取的代码
/**
* Read a block of data into the specified raw buffer.
* See http://msdn.microsoft.com/en-us/library/ms810467(v=MSDN.10).aspx
* for details for Overlapped IO usage, in particular note that setting
* the timeout each time is tricky.
*
* @param pData [in/out] data buffer
* @param rNumBytes [in] buffer size
* @param rTimeout [in/out] timeout specified in milliseconds.
* This parameter is updated to reflect the
* remaining time.
* @param rNumBytesRead
* [out] number of bytes read
*
* @return OS_SUCCESS, OS_WAIT_TIMEOUT, OS_INVALID_ARGUMENT or
* OS_FAILED
*/
OsStatus
SerialCommWnt::read(
void* pData,
const size_t& rNumBytes,
milliseconds& rTimeout,
size_t& rNumBytesRead)
{
OsStatus result = OS_WAIT_TIMEOUT;
rNumBytesRead = 0;
DWORD numBytesRead = 0;
DWORD commError;
COMSTAT commStatus;
auto startTime = system_clock::now();
if (mpOverlappedRx) {
// update the timeout used for ReadFile - note that the
// magic combination that works for an absolute timeout is
// MAXDWORD, timeoutMS, 0.
COMMTIMEOUTS commTimeouts;
GetCommTimeouts(mOsFileHandle, &commTimeouts);
if (commTimeouts.ReadTotalTimeoutConstant != rTimeout.count()) {
commTimeouts.ReadIntervalTimeout = MAXDWORD;
commTimeouts.ReadTotalTimeoutConstant =
static_cast<DWORD>(rTimeout.count());
SetCommTimeouts (mOsFileHandle, &commTimeouts);
}
// asynchronous overlapped IO mode.
// reset the manual event to the non-signaled.
// No Need for this as ReadFile resets it by itself
// ResetEvent(mpOverlappedRx->hEvent);
BOOL isOK = ReadFile(
mOsFileHandle, pData, (DWORD)rNumBytes,
reinterpret_cast<DWORD*>(&rNumBytesRead),
mpOverlappedRx.get());
// get the result to date - only valid to call this
// if ReadFile returns !isOK (FALSE) &&
// last error set to ERROR_IO_PENDING
//milliseconds elapsedTime;
if (!isOK) {
DWORD dwLastError = GetLastError();
if (dwLastError == ERROR_IO_PENDING) {
// pending IO, wait to complete using the COMMTIMEOUTS timer.
// when the COMMTIMEOUTS timer expires it will signal the
// manual mpOverlappedRx->hEvent
DWORD ovlStatus = ::WaitForSingleObject(
mpOverlappedRx->hEvent, static_cast<DWORD>(
/*rTimeout.count()*/INFINITE));
switch (ovlStatus) {
case WAIT_TIMEOUT:
// timeout - update the remaining time to 0
rTimeout = milliseconds::zero();
result = OS_WAIT_TIMEOUT;
//elapsedTime = duration_cast<milliseconds>(
// system_clock::now() - startTime);
break;
case WAIT_OBJECT_0:
// now that we have some data avaialable
// read it from overlapped IO
isOK = ::GetOverlappedResult(
mOsFileHandle, mpOverlappedRx.get(),
reinterpret_cast<DWORD*>(&rNumBytesRead),
FALSE);
result = (isOK && rNumBytesRead>0)?
OS_SUCCESS : OS_FAILED;
//elapsedTime = duration_cast<milliseconds>(
// system_clock::now() - startTime);
// update the remaing time (cannot be < 0)
rTimeout = std::max<milliseconds>(
rTimeout - duration_cast<milliseconds>(
system_clock::now() - startTime),
milliseconds::zero());
break;
default:
rTimeout = milliseconds::zero();
break;
}
} else if (dwLastError == ERROR_HANDLE_EOF) {
ClearCommError(mOsFileHandle, &commError, &commStatus);
result = OS_FILE_EOF;
} else {
ClearCommError(mOsFileHandle, &commError, &commStatus);
result = OS_FAILED;
}
} else { // Success
//elapsedTime = duration_cast<milliseconds>(
// system_clock::now() - startTime);
rTimeout = std::max<milliseconds>(
rTimeout - duration_cast<milliseconds>(
system_clock::now() - startTime),
milliseconds::zero());
result = OS_SUCCESS;
}
} else { // sync mode
BOOL isOK = ReadFile ( mOsFileHandle, pData, (DWORD)rNumBytes,
reinterpret_cast<LPDWORD>(&numBytesRead), NULL);
if ( isOK && (numBytesRead > 0) ) {
rNumBytesRead = (size_t) numBytesRead;
result = OS_SUCCESS;
} else {
ClearCommError(mOsFileHandle, &commError, &commStatus);
// @JC Changed from simple test if lpErrors == 9)
// which is equivalent to (CE_BREAK | CE_RXOVER)
//if ((lpErrors & (CE_BREAK | CE_FRAME | CE_OVERRUN |
// CE_RXOVER | CE_RXPARITY)) != 0x00) {
if (commError == 9) {
result = OS_FAILED;
// printf ("ClearCommError - lpErrors[%02x]", lpErrors);
}
}
// update the remaing time (cannot be < 0)
rTimeout = std::max<milliseconds>(
rTimeout - duration_cast<milliseconds>(
system_clock::now() - startTime),
milliseconds::zero());
}
return result;
}
最佳答案
if (dwLastError == ERROR_IO_PENDING) {
DWORD ovlStatus = ::WaitForSingleObject(mpOverlappedRx->hEvent, ...);
//...
}
当程序员使用重叠 I/O 时,这是一个非常常见的错误。核心思想是您使用它允许设备驱动程序在第一次调用 ReadFile() 时开始处理作业。这将需要一段时间,I/O 总是如此,尤其是串行端口,因为它们是非常慢的设备。
所以你问司机“开始吧”,它就开始工作了。最终,驱动程序将通过调用 OVERLAPPED.hEvent 上的 SetEvent() 方法来发出完成信号。这将完成您的 WaitForSingleObject() 调用。
当驱动程序处理它时,您应该做的是其他。您的线程应该做的另一项工作,在驱动程序处理 I/O 请求时很有用。例如,您可以用它点亮 MsgWaitForMultipleObjects()。它会触发一个消息循环,因此您的 UI 仍然可以响应。并且还会告诉您串口何时有可用的新数据。
代码中的缺陷在于您不知道还能做什么。它立即调用 WaitForSingleObject() 以等待重叠 I/O 完成。在驱动程序处理读取请求时阻塞线程而不做任何有用的工作。这是一个非常普遍的问题。
换句话说,您还没有找到使用重叠 I/O 的充分理由。通过使用同步 ReadFile() 调用,您将获得完全相同的结果。它会像您当前的代码一样阻塞,直到串行端口有可用数据。
所以不要理会它。也解决了超时问题。
关于c++ - 如何正确使用 COMMTIMEOUTS 和从串口读取的 OVERLAPPED IO 模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18216940/
我在网上搜索但没有找到任何合适的文章解释如何使用 javascript 使用 WCF 服务,尤其是 WebScriptEndpoint。 任何人都可以对此给出任何指导吗? 谢谢 最佳答案 这是一篇关于
我正在编写一个将运行 Linux 命令的 C 程序,例如: cat/etc/passwd | grep 列表 |剪切-c 1-5 我没有任何结果 *这里 parent 等待第一个 child (chi
所以我正在尝试处理文件上传,然后将该文件作为二进制文件存储到数据库中。在我存储它之后,我尝试在给定的 URL 上提供文件。我似乎找不到适合这里的方法。我需要使用数据库,因为我使用 Google 应用引
我正在尝试制作一个宏,将下面的公式添加到单元格中,然后将其拖到整个列中并在 H 列中复制相同的公式 我想在 F 和 H 列中输入公式的数据 Range("F1").formula = "=IF(ISE
问题类似于this one ,但我想使用 OperatorPrecedenceParser 解析带有函数应用程序的表达式在 FParsec . 这是我的 AST: type Expression =
我想通过使用 sequelize 和 node.js 将这个查询更改为代码取决于在哪里 select COUNT(gender) as genderCount from customers where
我正在使用GNU bash,版本5.0.3(1)-发行版(x86_64-pc-linux-gnu),我想知道为什么简单的赋值语句会出现语法错误: #/bin/bash var1=/tmp
这里,为什么我的代码在 IE 中不起作用。我的代码适用于所有浏览器。没有问题。但是当我在 IE 上运行我的项目时,它发现错误。 而且我的 jquery 类和 insertadjacentHTMl 也不
我正在尝试更改标签的innerHTML。我无权访问该表单,因此无法编辑 HTML。标签具有的唯一标识符是“for”属性。 这是输入和标签的结构:
我有一个页面,我可以在其中返回用户帖子,可以使用一些 jquery 代码对这些帖子进行即时评论,在发布新评论后,我在帖子下插入新评论以及删除 按钮。问题是 Delete 按钮在新插入的元素上不起作用,
我有一个大约有 20 列的“管道分隔”文件。我只想使用 sha1sum 散列第一列,它是一个数字,如帐号,并按原样返回其余列。 使用 awk 或 sed 执行此操作的最佳方法是什么? Accounti
我需要将以下内容插入到我的表中...我的用户表有五列 id、用户名、密码、名称、条目。 (我还没有提交任何东西到条目中,我稍后会使用 php 来做)但由于某种原因我不断收到这个错误:#1054 - U
所以我试图有一个输入字段,我可以在其中输入任何字符,但然后将输入的值小写,删除任何非字母数字字符,留下“。”而不是空格。 例如,如果我输入: 地球的 70% 是水,-!*#$^^ & 30% 土地 输
我正在尝试做一些我认为非常简单的事情,但出于某种原因我没有得到想要的结果?我是 javascript 的新手,但对 java 有经验,所以我相信我没有使用某种正确的规则。 这是一个获取输入值、检查选择
我想使用 angularjs 从 mysql 数据库加载数据。 这就是应用程序的工作原理;用户登录,他们的用户名存储在 cookie 中。该用户名显示在主页上 我想获取这个值并通过 angularjs
我正在使用 autoLayout,我想在 UITableViewCell 上放置一个 UIlabel,它应该始终位于单元格的右侧和右侧的中心。 这就是我想要实现的目标 所以在这里你可以看到我正在谈论的
我需要与 MySql 等效的 elasticsearch 查询。我的 sql 查询: SELECT DISTINCT t.product_id AS id FROM tbl_sup_price t
我正在实现代码以使用 JSON。 func setup() { if let flickrURL = NSURL(string: "https://api.flickr.com/
我尝试使用for循环声明变量,然后测试cols和rols是否相同。如果是,它将运行递归函数。但是,我在 javascript 中执行 do 时遇到问题。有人可以帮忙吗? 现在,在比较 col.1 和
我举了一个我正在处理的问题的简短示例。 HTML代码: 1 2 3 CSS 代码: .BB a:hover{ color: #000; } .BB > li:after {
我是一名优秀的程序员,十分优秀!