How to fix timeout on rs232 serial port? - c++
I have a problem when reading from the serial port.
The problem is that for the last 2 bytes ( CRC bytes ) read from an rs232 port the read waits until the timeout set in timeval ends, then returns. On rs485, with the same method used for reading, read returns fine. What I have seen while debbuging is that on rs485 there is an extra byte with value FF after the 2 CRC bytes. I can't find another difference between the 2.
Here are the relevant parts of code:
setting the port
bool Serial::setup(){
if(!openPort()){
return false;
}
tcgetattr(fdPort, &options);
cfsetispeed(&options, B115200);
cfsetospeed(&options, B115200);
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
options.c_cc[VMIN] = 0;
options.c_cc[VTIME] = 1;
options.c_oflag &= ~(OCRNL | ONLCR | ONLRET |
ONOCR | OFILL | OLCUC | OPOST);
options.c_iflag &= ~(IGNBRK | BRKINT | ICRNL | INLCR |
PARMRK | INPCK | ISTRIP | IXON) ;
options.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
if(tcsetattr(this->fdPort, TCSANOW, &options)){
return false;
}
return true;
}
opening the port
bool Serial::openPort(){
this->fdPort = open(this->port, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
if(fdPort == -1){
return false;
}
else{
//fcntl(fdPort, F_SETFL, 0);
//fcntl(fdPort, F_SETFL, FNDELAY);
}
int status = 0;
status |= TIOCM_RTS;
ioctl(this->fdPort, TIOCMSET, &status);
return true;
}
The wait frame where data is interpreted and read in chunks.
bool GlobalProtocol::WaitFrame(uint32_t timeOut) {
int32_t bytesRec = 0;
int32_t bytesToRec = 1;
int recPhase = GC_PHASE_START;
uint8_t *pData = m_RxBuff;
bool commSuccess = true;
m_LastError = boards::GCL_ERR_OK;
while (readData(pData, bytesToRec, &bytesRec, timeOut)) {
if (bytesRec) {
switch (recPhase) {
case GC_PHASE_START:
if (*pData != GC_START_FRAME_BYTE) {
continue;
}
recPhase++;
pData++;
break;
case GC_PHASE_DEST:
if (*pData != m_MasterAddr) {
commSuccess = false;
break;
}
recPhase++;
pData++;
break;
case GC_PHASE_SRC:
recPhase++;
pData++;
break;
case GC_PHASE_LEN_LO:
if (*pData < 2 || *pData > GC_MAX_COMM_DATA_LEN) {
commSuccess = false;
break;
}
recPhase++;
pData++;
break;
case GC_PHASE_LEN_HI:
if (*pData != 0) {
commSuccess = false;
break;
}
recPhase++;
pData++;
bytesToRec = m_RxBuff[GC_PHASE_LEN_LO];
break;
case GC_PHASE_DATA:
if (bytesRec != bytesToRec) {
commSuccess = false;
break;
}
recPhase++;
pData += bytesRec;
bytesToRec = 2;
break;
case GC_PHASE_CRC_LO:
if (bytesRec != bytesToRec) {
commSuccess = false;
break;
}
if (CheckCRC(m_RxBuff, m_RxBuff[GC_PHASE_LEN_LO] + GC_PHASE_DATA + sizeof(uint16_t))) {
m_RecAddr = m_RxBuff[GC_PHASE_SRC];
return true;
}
commSuccess = false;
break;
}
if (!commSuccess) break;
}
else break;
}
m_LastError = boards::GCL_ERR_ANSWERNOTREC;
return false;
}
And where the reading is done.
bool Serial::readData(uint8_t *data, uint32_t length, int32_t *receivedDataBytes, int32_t timeoutVal){
int32_t tempReceivedDataBytes = -1;
fd_set readFd;
FD_ZERO(&readFd);
FD_SET(fdPort, &readFd);
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = timeoutVal * 1000;
int test = 0;
uint32_t bytesAvail = 0;
QTime timer;
timer.start();
if(fcntl(fdPort, F_GETFD) != -1){
while(((test = select(this->fdPort + 1, &readFd, NULL, NULL, &timeout)) == 1) && (tempReceivedDataBytes == -1)){
ioctl(fdPort, FIONREAD, &bytesAvail);
if(FD_ISSET(fdPort, &readFd) && bytesAvail >= length){
tempReceivedDataBytes = read(fdPort, data, length);
}
if(timer.elapsed() > (timeoutVal + 5)){ //fail-safe
logger[debug_log] << "TIMEOUT" << endl;
break;
}
}
if(test == -1)
logger[debug_log]<< strerror(errno) << endl;
if(tempReceivedDataBytes < 0){
return false;
}
if(tempReceivedDataBytes >= 0){
*receivedDataBytes = tempReceivedDataBytes;
return true;
}
}
return false;
}
If I set the timeout to 100 ms, then it waits 100 ms to read the 2 bytes, if I set it to 10 ms, then it waits 10 ms to read the 2 bytes.
I tried changing the port settings, but with no success.
I have been trying to solve this for days but with no success.
Edit:
I should add that ioctl(fdPort, FIONREAD, &bytesAvail); is setting bytesAvail to 2, but read waits until timeout to read them.
Edit 2:
Here is a log with a timeout set to 25 seconds so you can get an idea of what's the problem:
04/17/2014 15:51:50:584,Main board start:
04/17/2014 15:51:50:586,1 Received 1 Needed to receive 1
04/17/2014 15:51:50:586,1 Received 1 Needed to receive 1
04/17/2014 15:51:50:586,1 Received 1 Needed to receive 1
04/17/2014 15:51:50:587,1 Received 1 Needed to receive 1
04/17/2014 15:51:50:587,1 Received 1 Needed to receive 1
04/17/2014 15:51:50:597,1 Received 110 Needed to receive 110
04/17/2014 15:51:50:597,1 Received 2 Needed to receive 2
04/17/2014 15:51:50:634,PID board start:
04/17/2014 15:51:50:635,1 Received 1 Needed to receive 1
04/17/2014 15:51:50:635,1 Received 1 Needed to receive 1
04/17/2014 15:51:50:635,1 Received 1 Needed to receive 1
04/17/2014 15:51:50:635,1 Received 1 Needed to receive 1
04/17/2014 15:51:50:635,1 Received 1 Needed to receive 1
04/17/2014 15:51:50:641,1 Received 70 Needed to receive 70
04/17/2014 15:52:15:647,0 Received 2 Needed to receive 2
04/17/2014 15:52:15:647,Set Leds board start:
04/17/2014 15:52:15:649,1 Received 1 Needed to receive 1
04/17/2014 15:52:15:649,1 Received 1 Needed to receive 1
04/17/2014 15:52:15:652,1 Received 1 Needed to receive 1
04/17/2014 15:52:15:652,1 Received 1 Needed to receive 1
04/17/2014 15:52:15:652,1 Received 1 Needed to receive 1
04/17/2014 15:52:15:652,1 Received 2 Needed to receive 2
04/17/2014 15:52:15:652,1 Received 2 Needed to receive 2
04/17/2014 15:52:15:652,Get state board start:
04/17/2014 15:52:15:654,1 Received 1 Needed to receive 1
04/17/2014 15:52:15:654,1 Received 1 Needed to receive 1
04/17/2014 15:52:15:654,1 Received 1 Needed to receive 1
04/17/2014 15:52:15:654,1 Received 1 Needed to receive 1
04/17/2014 15:52:15:655,1 Received 1 Needed to receive 1
04/17/2014 15:52:15:657,1 Received 30 Needed to receive 30
04/17/2014 15:52:15:657,1 Received 2 Needed to receive 2
The one with the problems is the PID board ( on a rs232), the others are on the same rs485.
And here is one with a timeout set to around 30 ms ( I can't remember the exact value):
04/17/2014 15:08:08:045,Main board start:
04/17/2014 15:08:08:046,1 Received 1 Needed to receive 1
04/17/2014 15:08:08:046,1 Received 1 Needed to receive 1
04/17/2014 15:08:08:046,1 Received 1 Needed to receive 1
04/17/2014 15:08:08:047,1 Received 1 Needed to receive 1
04/17/2014 15:08:08:047,1 Received 1 Needed to receive 1
04/17/2014 15:08:08:056,1 Received 110 Needed to receive 110
04/17/2014 15:08:08:056,1 Received 2 Needed to receive 2
04/17/2014 15:08:08:078,PID board start:
04/17/2014 15:08:08:079,1 Received 1 Needed to receive 1
04/17/2014 15:08:08:079,1 Received 1 Needed to receive 1
04/17/2014 15:08:08:079,1 Received 1 Needed to receive 1
04/17/2014 15:08:08:079,1 Received 1 Needed to receive 1
04/17/2014 15:08:08:079,1 Received 1 Needed to receive 1
04/17/2014 15:08:08:094,1 Received 70 Needed to receive 70
04/17/2014 15:08:08:120,0 Received 2 Needed to receive 2
04/17/2014 15:08:08:120,Set Leds board start:
04/17/2014 15:08:08:122,1 Received 1 Needed to receive 1
04/17/2014 15:08:08:122,1 Received 1 Needed to receive 1
04/17/2014 15:08:08:122,1 Received 1 Needed to receive 1
04/17/2014 15:08:08:122,1 Received 1 Needed to receive 1
04/17/2014 15:08:08:122,1 Received 1 Needed to receive 1
04/17/2014 15:08:08:122,1 Received 2 Needed to receive 2
04/17/2014 15:08:08:122,1 Received 2 Needed to receive 2
04/17/2014 15:08:08:123,Get state board start:
04/17/2014 15:08:08:124,1 Received 1 Needed to receive 1
04/17/2014 15:08:08:124,1 Received 1 Needed to receive 1
04/17/2014 15:08:08:124,1 Received 1 Needed to receive 1
04/17/2014 15:08:08:125,1 Received 1 Needed to receive 1
04/17/2014 15:08:08:125,1 Received 1 Needed to receive 1
04/17/2014 15:08:08:128,1 Received 30 Needed to receive 30
04/17/2014 15:08:08:128,1 Received 2 Needed to receive 2
Edit: I still can't figure out what is wrong. If I remove the extra byte on rs485 it is the same. Here is another log:
06/24/2014 12:57:01:923,Set Leds board start:
06/24/2014 12:57:06:701,Select value 1 Received: 1 Needed: 1 Bytes available: 9
06/24/2014 12:57:06:701,Select value 1 Received: 1 Needed: 1 Bytes available: 8
06/24/2014 12:57:06:702,Select value 1 Received: 1 Needed: 1 Bytes available: 7
06/24/2014 12:57:06:702,Select value 1 Received: 1 Needed: 1 Bytes available: 6
06/24/2014 12:57:06:702,Select value 1 Received: 1 Needed: 1 Bytes available: 5
06/24/2014 12:57:06:702,Select value 1 Received: 2 Needed: 2 Bytes available: 4
06/24/2014 12:57:06:752,Select value 0 Received: 2 Needed: 2 Bytes available: 2
06/24/2014 12:57:06:752,Get state board start:
06/24/2014 12:57:06:754,Select value 1 Received: 1 Needed: 1 Bytes available: 4
06/24/2014 12:57:06:754,Select value 1 Received: 1 Needed: 1 Bytes available: 3
06/24/2014 12:57:06:754,Select value 1 Received: 1 Needed: 1 Bytes available: 2
06/24/2014 12:57:06:754,Select value 1 Received: 1 Needed: 1 Bytes available: 1
06/24/2014 12:57:06:755,Select value 1 Received: 1 Needed: 1 Bytes available: 10
06/24/2014 12:57:06:758,Select value 1 Received: 30 Needed: 30 Bytes available: 30
06/24/2014 12:57:06:808,Select value 0 Received: 2 Needed: 2 Bytes available: 2
06/24/2014 12:57:06:886,Main board start:
06/24/2014 12:57:06:888,Select value 1 Received: 1 Needed: 1 Bytes available: 3
06/24/2014 12:57:06:888,Select value 1 Received: 1 Needed: 1 Bytes available: 2
06/24/2014 12:57:06:889,Select value 1 Received: 1 Needed: 1 Bytes available: 1
06/24/2014 12:57:06:890,Select value 1 Received: 1 Needed: 1 Bytes available: 23
06/24/2014 12:57:06:890,Select value 1 Received: 1 Needed: 1 Bytes available: 22
06/24/2014 12:57:06:898,Select value 1 Received: 110 Needed: 110 Bytes available: 113
06/24/2014 12:57:06:898,Select value 1 Received: 2 Needed: 2 Bytes available: 3
As you can see when the number of available bytes is equal with the number of bytes to read it waits in the read function until timeout and then returns.
What hardware are you using? Real serial port or usb adapter? Some FTDI usb to serial adapters are configured so they send the bytes over usb in batches. That speeds up the transfer when the port is fully loaded but they behave like you mentioned when dealing with few bytes at a time.
I managed to fix it. It was a simple fix.
I had to replace while(((test = select(this->fdPort + 1, &readFd, NULL, NULL, &timeout)) == 1) && (tempReceivedDataBytes == -1))
with while( (tempReceivedDataBytes == -1) && ((test = select(this->fdPort + 1, &readFd, NULL, NULL, &timeout)) == 1))
.
If the serial buffer was empty it was waiting in select until timeout, even if it read something. If there was someting on the port it was checking the second part of the while and exiting it.
Set a non-zero value of VMIN, so that the read can be satisfied as soon as at least that many characters have been received.
This would mean that:
If no data has been buffered, the call will wait up to timeout for some data
If at least VMIN characters have been buffered, the call will return immediately with those, without waiting for the timeout.
Related
Readfile API not reading anything while reading we are getting buffer as empty
Here is some details Note:- All command are working fine with OSCALL function in compiler VC12 with complier VC14 exe name is RemDicomNodes.exe CMD command prompt:- RemDicomNodes 5 6 1 2 3 10 8 9 RemDicomNodes.exe 1 A RemDicomNodes 2 B B 0 localhost 1 "BE" 104 3 1 7 7 60 0 "" 2 0 0 0 0 "" 3 0 0 0 0 "" 0 6 1 2 3 10 8 9 0 0 0 0 NoConversion 0 0 0 0 1 0 0 1 BE 0 0 0 IPv4 0 0 10 0 1 0 Above all commands are working fine and showing proper output on CMD command prompt With OSCAll function:- RemDicomNodes 5 6 1 2 3 10 8 9 #(Working fine i am getting output in variable "outputbuffer" which i am using inside readfile API) RemDicomNodes.exe 1 A #(Working fine i am getting output in variable "outputbuffer" which i am using inside readfile API) RemDicomNodes.exe 2 B B 0 localhost 1 """BE"""" " 104 3 1 7 7 60 0 " """""" " 2 0 0 0 0 " """""" " 3 0 0 0 0 " """"""" 0 6 1 2 3 10 8 9 0 0 0 0 NoConversion 0 0 0 0 1 0 0 0 AE 0 0 0 IPv4 0 0 10 0 1 0" #Problem(that any arguments we are send but it is not working, i am not getting output in variable "outputbuffer" which i am using inside readfile API it is not printing anything ) This is the function which i am using to run my exe BOOL MagicWatchComProc::OSCall(CString i_cmd, CString& a_output, DWORD& a_exitCode, long i_timeOut) { STARTUPINFO aStartupInfo; PROCESS_INFORMATION aProcessInfo; HANDLE hReadHandle = NULL; HANDLE hWriteHandle = NULL; HANDLE hErrorHandle = NULL; DWORD dwBytesRead = 0; SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; //time_t l_timeOut = 300000; //5 min. //reset output string a_output = ""; DEBUG_TRACE(_T("OSCall: launching ") + i_cmd); if (!i_cmd) { DEBUG_TRACE(_T("OSCall: Error: empty command\n")); return false; } //reset errors SetLastError(0); // Initialize process startup structure FillMemory(&aStartupInfo, sizeof(aStartupInfo), 0); //GetStartupInfo(&aStartupInfo); aStartupInfo.cb = sizeof(aStartupInfo); aStartupInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; aStartupInfo.wShowWindow = SW_HIDE; // Create pipe that will transfer the process output to our buffer if(!CreatePipe(&hReadHandle, &hWriteHandle, &sa, 0)) { DEBUG_TRACE(_T("OSCall: Error: Pipe creation\n")); return false; } // Set process' stdout to our pipe aStartupInfo.hStdOutput = hWriteHandle; // We are going to duplicate our pipe's write handle // and pass it as stderr to create process. The idea // is that some processes have been known to close // stderr which would also close stdout if we passed // the same handle. Therefore we make a copy of stdout's // pipe handle. if (!DuplicateHandle( GetCurrentProcess(), hWriteHandle, GetCurrentProcess(), &hErrorHandle, 0, TRUE, DUPLICATE_SAME_ACCESS )) { CloseHandle(hReadHandle); CloseHandle(hWriteHandle); DEBUG_TRACE(_T("OSCall: Error: duplicate handle\n")); return false; } aStartupInfo.hStdError = hErrorHandle; // Check input parameter TCHAR l_inputCommand[2048]; _tcscpy(l_inputCommand, i_cmd); // Create process of service program if(!CreateProcess( NULL, l_inputCommand, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &aStartupInfo, &aProcessInfo )) { CloseHandle(hReadHandle); CloseHandle(hWriteHandle); CloseHandle(hErrorHandle); DEBUG_TRACE(_T("OSCall: Error: could not create process\n")); return false; } // The process is alive now and has inherited the environment, now // we can release the critical section // Close the write end of our pipe (both copies) // so it will die when the child process terminates CloseHandle(hWriteHandle); CloseHandle(hErrorHandle); // We close the handle of the process in order to prevent memory leaks when // the process terminates. //CloseHandle(aProcessInfo.hThread); // Allocate memory for output buffer DWORD dwAvailableOutput = 16; CHAR outputbuffer[18]; //CString strPipeName; //DWORD dwSize = 0; //GetNamedPipeHandleState( hReadHandle, NULL, NULL, NULL, NULL, strPipeName.GetBuffer(1), dwSize ); //WaitNamedPipe( strPipeName, 100 ); // -> Read output from CGI program time_t l_time; time_t l_startTime; time(&l_startTime); do { time(&l_time); if( (l_time - l_startTime) > i_timeOut) { SetLastError(WAIT_TIMEOUT); break; } if( ReadFile( hReadHandle, outputbuffer, dwAvailableOutput, &dwBytesRead, NULL ) ) { outputbuffer[dwBytesRead] = 0; // null terminate a_output += outputbuffer; } } //We are done while ( GetLastError() != ERROR_BROKEN_PIPE ); //reset ERROR_BROKEN_PIPE error if(GetLastError() == ERROR_BROKEN_PIPE) SetLastError(0); //DEBUG_TRACE(_T("OSCall: command output: ") + a_output); //CloseHandle(hErrorHandle); CloseHandle(hReadHandle); if( !GetLastError() ) { return true; } else { DEBUG_TRACE(_T("OSCall: Error: cmd command failed. Error code: ")+ i2cs(GetLastError()) +_T("; ExitCode: ")+ i2cs(a_exitCode) +_T(".")); return false; } } int main() { DWORD dwExitCode = 0; long l_timeOut = 60000; //ms = 10 min BOOL bRet = FALSE; CString strInstallLmutil(_T("cmd.exe /C ")); CString strLmutilInstallFile(_T("remdicomnodes.exe")); CString strPathLmutilInstall; strPathLmutilInstall.Format(_T("%s\\bin\\%s"),strtemp,strLmutilInstallFile); strInstallOption = _T(""); strInstallOption = _T(" 2 B B 0 localhost 1 \"""BE""\"" " 104 3 1 7 7 60 0 " "\"""\"" " 2 0 0 0 0 " "\"""\"" " 3 0 0 0 0 " "\"""\""" 0 6 1 2 3 10 8 9 0 0 0 0 NoConversion 0 0 0 0 1 0 0 0 AE 0 0 0 IPv4 0 0 10 0 1 0"); bRet = OSCall ( cmd, l_commandOutput, dwExitCode, l_timeOut); SAM_TRACE1("OSCall: bRet value: :%d ",bRet); if( bRet == FALSE ) { SAM_TRACE0("remdicomnodes.exe execution failed \n"); } return 0; }
Multithreading has no effect in performance
I am working on my packet sniffer. there is a workerConnection() function that performs main processes on packets as follow . It reads a packet from _Connection_buffer that is defined as std::string* _Connection_buffer= new std::string[_Max_Element_Connection_buffer], then splits the packets by its white spaces and performs some actions on them. everythings works well except performance of parallel processing of workerConnection(). As it can be seen in the workerConnection(), in the first loop, each thread takes a unique number as its own 'MyID'. then uses its MyID as an offset for reading packets from _Connection_buffer. I am sure by parallel processing of workerConnection() each thread does not process all packets and only process (_Max_Element_Connection_buffer/_ConnectionThreadCount) packets. void workerConnection() { short MyID = 0; _Connection_tn->_mtx.lock(); for (int n = 0; n < _ConnectionThreadCount; n++) { if (_Connection_tn->getMyNumber[n] != 100) { MyID = _Connection_tn->getMyNumber[n]; _Connection_tn->getMyNumber[n] = 100; break; } } _Connection_tn->_mtx.unlock(); LOG_INFO("Session Worker :%d started", MyID); long int index = 0; s_EntryItem* entryItem = NULL; uint32_t srcIP_num; uint64_t p_counter=0; std::string connectionPayload1 = ""; connectionPayload1.reserve(40); std::string connectionPayload2 = ""; connectionPayload2.reserve(40); std::string connectionPayload = ""; connectionPayload.reserve(150); std::string part; part.reserve(30); std::string srcIP_str; srcIP_str.reserve(15); std::string t; t.reserve(50); std::string line; line.reserve(_snapLengthConnection + 1); std::string Protocol; Protocol.reserve(3); std::string srcIP_port; Protocol.reserve(7); std::vector<std::string> _CStorage(_storage_Count_Connection); struct timeval start, end; long mtime, secs, usecs; gettimeofday(&start, NULL); for (index = MyID; index < _Max_Element_Connection_buffer; index+=_ConnectionThreadCount) { if (unlikely(p_counter++ >= (_Connection_flag->_Number - MyID)) ) { LOG_INFO("sleeped"); boost::this_thread::sleep(boost::posix_time::milliseconds(20)); continue; } line = _Connection_buffer[index]; if(line.size()<_storage_Count_Connection) continue; part = line.substr(_column_ConnectionConditionLocation, ConnectionCondition.length() + 5); if (part.find("My Packet") == std::string::npos) { //assume always false. LOG_INFO("Part: %s, Condition: %s", part.c_str(), ConnectionCondition.c_str()); continue; } boost::split(_CStorage,line,boost::is_any_of(" ")); t = _CStorage[_column_ConnectionUserIP]; auto endSource = t.find("/", 0); srcIP_str = t.substr(0, endSource); try { srcIP_num = boost::asio::ip::address_v4::from_string(srcIP_str).to_ulong(); } catch (...) { continue; } entryItem = searchIPTable(srcIP_num); if (entryItem == NULL) { continue; } int ok = processConnection(srcIP_num, connectionPayload1, connectionPayload2, &_CStorage); if (!ok) { continue; } auto startSource = t.find("/", 8) + 1; endSource = t.find("-", startSource); connectionPayload2+=t.substr(startSource, endSource - startSource); connectionPayload2+=_CStorage[_column_ConnectionProtocol]; entryItem->_mtx.lock(); if (entryItem->InUse != false) { connectionPayload = entryItem->payload1; connectionPayload += connectionPayload1; connectionPayload += entryItem->payload2; connectionPayload += connectionPayload2; } entryItem->_mtx.unlock(); } gettimeofday(&end, NULL); secs = end.tv_sec - start.tv_sec; usecs = end.tv_usec - start.tv_usec; mtime = ((secs) * 1000 + usecs/1000.0) + 0.5; LOG_INFO("Worker %d :Elapsed time for %lu times running Connection Worker is %ld millisecs\n",MyID,index, mtime); LOG_INFO("Connection Worker %d :stopped",MyID); } so now, there is a problem that drives me crazy . processing all the packets using one or 2 or n threads takes equal time. as said earlier, on multithreading, i am sure each threads process only _Max_Element_Connection_buffer/_ConnectionThreadCount packets. I ran my program on a virtual ubuntu 14.04 which has 20G RAM and 4 CPUs. the host OS windows 8 and has 8 CPUs. the specification of one of my vitual ubuntu processor is shown below: processor : 3 vendor_id : GenuineIntel cpu family : 6 model : 60 model name : Intel(R) Core(TM) i5-4460 CPU # 3.20GHz stepping : 3 cpu MHz : 3192.718 cache size : 6144 KB physical id : 0 siblings : 4 core id : 3 cpu cores : 4 the results of processing my program with 1, 2, 4 and 8 threads are as follow: Number of _Connection_buffer elements= 10,000 using one thread: Worker 0 :Elapsed time for 10000 times running Connection Worker is 149 millisecs using 2 threads: Worker 0 :Elapsed time for 10000 times running Connection Worker is 122 millisecs Worker 1 :Elapsed time for 10001 times running Connection Worker is 127 millisecs using 4 threads: Worker 0 :Elapsed time for 10000 times running Connection Worker is 127 millisecs Worker 1 :Elapsed time for 10002 times running Connection Worker is 129 millisecs Worker 2 :Elapsed time for 10001 times running Connection Worker is 138 millisecs Worker 3 :Elapsed time for 10003 times running Connection Worker is 140 millisecs using 8 threads. Worker 0 :Elapsed time for 10007 times running Connection Worker is 135 millisecs Worker 1 :Elapsed time for 10000 times running Connection Worker is 154 millisecs Worker 2 :Elapsed time for 10002 times running Connection Worker is 153 millisecs Worker 3 :Elapsed time for 10003 times running Connection Worker is 158 millisecs Worker 4 :Elapsed time for 10006 times running Connection Worker is 169 millisecs Worker 5 :Elapsed time for 10004 times running Connection Worker is 170 millisecs Worker 6 :Elapsed time for 10005 times running Connection Worker is 176 millisecs Worker 7 :Elapsed time for 10001 times running Connection Worker is 178 millisecs
Simple C++/CLI SerialPort ReadByte (at least, so I thought...)
So, I am working with C++/CLI in VisualStudio and an Arduino based board. My goal is to implement MODBUS via RS485. So the setup I have for development is as follows... Laptop connected Via FTDI USB-RS485 interface cable to Maxim MAX3485 chip which is connected to Arduino serial port "Serial1". I have been writing my MODBUS protocol in Visual Studio and testing it out by asking the Arduino to respond with the contents of 5 registers (a 5 byte array). Everything works except for some reason, return bytes are getting split in two when I check the result. I.E... I'm sending the following bytes from the Arduino: 0 A 0 14 0 1E 0 28 0 32 A is actually "0A", but the terminal window only displays it as "A". The software on the computer receives the bytes, and stores them in an array. I then display the bytes received on the screen as text. What I get is: 0 A 0 1 4 0 1 E 0 2 8 0 3 2 Which looks correct, except the space between the "1 & 4", "2 & 8" etc.. which is telling me that I have 14 bytes instead of the 10 bytes the I sent out. I'm displaying each byte on the screen separated by a space. I verified the bytes leaving are correctly formatted using a terminal window on a separate com port, so the problem must be in the reading of the bytes? My Arduino code: // Print to terminal window to verify bytes leaving Serial.print("Sending:- "); for (int x = 0; x < i_Index; x++) { Serial.print(DataTxRegister[x], HEX); Serial.print(" "); } Serial.println(" "); // CONFIGURE 485 CHIP TO TX MODE digitalWrite(CNTL_PIN, HIGH); delay(5); // TRANSMIT ALL DATA FROM TX REGISTER for (int x = 0; x < i_Index; x++) { Serial1.print(DataTxRegister[x], HEX); } i_Index = 0; delay(5); // CONFIGURE 485 CHIP BACK TO RX MODE digitalWrite(CNTL_PIN, LOW); Visual Studio code Read Bytes.... int8_t Byte; // DATA RECIEVED FROM ARDUINO / DEVICE USING MODBUS PROTOCOL if(sender == this->serialPort1){ Msg.Message_Length = 0; while (this->serialPort1->BytesToRead != 0) { Byte = this->serialPort1->ReadByte; if (Byte != -1) { Msg.Incoming_Bytes[Msg.Message_Length++] = (Byte); } } this->BeginInvoke(gcnew EventHandler(this, &Form1::DisplayMBRecieved)); } Display Bytes... this->textBox1->AppendText("\r\n"); this->textBox1->AppendText("Bytes Received: "); this->textBox1->AppendText(Convert::ToInt32(Msg.Message_Length).ToString("X8") + " :- "); for (unsigned int i = 0; i < Msg.Message_Length; i++) { this->textBox1->AppendText(Convert::ToString(Convert::ToChar(Msg.Incoming_Bytes[i]))); this->textBox1->AppendText(" "); } Msg.Message_Length = 0;
Sudden receive-buffer buildup on CentOS for C++ application
I have a somewhat strange problem when receiving UDP data on CentOS. When my application receives data everything is fine at first and all packets are received as expected, then all of a sudden the kernel receive buffer (net.core.rmem) starts to fill up for no apparent reason until it's full and packets are dropped. The strange part is that the buffer is more or less empty until all of a sudden when it starts to increase dramatically even though the sending party sends at the same rate as before. As if a resource I haven't accounted for is depleted, or the operating system changes priority of the thread dedicated for receive operations. Data is still received and read by receive(), but the buffer starts to fill too fast. Files are sent from the sending application to the receiving application. There is a unidirectional gateway between the sending and receiving application, so there is no possibility for congestion control (or TCP) what so ever. The problem only arises when I send a big file (around 3 GiB or more). Everything works fine when I send multiple small files, even if the sum of their size is much larger than 3 GiB. At the moment I'm unable to specify the problem further and I'm pretty stunned as to what could be wrong. This is the information about the systems configuration that I can imagine being relevant, but I've looked into memory leaks, disk usage and buffer sizes without being able to find something specific. Data is sent at a rate of 100 Mbit/s. MTU is 9000 on both the sending and receiving machine. net.core.rmem_max/net.core.rmem_default is set to 536870912 Bytes (huge). net.core.netdev_max_backlog is set to 65536 (huge). Each UDP packet sent is 8192 Bytes, excluding the UDP header. A temporary file created through tmpfile() is used to store the data for each file. The temporary file is closed as soon as the file is completed (hashsum is verified). CPU usage when receiving files is consistent at 100%. Memory usage when receiving files is consistent at 0.5%. receive() std::vector<uint8_t>* vector = new std::vector<uint8_t>(); while (signal == 0) { ret = _serverio->Receive(*vector); if (ret == -1 || ret == 0) { continue; } else { Produce(vector); vector = new std::vector<uint8_t>(); } } _serverio->Receive(std::vector& data) ssize_t n; data.resize(UDPMAXMSG); int res = m_fdwait.Wait(m_timeoutms); if(res < 1) { data.resize(0); return res; // timeout or interrupt } n = read(m_servfd, &(data[0]), data.size()); if(n < 0) { if(errno == EINTR) { data.resize(0); return -1; } else { throw socket_error(errno, "UDPServer::Receive"); } } data.resize(n); return n; Produce(std::vector* vector) _producerSemaphore.aquire(); _queue.lock(); _buffer.push_back(vector); _queue.unlock(); _consumerSemaphore.release(); Consume() bool aquired = false; while (!aquired) { if (_terminated) { // Consume should return NULL immediately if // receiver has been terminated. return NULL; } aquired = _consumerSemaphore.aquire_timeout(1); } std::vector<uint8_t>* vector = NULL; _queue.lock(); vector = _buffer.front(); _buffer.pop_front(); _queue.unlock(); _producerSemaphore.release(); return vector; recv_buffer.sh (for monitoring of the receive buffer) while true ; do _BUFFER_VALUE=$(printf "%d" "0x$(grep 2710 /proc/net/udp \ | awk '{print $5}' | sed 's/.*://')") _DELTA=$(expr $_BUFFER_VALUE - $_PRE_BUFFER) _PRE_BUFFER=$_BUFFER_VALUE echo "$_BUFFER_VALUE : $_DELTA" sleep 0.1 done recv_buffer.sh output buffer-size delta 0 0 0 0 ... 10792 10792 10792 0 0 -10792 10792 10792 0 -10792 0 0 0 0 0 0 // This type of pattern goes on for 2.5 GiB ... 0 0 0 0 0 0 0 0 971280 971280 // At this point the buffer starts to fill 1823848 852568 1931768 107920 2039688 107920 2179984 140296 2287904 107920 2406616 118712 2525328 118712 2644040 118712 2741168 97128 2881464 140296 3010968 129504 3140472 129504 ... 533567272 647520 536038640 2471368 536675368 636728 536880416 205048 // At this point packets are dropped 536869624 -10792 536880416 10792 536880416 0 536869624 -10792 536880416 10792 536869624 -10792 536880416 10792 536880416 0 536880416 0 536880416 0 536880416 0 536880416 0
Why does TTYUSB0 port settings change my stdout settings as well
I have an embedded Atmel ARM926 board that I created a usb serial ko to get data from an FTDI as USBtty0. This board also has a serial port DBGU which is used as the console terminal that normally runs at 230kb. When I config the USBtty0 port to the required 115kb, DBGU apparently changes to 115kb as well. if( m_fdELMdev = open(m_ELMdevice, O_RDWR | O_NOCTTY )< 0) {//error } else { // Configure the port tcgetattr(m_fdELMdev, &dev_settings); dev_settings.c_cflag |= B115200; cfmakeraw(&dev_settings); } Can someone please tell me what I might be doing wrong? This is snippet of my devices.tab /dev/tty c 640 0 0 4 0 0 1 4 /dev/tty c 640 0 0 5 0 - - - /dev/ttyGS c 640 0 0 252 0 - - - /dev/ttyS c 640 0 0 4 64 0 1 3 /dev/watchdog c 640 0 0 10 130 - - - /dev/zero c 640 0 0 1 5 - - - /dev/ttyACM0 c 640 0 0 166 0 - - - /dev/ttyUSB0 c 640 0 0 188 0 - - - Also, I occasionally see some 'Interrupted System Calls' from select. How do I need to handle these? Do I retry the select until I get some data? Then what if I never get any data? enter code here do { iret = select(m_fdELMdev + 1, &fdrefid, NULL, NULL, &porttime); switch(iret) { case READ_TIMEOUT: ierr = -1; break; case READ_ERROR: g_dbg->debug("CACS_Elm327::Select error:%s (%d)\n",strerror(errno), errno); ierr = -1; break; default: iret = read(m_fdELMdev, data, ilen); g_dbg->debug("CACS_Elm327::Readport_ELM:read %s %d\n", data, iret ); break; } }while((ierr == 0) && (iret<ilen) );