当前位置: 技术问答>linux和unix
关于linux下运行线程的问题,请高手帮忙!
来源: 互联网 发布时间:2015-09-23
本文导语: 两个线程同时运行时存在的问题: 线程1:画正弦波(原意是把串口接收到的数据画出波形,现画个正弦波用来测试) 线程2:打开串口,初始化串口(115200, 8, 1, "N"),接收串口数据(9600bytes/sec) 如果单个线程运行时,都...
两个线程同时运行时存在的问题:
线程1:画正弦波(原意是把串口接收到的数据画出波形,现画个正弦波用来测试)
线程2:打开串口,初始化串口(115200, 8, 1, "N"),接收串口数据(9600bytes/sec)
如果单个线程运行时,都运行正常;但是如果同时打开两个线程,则画波形速度有快慢之分,串口数据异常(写文件后检查数据发现偶尔要
丢掉几个字节的数据,只运行串口监控线程又正确)。现列出简短代码,让大家指点一下!
如果有高人有心帮忙,我可以把原代码发过来!
//////////////////////////////////////////////////
//画波形的关键代码
void DrawSinLine(int sig)
{
在兼容DC上画波形并bitblt,颜色深度为8位
}
void Timer(int sec, long usec)
{
struct timeval tvSelect;
tvSelect.tv_sec = sec;
tvSelect.tv_usec = usec;
select(FD_SETSIZE, NULL, NULL, NULL, &tvSelect);
}
void ThreadWave(void* data)
{
//该循环应该是50ms执行一次,本来是调用Timer(0,50*1000),但是考虑到让循环能空出资源,所以延时了一下
while(1)
{
usleep(20000);
Timer(0, 30*1000);
DrawSinLine(0);
}
return;
}
//////////////////////////////////////////////////
//////////////////////////////////////////////////
//串口接收的代码
int OpenComAndReceive()
{
OpenComPort (0, 115200, 8, "1", 'N'));
ReceiveChar();
CloseComPort ();
exit (0);
}
INT32 ReceiveChar()
{
sigaction_io.sa_handler = signal_handler_IO;
sigemptyset (&(sigaction_io.sa_mask));
sigaction_io.sa_flags = 0;
sigaction_io.sa_restorer = NULL;
tv_timeout.tv_sec = TIMEOUT_SEC (CHAR_MAX, GetBaudrate ());
tv_timeout.tv_usec = TIMEOUT_USEC;
//tv_timeout.tv_sec = 0;
//tv_timeout.tv_usec = 10 * 1000;
while (1) {
usleep(1000);
SetPortSig ();
} /* end of while (1) */
fflush (stdout);
fflush (stderr);
close (fd);
return (0);
}
int SetPortSig ()
{
sigaction (SIGIO, &sigaction_io, NULL);
/* allow the process to receive SIGIO */
if (-1 == fcntl (fd, F_SETFL, O_ASYNC))
return (-1);
if (-1 == fcntl (fd, F_SETOWN, getpid ()))
return (-1);
return (0);
}
static void signal_handler_IO (int status)
{
char recvbuf[CHAR_MAX];
int iReadCount = 0;
INT32 retval = 0;
FD_ZERO (&fs_read);
FD_SET (fd, &fs_read);
retval = select (fd + 1, &fs_read, NULL, NULL, &tv_timeout);
if (retval)
{
iReadCount = read (fd, recvbuf, sizeof(recvbuf));
}
else
return;
static int ii = 0;
if (ii > 1000 * 1024)
{
printf("nFile Close");
close (iFile);
return;
}
else
{
ii += iReadCount;
lseek(iFile, 0, SEEK_END);
write (iFile, recvbuf, iReadCount);
}/**/
}
//////////////////////////////////////////////////
int MiniGUIMain (int args, const char* arg[])
{
....
pthread_t th1;
int ret;
struct sched_param scheduling_value;
scheduling_value.sched_priority = 1;
ret = pthread_create(&th1, NULL, &ThreadWave, NULL);
pthread_setschedparam(th1, SCHED_RR, &scheduling_value);
pthread_t th_com;
scheduling_value.sched_priority = 20;
ret = pthread_create(&th_com, NULL, &OpenComAndReceive, NULL);
pthread_setschedparam(th_com, SCHED_RR, &scheduling_value);
....
}
线程1:画正弦波(原意是把串口接收到的数据画出波形,现画个正弦波用来测试)
线程2:打开串口,初始化串口(115200, 8, 1, "N"),接收串口数据(9600bytes/sec)
如果单个线程运行时,都运行正常;但是如果同时打开两个线程,则画波形速度有快慢之分,串口数据异常(写文件后检查数据发现偶尔要
丢掉几个字节的数据,只运行串口监控线程又正确)。现列出简短代码,让大家指点一下!
如果有高人有心帮忙,我可以把原代码发过来!
//////////////////////////////////////////////////
//画波形的关键代码
void DrawSinLine(int sig)
{
在兼容DC上画波形并bitblt,颜色深度为8位
}
void Timer(int sec, long usec)
{
struct timeval tvSelect;
tvSelect.tv_sec = sec;
tvSelect.tv_usec = usec;
select(FD_SETSIZE, NULL, NULL, NULL, &tvSelect);
}
void ThreadWave(void* data)
{
//该循环应该是50ms执行一次,本来是调用Timer(0,50*1000),但是考虑到让循环能空出资源,所以延时了一下
while(1)
{
usleep(20000);
Timer(0, 30*1000);
DrawSinLine(0);
}
return;
}
//////////////////////////////////////////////////
//////////////////////////////////////////////////
//串口接收的代码
int OpenComAndReceive()
{
OpenComPort (0, 115200, 8, "1", 'N'));
ReceiveChar();
CloseComPort ();
exit (0);
}
INT32 ReceiveChar()
{
sigaction_io.sa_handler = signal_handler_IO;
sigemptyset (&(sigaction_io.sa_mask));
sigaction_io.sa_flags = 0;
sigaction_io.sa_restorer = NULL;
tv_timeout.tv_sec = TIMEOUT_SEC (CHAR_MAX, GetBaudrate ());
tv_timeout.tv_usec = TIMEOUT_USEC;
//tv_timeout.tv_sec = 0;
//tv_timeout.tv_usec = 10 * 1000;
while (1) {
usleep(1000);
SetPortSig ();
} /* end of while (1) */
fflush (stdout);
fflush (stderr);
close (fd);
return (0);
}
int SetPortSig ()
{
sigaction (SIGIO, &sigaction_io, NULL);
/* allow the process to receive SIGIO */
if (-1 == fcntl (fd, F_SETFL, O_ASYNC))
return (-1);
if (-1 == fcntl (fd, F_SETOWN, getpid ()))
return (-1);
return (0);
}
static void signal_handler_IO (int status)
{
char recvbuf[CHAR_MAX];
int iReadCount = 0;
INT32 retval = 0;
FD_ZERO (&fs_read);
FD_SET (fd, &fs_read);
retval = select (fd + 1, &fs_read, NULL, NULL, &tv_timeout);
if (retval)
{
iReadCount = read (fd, recvbuf, sizeof(recvbuf));
}
else
return;
static int ii = 0;
if (ii > 1000 * 1024)
{
printf("nFile Close");
close (iFile);
return;
}
else
{
ii += iReadCount;
lseek(iFile, 0, SEEK_END);
write (iFile, recvbuf, iReadCount);
}/**/
}
//////////////////////////////////////////////////
int MiniGUIMain (int args, const char* arg[])
{
....
pthread_t th1;
int ret;
struct sched_param scheduling_value;
scheduling_value.sched_priority = 1;
ret = pthread_create(&th1, NULL, &ThreadWave, NULL);
pthread_setschedparam(th1, SCHED_RR, &scheduling_value);
pthread_t th_com;
scheduling_value.sched_priority = 20;
ret = pthread_create(&th_com, NULL, &OpenComAndReceive, NULL);
pthread_setschedparam(th_com, SCHED_RR, &scheduling_value);
....
}
|
你用的什么系统,有些linux或unix的线程是靠线程库支持的,内核不支持,即所谓的伪线程,这类线程在执行一般的运算没问题,但涉及到IO操作时会出现异常。
|
我觉得问题可能出在:
线程1和线程2存在共享内存段
如1画图所用数据buffer和2串口接受数据buffer相同
那么可能会出现串口数据接收错误或正弦波形不连续等错误
解决的方法是设置互斥量
在一个线程中对共享数据进行操作时
不允许另一个线程操作该数据
线程1和线程2存在共享内存段
如1画图所用数据buffer和2串口接受数据buffer相同
那么可能会出现串口数据接收错误或正弦波形不连续等错误
解决的方法是设置互斥量
在一个线程中对共享数据进行操作时
不允许另一个线程操作该数据
|
还有select (fd + 1, &fs_read, NULL, NULL, &tv_timeout)
使用定时阻塞方式
换成非阻塞方式看看
使用定时阻塞方式
换成非阻塞方式看看
|
gz
|
不知道跟进程的优先级有没有关系
你把两个进程的优先级设成相等看看
你把两个进程的优先级设成相等看看