是高手就进来帮帮忙!ARM9(2440)多线程串口编程,运行错误:__gnu_cxx::__concurrence_broadcast_error
在ARM9运行多线程串口程序是抛出这样的异常:terminate called after throwing an instance of '__gnu_cxx::__concurrence_broadcast_error'
what(): __gnu_cxx::__concurrence_broadcast_error
只要以调用OpenPort就报错。
该源代码在Fedora9上编译、运行都没问题,程序中用了网上找到的一个多线程串口类。
编译器用的是gcc 4.4.3
Google、百度边了也没找到解决方法,各位有什么解决方法或思路不?
希望大家能帮帮忙,多谢!!!!!!!!
//主程序#include "CSerial.h"#include <string>using namespace std;int main(int argc, char* argv[]){ CSerial::CSerial serial; serial.OpenPort("/dev/ttySAC0", 115200, 8, 1, 'N');//报错!! while(1); return 0;}/*自定义串口类* CSerial.h** Created on: 2010-7-20* Author: yzm*/#ifndef CSERIAL_H_#define CSERIAL_H_#include <pthread.h>#include <time.h>#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h> /*文件控制定义*/#include <termios.h> /*PPSIX 终端控制定义*/#include <errno.h> /*错误号定义*/#include <string.h>#include <string>#include "CCriticalSection.h"using namespace std;#define BUFFER_LENGTH 1024namespace CSerial {class CSerial{private: string m_PortName; int m_baudrate; int m_databits; int m_stopbits; char m_parity; //通讯线程标识符ID pthread_t m_thread; CCriticalSection mutex; // 串口数据接收线程 static void* ReceiveThreadFunc( void* lparam );public: CSerial(); virtual ~CSerial(); // 已打开的串口文件描述符 int m_fd; int m_DatLen; unsigned char DatBuf[BUFFER_LENGTH]; int m_ExitThreadFlag; // 按照指定的串口参数打开串口,并创建串口接收线程 int OpenPort( string PortName, int baudrate, int databits, int stopbits, char parity ); // 关闭串口并释放相关资源 int ClosePort( ); // 向串口写数据 int WritePort( unsigned char* Buf, int len ); // 接收串口数据处理函数 virtual int PackagePro( unsigned char* Buf, int len );private: void set_speed(int fd, int speed); int set_Parity(int fd,int databits,int stopbits,int parity);};}#endif /* CSERIAL_H_ *//** CSerial.cpp** Created on: 2010-7-20* Author: yzm*/#include "CSerial.h"#include <sys/select.h>#include <sys/time.h>#include <stdlib.h>#include <unistd.h> /*Unix 标准函数定义*/namespace CSerial {int speed_arr[] = {B115200,B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400, B19200, B9600, B4800, B2400, B1200, B300, };int name_arr[] = {115200,38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200, 9600, 4800, 2400, 1200, 300, };string BYTE2HEX(unsigned char* buffer,int nSize){ char buf[1024]; memset(buf,0,1024); int len = 0; for(int i = 0;i < nSize;i++) { int tmp = sprintf(buf + len,"%02x ",buffer); len += tmp; } string str(buf); return str;}CSerial::CSerial(){ m_ExitThreadFlag = false; m_PortName = "/dev/ttyS0"; m_baudrate = 2400; m_databits = 8; m_stopbits = 1; m_parity = 'e';}CSerial::~CSerial(){ ClosePort( );}int CSerial::OpenPort(string PortName, int baudrate, int databits, int stopbits, char parity) { /*以读写方式打开串口*/ m_fd = open(PortName.data(), O_RDWR); if (-1 == m_fd) { /* 不能打开串口一*/ perror(" 提示错误!"); return -1; } else { m_PortName = PortName; m_baudrate = baudrate; m_databits = databits; m_stopbits = stopbits; m_parity = parity; //设置参数 set_speed(m_fd, baudrate); set_Parity(m_fd, databits, stopbits, parity); pthread_create(&m_thread,NULL,CSerial::CSerial::ReceiveThreadFunc,this); return 1; }}int CSerial::ClosePort( ){ m_ExitThreadFlag = true; close(m_fd); pthread_join(m_thread,NULL); return 1;}int CSerial::PackagePro( unsigned char* Buf, int len ){ string str = BYTE2HEX(Buf,len); printf("%s\r\n",str.data()); WritePort(Buf,len); return 1;}void* CSerial::ReceiveThreadFunc(void* lparam) { CSerial *pSer = (CSerial*) lparam; fd_set fdRead; int ret; struct timeval aTime; while (1) { //收到退出事件,结束线程 //printf("Thread...\r\n"); if (pSer->m_ExitThreadFlag) { break; } FD_ZERO(&fdRead); FD_SET(pSer->m_fd,&fdRead); aTime.tv_sec = 2; aTime.tv_usec = 100; ret = select(pSer->m_fd + 1, &fdRead, NULL, NULL, &aTime); if (ret < 0) { //关闭串口 pSer->ClosePort(); break; } if (ret > 0) { //判断是否读事件 if (FD_ISSET(pSer->m_fd,&fdRead)) { //data available, so get it! pSer->m_DatLen = read(pSer->m_fd, pSer->DatBuf, BUFFER_LENGTH); // 对接收的数据进行处理,这里为简单的数据回发 if (pSer->m_DatLen > 0) { pSer->PackagePro(pSer->DatBuf, pSer->m_DatLen); } // 处理完毕 } } } printf("ReceiveThreadFunc finished\n"); pthread_exit(NULL); return 0;}/***@brief 设置串口通信速率*@param fd 类型 int 打开串口的文件句柄*@param speed 类型 int 串口速度*@return void*/void CSerial::set_speed(int fd, int speed) { unsigned int i; int status; struct termios Opt; tcgetattr(fd, &Opt); for (i = 0; i < sizeof(speed_arr) / sizeof(int); i++) { if (speed == name_arr) { tcflush(fd, TCIOFLUSH); cfsetispeed(&Opt, speed_arr); cfsetospeed(&Opt, speed_arr); status = tcsetattr(fd, TCSANOW, &Opt); if (status != 0) { perror("tcsetattr fd1"); return; } tcflush(fd, TCIOFLUSH); } }}/***@brief 设置串口数据位,停止位和效验位*@param fd 类型 int 打开的串口文件句柄*@param databits 类型 int 数据位 取值 为 7 或者8*@param stopbits 类型 int 停止位 取值为 1 或者2*@param parity 类型 int 效验类型 取值为N,E,O,,S*/int CSerial::set_Parity(int fd, int databits, int stopbits, int parity) { struct termios options; if (tcgetattr(fd, &options) != 0) { perror("SetupSerial 1"); return (false); } options.c_cflag &= ~CSIZE; switch (databits) /*设置数据位数*/ { case 7: options.c_cflag |= CS7; break; case 8: options.c_cflag |= CS8; break; default: fprintf(stderr, "Unsupported data size\n"); return (false); } switch (parity) { case 'n': case 'N': options.c_cflag &= ~PARENB; /* Clear parity enable */ options.c_iflag &= ~INPCK; /* Enable parity checking */ break; case 'o': case 'O': options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/ options.c_iflag |= INPCK; /* Disnable parity checking */ break; case 'e': case 'E': options.c_cflag |= PARENB; /* Enable parity */ options.c_cflag &= ~PARODD; /* 转换为偶效验*/ options.c_iflag |= INPCK; /* Disnable parity checking */ break; case 'S': case 's': /*as no parity*/ options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; break; default: fprintf(stderr, "Unsupported parity\n"); return (false); } /* 设置停止位*/ switch (stopbits) { case 1: options.c_cflag &= ~CSTOPB; break; case 2: options.c_cflag |= CSTOPB; break; default: fprintf(stderr, "Unsupported stop bits\n"); return (false); } options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG | IEXTEN); /*Input*/ options.c_iflag &= ~(IXON | IXOFF | IXANY);//关流控 options.c_iflag &= ~(INLCR | IGNCR | ICRNL | IUCLC | IGNBRK|BRKINT|PARMRK|ISTRIP); options.c_oflag &= ~(ONLCR | OCRNL | ONLRET | ONOCR | OLCUC | OFILL | CRTSCTS); options.c_oflag &= ~OPOST; /*Output*/ /* Set input parity option */ if (parity != 'n') options.c_iflag |= INPCK; tcflush(fd, TCIFLUSH); options.c_cc[VTIME] = 50; /* 设置超时15 seconds*/ options.c_cc[VMIN] = 0; /* Update the options and do it NOW */ if (tcsetattr(fd, TCSANOW, &options) != 0) { perror("SetupSerial 3"); return (false); } return (true);}int CSerial::WritePort( unsigned char* Buf, int len ){ mutex.Lock(); int ToWrite = len; int hasWrite = 0; int wPos = 0; while(ToWrite > 0){ hasWrite = write(m_fd, Buf + wPos, ToWrite); if(hasWrite <= 0)break; ToWrite -= hasWrite; wPos += hasWrite; } mutex.Unlock(); return len - ToWrite;}}
#ifndef __CCRITICALSECTION_H#define __CCRITICALSECTION_H#include <pthread.h>class CCriticalSection{private: pthread_mutex_t mutex;public: CCriticalSection(); ~CCriticalSection();public: void Lock(); void Unlock();};#endif#include "CCriticalSection.h"CCriticalSection::CCriticalSection(){ pthread_mutex_init(&mutex,NULL); }CCriticalSection::~CCriticalSection(){ pthread_mutex_destroy(&mutex); }void CCriticalSection::Lock(){ pthread_mutex_lock(&mutex);}void CCriticalSection::Unlock(){ pthread_mutex_unlock(&mutex);}<iostream><string>using namespace std;
[解决办法]
第一个可能原因是pthread的问题
看看你用的arm工具链的pthread库是否正确复制到目标机里了
如果不是系统路径,链接时使用-Wl,-rpath=... -Wl,--dyanmic-linker=...来确定路径
第二个可能原因是有的嵌入式系统不支持异常,这也是1L的说法
如果你确定没有在代码里使用异常,那么尝试在编译开关里加入-fno-exceptions。