Read serial data without high CPU use - linux

I want to read messages sent from an Arduino via the FTDI (serial) interface in a simple C or C++ program under Linux. The Arduino sends a two character 'header', a command byte followed by a few bytes of data depending on the command.
My first attempt was to simply poll the data using open() and read() but doing so causes about 12% CPU use. This didn't seem to be the appropriate way of doing things.
Second I read up on libevent on implemented an event loop that fires an event when data is present on the file descriptor. My cpu usage was next to nothing but I couldn't read the entire message before another event was called. The events didn't fire when an entire message was received but as soon as any/some data was available on the file descriptor. Looking at it more it was obvious that this wouldn't work quite the way I wanted it. This is my event code: http://pastebin.com/b9W0jHjb
Third I implemented a buffered event with libevent. It seemed to work somewhat better but still split some of the messages up. My event code is: http://pastebin.com/PQNriUCN
Fourth I dumped libevent and tried out Boost's ASIO class. The example I was following was http://www.webalice.it/fede.tft/serial_port/serial_port.html. It seemed to work alright but the "event loop" was a "while(1) {}" which caused CPU usage to go up again. The loop just checks for error status while serial reading happens in a callback on a different thread. I added a usleep(1) to the while loop and it brought my CPU usage to 2% which is ok, but still seems heavy for such a light program.
Most of the examples of libevent and even the underlying epoll use TCP sockets which doesn't seem to behave quite the same as serial port data.
So my main question is: what is a good lightweight way to read messages from a serial port without heavy polling? (in linux, using C or C++)

The OP has probably long since solved this, but for the sake of anyone who gets here by google:
#include <sys/poll.h>
struct pollfd fds[1];
fds[0].fd = serial_fd;
fds[0].events = POLLIN ;
int pollrc = poll( fds, 1, 1000);
if (pollrc < 0)
{
perror("poll");
}
else if( pollrc > 0)
{
if( fds[0].revents & POLLIN )
{
char buff[1024];
ssize_t rc = read(serial_fd, buff, sizeof(buff) );
if (rc > 0)
{
/* You've got rc characters. do something with buff */
}
}
}
Make sure the serial port is opened in nonblocking mode as poll() can sometimes return when there are no characters waiting.

Related

How to tell another thread that one thread is within recv() call *now*

There is an embedded Linux system with an externally connected (ethernet) device which sends lots of UDP data, once it's started by a command.
At startup, I have one thread which is to continuously receive UDP data for the remainder of the program runtime.
As I see it, for reliability in principle, not just by accident, it must be ensured that the UDP reception loop must make its first call to recv() before the external data source is started, or the first packet or so might me lost, depending on scheduler whims. (this is all in a very local, purposefully simple network setup - packet loss is normally not an issue and not handled - speed is king)
Currently, right before calling that UDP reception code, I start a temporary thread which delays for some time, then enables the data source to send UDP data.
This is currently the way to "ensure" that the first UDP packet arrives when the reception thread is "armed", i.e. within a recv() call, the OS waiting for data.
Even if I, say, set a condition variable, right before the first call to recv() to tell the rest of the program "ok, you can enable the data source now, I'm ready" - it could, in theory, happen that there is some scheduling induced delay between that signal flagging and the actual call to recv (or/and for the internals of recv actually being ready).
Is there a more elegant / proper way to solve this, than using some "empirical delay time"?
Pseudo code for illustration:
// ******** main thread ********
thread delayed( [&]{ sleepMs(500); enableUdpDataSource(); } );
thread udpRecv( [&]{ udpRecvUntilTimeout() } );
delayed.join();
udpRecv.join();
return 0;
// ******** UDP thread ********
void udpRecvUntilTimeout()
{
udpInit(); // set up socket, buffer sizes etc
while (shouldRun)
{
// recv() needs to be "armed" *before* the data source is enabled.
// If I set a condition variable for another thread right here,
// there may be a scheduling intervention between it and the actual
// engaging of recv() - when the other thread happily enables the datasource.
int received = recv( sockFd, buf, maxlen, 0 );
timeoutWatchdogReset();
processReceivedData();
}
}
In an earlier version, I suggested that the call to bind is optional, but of course it is not. You have to call it in order to tell the kernel which UDP port to open.
After bind, the kernel will buffer incoming UDP packets and you can call recv if you're not interested in the client network details (otherwise, call recvfrom).
Something along these lines:
char buf[1500];
struct sockaddr_in addr;
int sd = socket(AF_INET, SOCK_DGRAM, 0);
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons((unsigned short) 1234); // UDP port
bind(sd, (struct sockaddr *)&addr, sizeof(addr));
// start data sending thread
sleep(1); // for testing
recv(sd, buf, 100, 0);
But there are no guarantees with UDP; you might still lose packets (eg. if the sender is overloading the receiver)
As you're using Linux, it might be possible to use FTRACE to determine whereabouts your receiving thread has got. The function tracing in this allows one (normally in post mortem debugging / analysis) to see the function calls made by a process. I'm pretty sure that this is exposed through some /sys or /proc file system, so it ought to be possible to monitor it live instead.
So if you had your temporary thread looking at the system calls of the receiving thread, it would be able to spot it entering the call to recv().
If FTRACE is not already built into your kernel, you'll need to recompile your kernel to include it. Could be handy - FTRACE + kernelshark is a nice way of debugging your application anyway.

Is read guaranteed to return as soon as data is available?

I want to implement a simple notification protocol using TCP sockets. The server will write a byte to a socket to notify the client, and the client reads from the socket, waiting until some data arrives, at which point it can return from the read call and perform some work.
while (1) {
/* Wait for any notifications */
char buf[32];
if (read(fd, buf, sizeof(buf)) <= 0) {
break;
}
/* Received notification */
do_work();
}
My question is, is read guaranteed to return as soon as any data is available to read, or is the kernel allowed to keep waiting until some condition is met (e.g. some minimum number of bytes received, not necessarily the count which I pass into read) before it returns from the read call? If the latter is true, is there a flag that will disable that behavior?
I am aware that I could use the O_NONBLOCK flag and call read in a loop, but the purpose of this is to use as little CPU time as possible.
There are multiple implicit questions here:
Is read guaranteed to return immediately or shortly after a relevant event?
No. The kernel is technically allowed to make you wait as long as it wants.
In practice, it'll return immediately (modulo rescheduling delays).
This is true for poll and O_NONBLOCK as well. Linux is not a realtime OS, and offers no hard timing guarantees, just its best effort.
Is read allowed to wait indefinitely for multiple bytes to become available?
No, this would cause deadlocks. read needs to be able to return with a single byte, even if there are no guarantees about when it will do so.
In practice, Linux makes the same effort for 1 byte as it does for 1,048,576.
Is sending a single byte on a socket a practical way of waking up a remote process as soon as possible?
Yes, your example is perfectly fine.

Emitting a poll/select event from a timer handler through a wait queue

I'm writing a Linux character driver for a custom lab hardware attached to a development board with a slow ARM SoC and got stuck trying to implement a suitable notification system from kernel space to user space.
Basically, I read data from the HW periodically (every 10 ms), process this data through some filters running in kernel space (this part is ok), and notify the user space when some conditions are met. My approach is make the user space daemon wait a notification from the driver with a poll() system call (natural, as I'm also monitoring a network socket there).
on driver initialization, I create the timer (with setup_timer) that will call the function responsible for reading the hardware, set the GPIOs used for that, and create a wait queue (with init_waitqueue_head) to signal the .poll handler in struct file_operations from the timer handler. This part seems ok.
There is a .unlocked_ioctl handler to set and get the conditions, but this part is working.
my .read method from struct file_operations just puts a single byte with the status to user space; It never blocks as there is always a valid one (including the 'W' for "waiting more data from the sensors").
Once the device is open, I enable the timer. Its handler function is called after 10 ms, reads data from the HW, runs through the filter, and sets the timer to run again (with mod_timer); If the filtered data match my conditions, it changes the status, sets a flag poll_evt_waiting to 1 and calls wake_up_interruptible on the queue shared with the .pollmethod from struct file_operations. This method is just:
static unsigned int firflt_file_poll(struct file *filp, poll_table *wait)
{
unsigned int mask = 0;
poll_wait(filp, &firflt_queue, wait);
if (poll_evt_waiting != 0) {
mask = POLLIN | POLLRDNORM;
poll_evt_waiting = 0;
}
return mask;
}
Problem is: the poll() in my user space daemon never receives a notification from the driver! Is there any obvious error in my approach? Specially regarding the wait queue? I never implemented the "other side" of a poll() before, and got all information regarding this from "Linux Device Drivers", 2005 ed.
If a read the devices file descriptor continuosly, I can see the status changes from user space, but this puts my daemon in a busy loop, which is too much for the slow CPU. I really need to keep it waiting in the poll until there is something new.
Also, the only operations I do with the wait queue is initializing it with init_waitqueue_head, waking it up with poll_evt_waiting when status changes, and passing it to poll_wait in my .poll handler. Is this approach sound?
Call wake_up_interruptible() on the polled queue just force the .poll method to be called again. User space process receive notification only when .poll method returns mask which have polled bits set.
Check that your .poll method actually returns non-zero mask.

printf in system call returns malformed output

I'm logging system calls in OS X using a kext, like so:
int hook_read(struct proc *p, struct read_args *u, user_ssize_t *r) {
/* get som params here... */
printf("[IDEN] SYS_read called, %s, %d, %d, %d.\n", params);
return read(p, u, r);
}
This logs to system.log. The issue now is that if the printf load is high (many system calls are called), the output in system.log is often malformed:
ID]SYS_readEN] callparam, 123, ed 123, 123 for example. The string is scrambled. If I use kprintf, which prints to a serial port, malformed logs never occur.
Any idea's what's causing this behaviour are much appreciated!
printf/IOLog uses a buffer for sending messages to userspace, where they're then logged to the system log. If you output a lot of messages, this buffer can get full before the logging daemon has a chance to clear it, and your messages will be truncated and start running into each other. (printf/IOLog will return as soon as the message has been submitted to the buffer, and will not wait for the daemon to receive it.)
Additionally, I'm not sure if kernel printf/IOLog is in any way thread-safe, so it might also be the case that calling it from multiple threads simultaneously causes race conditions. I'd have to check the source to be sure.
kprintf is fully synchronous and will block until your message has been transmitted on the serial port or submitted via firewire. It's also thread-safe. In the firewire case, the kprintf output is also buffered, so if you output a lot of messages, this can fill up too and cause truncation. The fwkpfv command lets you specify the buffer size using the --buffer argument though, so you can counteract that. The downside of kprintf being synchronous is that it can slow the system down considerably with a high volume of messages.

Understanding the lifeline of linux pipe for ipc communication

I want to understand the lifetime of a pipe? http://linux.die.net/man/2/pipe
Does the data in the pipe stay alive if either the sender or receiver dies/exits?
Can the pipe be created if the receiver is not present? (i.e. has not been forked off yet)?
I need to send data from sender to the receiver. However, the receiver may not have been forked off yet, and may be active about (1~2 seconds after the sender). They share the parent process, but the receiver may be forked off at some point much after the sender or vice versa.
Also it is possible that the sender can finish processing and exit at any time.
I'm trying to see if using pipe's instead of a shared memory queue would work for me.
The pipe MUST be created before the fork. After the fork, each process uses either the read or the write end. It's best to close the not-used end of the pipe immediately after the fork.
If the writing process exits, the reader can read all the remaining data in the pipe, but the subsequent read system call in it returns with 0 bytes read, that's how you know it's over. If the writing process is still keeping the pipe open but does not write anything into it, read blocks until bytes become available.
If the writing process has written a lot of data into the pipe and exits, the data are still available for the reader.
If the reading process exits, the writing process is killed by a SIGPIPE signal. It has the option of handling the signal in different ways, but it's killed by default.
So the pipe may survive the writer, but not the reader. Proof of concept (cső is Hungarian for pipe):
#include <unistd.h>
int main(void)
{
int cso[2];
pipe(cso);
if (fork() == 0) {
close(cso[0]);
write(cso[1], "cso\n", 4);
return 0;
}
close(cso[1]);
sleep(2);
if (fork() == 0) {
char line[4];
read(cso[0], line, 4);
write(1, line, 4);
return 0;
}
close(cso[0]);
return 0;
}

Resources