我正在编写一个条形码阅读器的应用程序,我有几种方法可以同步执行。作为初始点,我将同时从设备读取数据。以下是我的情景。
环境 操作系统:CENTOS 6.3(LINUX) 提升:1.41
为了数据读取目的,我有2种方法,我有1种方法将命令发送到解码器。我正在尝试使用来自互联网的boost :: thread示例,但我仍然无法理解这个场景。以下是我的申请中的示例代码。在这种情况下,请告诉我线程管理。
我在下面使用OOP方法是DeviceRS232.cpp类
中的方法// Open and set attributes for serial port
int DeviceRS232::openSerialPort()
{
int fd, baudr, status, portStatus;
setDefaultAttributes();
switch(getBaudRate())
{
case 50 : baudr = B50;
break;
case 75 : baudr = B75;
break;
case 110 : baudr = B110;
break;
case 134 : baudr = B134;
break;
case 150 : baudr = B150;
break;
case 200 : baudr = B200;
break;
case 300 : baudr = B300;
break;
case 600 : baudr = B600;
break;
case 1200 : baudr = B1200;
break;
case 1800 : baudr = B1800;
break;
case 2400 : baudr = B2400;
break;
case 4800 : baudr = B4800;
break;
case 9600 : baudr = B9600;
break;
case 19200 : baudr = B19200;
break;
case 38400 : baudr = B38400;
break;
case 57600 : baudr = B57600;
break;
case 115200 : baudr = B115200;
break;
case 230400 : baudr = B230400;
break;
case 460800 : baudr = B460800;
break;
case 500000 : baudr = B500000;
break;
case 576000 : baudr = B576000;
break;
case 921600 : baudr = B921600;
break;
case 1000000 : baudr = B1000000;
break;
default : printf("invalid baudrate\n");
return(1);
break;
}
// Open serial port
fd = open(getSerialPort().c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
if(fd == -1)
{
printf("Unable to open serial port...\n");
perror(getSerialPort().c_str());
return 1;
}
fdRS232 = fd;
fcntl(fdRS232, F_SETFL, FNDELAY);
status = tcgetattr(fdRS232, &oldSerialPortSetting);
if(status == -1)
{
close(fdRS232);
printf("Unable to get serial port attributes...\n");
return 1;
}
memset(&newSerialPortSetting, 0, sizeof(newSerialPortSetting));
newSerialPortSetting.c_cflag = baudr | CS8 | CLOCAL | CREAD | CRTSCTS; // | CRTSCTS
newSerialPortSetting.c_iflag = IGNPAR;
newSerialPortSetting.c_oflag = 0;
newSerialPortSetting.c_lflag = 0;
newSerialPortSetting.c_cc[VMIN] = 0;
newSerialPortSetting.c_cc[VTIME] = 0;
ChangeCTS(fdRS232, 0);
ChangeRTS(fdRS232, 0);
return 0;
}
// send data to the decoder
int DeviceRS232::sendDataBuffer(const unsigned char *dataBuffer, size_t bufferSize)
{
int sentSize;
ChangeRTS(fdRS232, 1);
ChangeCTS(fdRS232, 1);
while(true)
{
sentSize = write(fdRS232, dataBuffer, bufferSize);
if(sentSize > 0)
break;
}
hasCommandSent = true;
sleep(1);
return sentSize;
}
// Receive response from the decoder
int DeviceRS232::receiveDataBuffer(unsigned char *dataBuffer, size_t bufferSize)
{
unsigned char recvBuffer[251];
unsigned char *ptrChar;
int nBytes, portStatus;
int inputBufSize = 0;
ChangeCTS(fdRS232, 0);
ChangeRTS(fdRS232, 0);
while(inputBufSize <= 0)
{
ioctl(fdRS232, FIONREAD, &inputBufSize);
usleep(1);
}
//TEST PURPOSES
//sleep(1);
if(inputBufSize > 0)
{
memset(recvBuffer, 0x00, sizeof(recvBuffer));
nBytes = read(fdRS232, recvBuffer, 251);
if(nBytes < 0)
{
printf("Unable to receive data...\n");
perror("/dev/ttyS0");
}
std::cout << "RECV Length: " << nBytes << std::endl;
for(int i=0; i<nBytes; i++)
{
std::cout << "recvBuffer[" << (int)i << "]: ";
printf("%x\n", recvBuffer[i]);
}
std::cout << "-----------------------------------" << std::endl;
//ChangeRTS(fdRS232, 1);
//sleep(1);
}
strcpy((char *)dataBuffer, (char *)recvBuffer);
inputBufSize = 0;
return nBytes;
}
// Receive decoded data from decoder.
int DeviceRS232::receiveDecodedData(unsigned char *dataBuffer, size_t bufferSize)
{
unsigned char recvBuffer[251];
unsigned char *ptrChar;
int nBytes, portStatus;
int inputBufSize = 0;
ChangeCTS(fdRS232, 0);
ChangeRTS(fdRS232, 0);
while(inputBufSize <= 0)
{
ioctl(fdRS232, FIONREAD, &inputBufSize);
usleep(1);
}
// TEST PURPOSES
//sleep(1);
if(inputBufSize > 0)
{
int decodePacketLen;
//unsigned char
memset(recvBuffer, 0x00, sizeof(recvBuffer));
nBytes = 0;
while(nBytes < ((int)recvBuffer[0] + 2))
{
int index = 0;
if(nBytes != 0)
index = nBytes - 1;
nBytes += read(fdRS232, &recvBuffer[index], 251);
if(nBytes == ((int)recvBuffer[0] + 2))
break;
}
std::cout << "RECV Length: " << (int)recvBuffer[0] << std::endl;
for(int i=0; i<nBytes; i++)
{
std::cout << "recvBuffer[" << (int)i << "]: ";
printf("%x\n", recvBuffer[i]);
}
std::cout << "-----------------------------------" << std::endl;
//ChangeRTS(fdRS232, 1);
//ChangeCTS(fdRS232, 1);
//sleep(1);
}
//strcpy((char *)dataBuffer, (char *)recvBuffer);
memcpy((char *)dataBuffer, recvBuffer, sizeof(recvBuffer)/sizeof(recvBuffer[0]));
inputBufSize = 0;
return nBytes;
}
// Method I am going to use for concurrent reading
void DeviceRS232::startReadTread()
{
boost::thread *dataReader1, *dataReader2;
dataReader1 = new boost::thread(boost::bind(&DeviceRS232::decodedDataReadThread, this));
dataReader2 = new boost::thread(boost::bind(&DeviceRS232::commandResponseReadThread, this));
dataReader2->join();
}
// Finally I am hoping to create and call to thread handling method from main method.
int main()
{
DeviceRS232 dev_rs232;
dev_rs232.setDefaultAttributes();
dev_rs232.openSerialPort();
dev_rs232.startReadTread();
return 0;
}
我可以上传完整的程序以供进一步参考。
答案 0 :(得分:2)
通过使用Boost Asio的串行通信选项,您可以更轻松地实现John Zwinck所提到的。
这有使您的代码可移植的神奇好处
串行端口可在所有POSIX平台上使用。对于Windows,串行端口仅在使用I / O完成端口后端的编译时可用(这是默认设置)。程序可以测试宏BOOST_ASIO_HAS_SERIAL_PORT以确定它们是否受支持。
答案 1 :(得分:0)
您应该使用基于事件的解决方案,如select(),epoll(),WaitForMultipleEvents等,而不是在单独的线程中旋转等待读取数据。这样您就可以避免浪费CPU内核进行读取,并且避免使用互斥体,并在数据可供读取时准确唤醒。