2011-08-12 26 views
4

我想通過Linux下簡單的C或C++程序中的FTDI(串行)接口讀取Arduino發送的消息。 Arduino根據命令發送一個雙字符「標題」,一個命令字節,隨後是幾個字節的數據。讀取沒有CPU使用率高的串行數據

我的第一次嘗試是使用open()和read()來輪詢數據,但這樣做會導致大約12%的CPU使用率。這似乎不是做事的合適方式。

第二我讀了libevent關於實現了一個事件循環,當數據出現在文件描述符上時觸發一個事件。我的CPU使用率幾乎沒有,但在另一個事件被調用之前我無法讀取整個消息。當收到整個消息時,事件並不會觸發,只要文件描述符中有任何/某些數據可用。更多地看它,很明顯,這不會像我想要的那樣工作。這是我的事件代碼:http://pastebin.com/b9W0jHjb

第三我用libevent實現了一個緩衝事件。它似乎有點更好,但仍然分裂了一些消息。我的活動代碼是:http://pastebin.com/PQNriUCN

第四我傾倒了libevent並試用了Boost的ASIO課。我所遵循的例子是http://www.webalice.it/fede.tft/serial_port/serial_port.html。它似乎可以正常工作,但「事件循環」是一個「while(1){}」,導致CPU使用率再次上升。循環只是檢查錯誤狀態,而串行讀取發生在不同線程的回調中。我在while循環中添加了一個usleep(1),它將我的CPU使用率提高到了2%,這沒問題,但對於這樣一個輕量級程序來說仍然很重。

libevent甚至是底層epoll的大部分例子都使用TCP套接字,這些套接字的行爲與串行端口數據的行爲並不相同。

所以我的主要問題是:什麼是一個很好的輕量級的方式來閱讀消息從串口沒有重輪詢? (在Linux中,使用C或C++)

+1

你使用非阻塞'read()'?阻止'read()'不適合你嗎? – Ariel

+0

調用'read'是一個阻塞調用。你真的可以證明調用'read'是否對12%的CPU使用負責,或者你只是在看系統監視器?如果真的是CPU密集型,請嘗試通過'gprof'運行它來查看瓶頸所在。 –

+0

我通常在大多數情況下使用Qt庫,但對於這個小任務似乎有點沉重。另外我喜歡學習API的「更低」級別。我的第一次嘗試使用了阻塞read(),而libevent嘗試使用了非阻塞read()。我會檢查gprof並使用一個簡單的阻塞read()明天,並將我的發現報告回來。 – darkadept

回答

12

的OP有可能早就解決了這一點,但對任何人的緣故誰由谷歌在這裏得到:

#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 */ 
     } 
    } 
}  

確保串行端口已在非阻塞打開模式爲poll()有時可以在沒有字符等待時返回。