共計 1808 個字符,預計需要花費 5 分鐘才能閱讀完成。
Linux 串口 IO 模式的心得有哪些呢,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面丸趣 TV 小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。
眾所周知,在 Linux 系統下所有設備都是以文件的形式存在,串口也一樣。
通常 I / O 操作都是有阻塞與非阻塞的兩種方式。
其中 超時 這個概念其實是阻塞中的一種處理手段,本質還是屬于阻塞的 I / O 模式.
在 Linux 中串口的 IO 操作 本文將它分為三種狀態:
阻塞狀態
超時狀態
非阻塞狀態
這三種狀態的轉換組合有這么幾種:
阻塞 — 超時
阻塞 — 非阻塞
超時 — 阻塞
超時 — 非阻塞
非阻塞 — 阻塞
我們一個一個來分析
首先在一個串口的描述符打開的時候指定它的模式是阻塞還是阻塞
fd = open(/dev/tttyS0 ,O_RDWR | O_NOCTTY);// 以阻塞模式打開串口 fd = open(/dev/tttyS0 ,O_RDWR | O_NOCTTY | O_NDELAY);// 以非阻塞模式打開串口 //O_NDELAY 等價于 O_NOBLOCK
當一個串口是阻塞狀態的時候便可以設置它為超時狀態。
利用 struct termios 的 cc_t c_cc[NCCS] 成員
c_cc[VTIME] 非規范模式讀取時的超時時間(單位: 百毫秒)
c_cc[VMIN] 非規范模式讀取時的最小字符數
如需需要設置超時則 c_cc[VMIN] 必須等于 0。這代表能夠讀取的最小字符是 0 個,即使用 read 讀取數據超時 read 返回 0
有一個需要注意的地方!
當 c_cc[VTIME] 設置為 0 且 c_cc[VMIN] == 0 的時候, 代表超時 0 秒 (姑且這么叫吧!) 這個時候使用 read 讀取數據會立即返回(有讀到數據時返回字節數,沒有數據和一般超時一樣返回 0)但是,雖然這時候在現象上看起來和非阻塞模式一樣 (read 都不會阻塞) 但返回值不同
非阻塞模式: read 沒有讀到數據立即返回 -1
超時 0 秒時: read 沒有讀到數據立即返回 0 (設置了超時的阻塞模式)
ret = read(fd,recvbuf,BUF_SIZE); if(ret == -1)// 非阻塞模式時 無數據返回 { //do something } ret = read(fd,recvbuf,BUF_SIZE); if(ret == 0)// 阻塞模式設置超時 0 秒時 超時返回 { //do something }
雖然表現形式一樣,但在編程時必須要了解自己使用的是哪一種模式和串口當前的狀態才能更好的分析和處理問題。
這里說一下我曾經遇到過的一個問題:
我在打開串口時使用阻塞模式打開,但是沒有設置 c_cc[VMIN]的值,而它初始化后就是 0, 所以發現串口沒有被阻塞,其實原因就是串口模式還是阻塞模式沒錯,但是它是超時 0 秒的狀態,所以在沒有數據到達時 read 也返回了。
阻塞狀態和非阻塞狀態的切換
非阻塞狀態時使用
fcntl(fd,F_SETFL,0);
即可轉換成阻塞狀態,同樣可以設置超時
當非阻塞狀態已經設置了超時時,在轉換成阻塞狀態后超時也隨同生效
阻塞狀態時使用
fcntl(fd,F_SETFL,FNDELAY); //FNDELAY 等價于 FNONBLOCK
即可轉換成非阻塞狀態,超時失效
這里提一下 fcntl.h 中幾個宏的定義
/* Define some more compatibility macros to be backward compatible with BSD systems which did not managed to hide these kernel macros. */ #ifdef __USE_BSD # define FAPPEND O_APPEND # define FFSYNC O_FSYNC # define FASYNC O_ASYNC # define FNONBLOCK O_NONBLOCK # define FNDELAY O_NDELAY #endif /* Use BSD. */
現在一目了然了吧?打開串口時非阻塞模式的 O_NDELAY 或 O_NONBLOCK 選項
fcntl 設置非阻塞模式的第 3 個參數 FNDELAY 或者 FNONBLOCK 其實都是 O_NONBLOCK 主要就是為了兼容
看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注丸趣 TV 行業資訊頻道,感謝您對丸趣 TV 的支持。