2013-01-10 29 views
3

最近我發現了一個對我來說很新的問題,我會很感激的建議。我使用termios函數在Linux上進行串行通信。我其實並沒有使用真正的串口,而是虛擬的小工具串口驅動程序/dev/ttyGS0。文件描述符被打開爲非阻塞。在linux中的串行端口描述符塊'close'功能

我的程序定期生成數據併發送到/ dev/ttyGS0。如果另一端讀取或不讀取信息,則不會有任何信息。如果沒有,一些內部FIFO會填滿並寫回「會阻塞」錯誤。到目前爲止,我沒有任何問題。

問題是,當我想關閉帶有填充FIFO的文件描述符時,關閉函數塊!不是無限期的,但約10秒鐘。

我試圖做tcflush(uart->fd, TCOFLUSH)之前關閉沒有任何影響。

這對我來說是非常奇怪的行爲,我發現沒有描述,關閉可能會阻止。有什麼辦法可以避免這種情況?或者至少減少這個超時?我應該在哪裏尋找這個超時? VTIME屬性對此也沒有影響。

+2

close()映射到可能發生延遲的設備驅動程序中的調用。如果你有驅動程序的源代碼,你可以修改它的行爲。還要查找該設備支持的任何自定義ioctl()調用,以允許修改該行爲。 –

+0

對於我來說,關閉具有數據的close()會阻塞 - 我認爲非阻塞IO的POSIX語義也不會延伸到close()。我希望在'close()'之後,設備將處於開始準備好再次打開()的狀態。由於這是通過USB的虛擬串口,我會開始懷疑終端的無序拆卸,並且10是超時。 – marko

回答

2

正如Amardeep所述,close()調用由驅動程序處理。關閉本身始終是一個阻塞呼叫,但通常它是一個快速的呼叫。

所以,答案是延遲是特定於虛擬小工具驅動程序。我沒有這方面的經驗幫助。

它關閉文件有多重要?如果延遲是一個主要問題並且需要關閉文件(例如避免長時間運行的進程中的文件描述符泄漏),那麼可能需要在單獨的線程中調用close。顯然,最好的答案將是那個司機的特定答案。也許研究可能會產生一個答案,例如清除虛擬設備狀態的ioctl()調用。

0

我面臨同樣的問題,在我的情況下關閉設備之前禁用流量控制幫助。爲此,您可以使用以下功能:

int set_flowcontrol(int fd, int control) 
{ 
    struct termios tty; 
    memset(&tty, 0, sizeof tty); 
    if (tcgetattr(fd, &tty) != 0) 
    { 
     perror("error from tggetattr"); 
     return -1; 
    } 

    if(control) tty.c_cflag |= CRTSCTS; 
    else tty.c_cflag &= ~CRTSCTS; 

    if (tcsetattr(fd, TCSANOW, &tty) != 0) 
    { 
     perror("error setting term attributes"); 
     return -1; 
    } 
    return 0; 
} 

收盤前只需撥打這個:

... 
rc = set_flowcontrol(fd, 0); 
if (rc != 0) 
{ 
    perror("error setting flowcontrol: "); 
    exit(-1); 
} 

rc = close(fd); 
if (rc != 0) 
{ 
    perror("error closing fd: "); 
    exit(-1); 
} 
... 
0

您可能需要配置端口的closing_wait參數。從setserial的手冊:

closing_wait延遲 指定的時間量,在百分之一秒,內核應等待從 被髮送而 關閉該端口的串行端口數據。如果指定「無」,則不會發生延遲。如果指定「無限」,則內核將無限期地等待 ,以便傳輸緩衝數據。默認設置爲3000或30秒延遲。此默認值通常爲 適用於大多數 設備。如果選擇的延遲時間太長,則串行端口可能會掛起很長時間,如果串行端口 未連接,並且 有數據未決,則會關閉。如果選擇的延遲太短,則有可能發生一些傳輸數據爲 輸出。 如果設備非常慢,如繪圖儀,closing_wait可能需要更大。

請與您的端口setserial的參數:

$ setserial -g -a /dev/ttyS0 
/dev/ttyS0, Line 0, UART: 16550A, Port: 0x03f8, IRQ: 4 
     Baud_base: 115200, close_delay: 50, divisor: 0 
     closing_wait: 3000 
     Flags: spd_normal skip_test 

在我的情況下,斷層設備沒有收到我送了它最後的字節,並關閉端口始終把正因爲如此30秒。您可以更改此超時與setserial的,例如,1秒:

$ sudo setserial /dev/ttyS0 closing_wait 100 

當然,你可能希望在發佈關於啓動此命令你的/etc/rc.local或任何腳本你的發行版使用配置你的端口。