我使用的是serial port,在与此通信时,我必须使用tcsetattr()和TCSDRAIN模式更改配置。
TCSADRAIN
The change should take place after all output written to fd has been read by the master pseudoterminal. Use this value when changing terminal attributes that affect output.当使用tcsetattr()调用TCSDRAIN时,如果缓冲区中仍然保留输出数据,则Linux似乎被阻塞,并在中断时间后再次检查缓冲区以更改配置。
我对此进行了如下测试
1. write data to serial
2. change configuration using tcsetattr()
3. there is a remaining data in output buffer
4. the process blocked during regular interval, for example 20ms
5. wake up.
1. write data to serial
2. take sleep() manually for 5ms, it means give enough time to clear output to Linux
3. there is no remaining data
4. change configuration using tcsetattr()
5. there is no block
对我来说,中断时间太长,做不到我想做的事。
如何更改这个中断计时器间隔?( Ubuntu和raspberrypi)
发布于 2015-03-27 18:07:12
我不认为termios结构的.cc[VTIME]字段会影响刷新超时,如果这正是您所要求的。据我所知,它只影响read()行为。
但是,在放弃之前,有几种方法可以控制内核尝试耗尽/刷新的时间间隔。
一种选择是使用fcntl(fd, F_SETFL, O_NONBLOCK) (暂时)将描述符设置为非阻塞状态,并使用clock_gettime(CLOCK_MONOTONIC, &now)和nanosleep()在适当的时间间隔内多次重试tcsetattr(fd, TCSADRAIN, &attrs),直到成功为止。然后使用fcntl(fd, F_SETFL, 0)将描述符恢复到正常模式。如果tcsetattr()调用在errno == EWOULDBLOCK || errno == EAGAIN中失败,请使用tcsetattr(fd, TCSANOW, &attrs)丢弃所有未读/未发送数据。
注意,我还没有在RPi上测试过上面的内容!它可能无法在某些特定的体系结构/串口驱动程序上工作,因为可以将刷新/排水间隔硬编码到驱动程序中,而忽略描述符处于非阻塞模式的事实。但是,这将是一个bug,并且可以用内核修补程序来修复。(换句话说,这应该是可行的,但是一些串口驱动程序可能很糟糕,忽略了上面的非阻塞特性,并且会一直阻塞到某个未指定的时间间隔。)
另一种选择是使用计时器来发出信号。如果您安装了一个函数来处理不带SA_RESTART标志的信号,则信号的传递将中断阻塞的SA_RESTART调用。(如果进程使用多个线程,则信号应该在所有其他线程中被阻塞,否则内核只会选择进程的一个线程来传递信号。如果不是阻塞调用中的线程,则阻塞调用不会被中断。)
因为信号是中断大多数syscall和库函数的一种非常可靠的方法(参见man 7信号中信号处理程序中断系统调用和库函数一节-- termios函数等效于Linux中的ioctl()调用),因此我个人倾向于让一个单独的线程除了维护这些超时之外什么也不做。这样的线程非常轻量级,除非经过超时或添加超时,否则不会占用CPU时间。我还可以有多个并发超时,有一个简单的接口来检查、取消和添加超时,这使得设计应用程序的其余部分变得更加健壮和高效。
https://stackoverflow.com/questions/29293227
复制相似问题