linux中select監(jiān)聽(tīng)多路串口數(shù)據(jù)

串口讀函數(shù)read是阻塞函數(shù),多路串口接收不太好處理,如果每路串口使用單獨(dú)的線程接收浪費(fèi)資源,使用select()函數(shù)監(jiān)聽(tīng)多路串口數(shù)據(jù)可以把所有接收的數(shù)據(jù)在一個(gè)線程中處理,類(lèi)似QT中的槽函數(shù)功能。
1、函數(shù)原型介紹

int select(int nfds, fd_set *rdfds, fd_set *wtfds, fd_set *exfds, struct timeval *timeout)

入口參數(shù):
①:ndfs:select() 中監(jiān)視的文件句柄,一般設(shè)為要監(jiān)視的文件中的最大文件號(hào)加一。
②:rdfds:select()監(jiān)視的可讀文件句柄集合,當(dāng)rdfds映象的文件句柄狀態(tài)變成可讀時(shí)系統(tǒng)告訴select函數(shù)返回。這個(gè)集合中有一個(gè)文件可讀,select就會(huì)返回一個(gè)大于0的值,表示有文件可讀,如果沒(méi)有可讀的文件,則根據(jù)timeout參數(shù)再判斷是否超時(shí),若超出timeout的時(shí)間,select返回0,若發(fā)生錯(cuò)誤返回負(fù)值,可以傳入NULL值,表示不關(guān)心任何文件的讀變化;
③:wtfds: select()監(jiān)視的可寫(xiě)文件句柄集合,當(dāng)wtfds映象的文件句柄狀態(tài)變成可寫(xiě)時(shí)系統(tǒng)告訴select函數(shù)返回。
如果這個(gè)集合中有一個(gè)文件可寫(xiě),select就會(huì)返回一個(gè)大于0的值,表示有文件可寫(xiě),
如果沒(méi)有可寫(xiě)的文件,則根據(jù)timeout參數(shù)再判斷是否超時(shí),
若超出timeout的時(shí)間,select返回0,若發(fā)生錯(cuò)誤返回負(fù)值,
可以傳入NULL值,表示不關(guān)心任何文件的寫(xiě)變化。
④:exfds:select()監(jiān)視的異常文件句柄集合,當(dāng)exfds映象的文件句柄上有特殊情況發(fā)生時(shí)系統(tǒng)會(huì)告訴select函數(shù)返回。
⑤:timeout:select()的超時(shí)結(jié)束時(shí)間
配置函數(shù):
FD_ZERO(fd_set *fdset):清空f(shuō)dset與所有文件句柄的聯(lián)系。
FD_SET(int fd, fd_set *fdset):建立文件句柄fd與fdset的聯(lián)系。
FD_CLR(int fd, fd_set *fdset):清除文件句柄fd與fdset的聯(lián)系。
FD_ISSET(int fd, fdset *fdset):檢查fdset聯(lián)系的文件句柄fd是否可讀寫(xiě),>0表示可讀寫(xiě)。

2、

int main(void)
{
    int     uart01_fd ,uart02_fd;
    fd_set  recv_fds;  /* 定義接收f(shuō)ds  一個(gè)存放文件描述符(file descriptor),即文件句柄的聚合,實(shí)際上是一long類(lèi)型的數(shù)組 */
    int     maxfd   = 0;    /* 定義最大句柄 */
    int     fd_result;
    struct  timeval tv;       /* 超時(shí)時(shí)間 */

    uart01_fd   =    open("/dev/ttyO1", O_RDWR | O_NOCTTY); /* 打開(kāi)串口 */
    if(uart01_fd < 0) {
        printf("open /dev/ttyO1 error \r\n");
               // return -1;
    }
    
    uart02_fd   =    open("/dev/ttyO2", O_RDWR | O_NOCTTY); /* 打開(kāi)串口 */
    if(uart02_fd < 0) {
        printf("open /dev/ttyO2 error \r\n");
               // return -1;
    }
    
    tv.tv_sec   = 10;       //設(shè)定超時(shí)時(shí)間 
    tv.tv_usec  = 0;          //10000us = 10ms
    if(uart01_fd > maxfd)                            /* maxfd 為最大值  */
    {
        maxfd = uart01_fd;
    }
    if(uart02_fd > maxfd)
    {
        maxfd = uart01_fd;
    }
    for(;;)
    {   
        /* 注意每次都要重新設(shè)置 */
        FD_ZERO(&recv_fds);
        FD_SET(uart01_fd,&recv_fds);                                /* 分別把句柄加入讀監(jiān)視集合里去   */
        FD_SET(uart02_fd,&recv_fds);                                /* 分別把句柄加入讀監(jiān)視集合里去   */

        fd_result = select(maxfd + 1, &recv_fds, NULL, NULL, &tv);  /* 注意是最大值加1                   */
        if(fd_result < 0)
        {
                printf("select err");                               /* select函數(shù)出錯(cuò)                 */
            usleep(10000);
            continue;
        }
        else if(fd_result == 0)
        {
            // printf("select time out \n"); /* 在設(shè)定的tv時(shí)間內(nèi),socket的狀態(tài)沒(méi)有發(fā)生變化 */
            usleep(10000);
            continue;
        }
        else                                                        /* 開(kāi)始讀數(shù)據(jù) */
        {
            if(FD_ISSET(uart01_fd, &recv_fds))                      /* 先判斷一下是哪個(gè)句柄可讀 */
                {
                uiLen  = read(uart01_fd,ucbuff,0xff);               /*  讀取串口數(shù)據(jù)  */
                                /*
                                  ** 數(shù)據(jù)解析 
                                  */        
            }   
            if(FD_ISSET(uart02_fd, &recv_fds))                      /* 先判斷一下是哪個(gè)句柄可讀 */
                {
                uiLen  = read(uart02_fd,ucbuff,0xff);                /*  讀取串口數(shù)據(jù)  */
                                /*
                                  ** 數(shù)據(jù)解析 
                                  */        
            }
        }
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 串口操作 串口操作需要的頭文件 #include /*標(biāo)準(zhǔn)輸入輸出定義*/ #include /*標(biāo)準(zhǔn)函數(shù)庫(kù)定...
    旅行家John閱讀 1,469評(píng)論 0 3
  • 本文摘抄自linux基礎(chǔ)編程 IO概念 Linux的內(nèi)核將所有外部設(shè)備都可以看做一個(gè)文件來(lái)操作。那么我們對(duì)與外部設(shè)...
    lintong閱讀 1,686評(píng)論 0 4
  • I/O復(fù)用基本概念 I/O多路復(fù)用技術(shù)通過(guò)把多個(gè)I/O的阻塞復(fù)用到同一個(gè)select的阻塞上,從而使得系統(tǒng)在單線程...
    Ycres閱讀 1,054評(píng)論 0 0
  • select,poll,epoll都是IO多路復(fù)用的機(jī)制。I/O多路復(fù)用就是通過(guò)一種機(jī)制,可以監(jiān)視多個(gè)描述符,一旦...
    yeying12321閱讀 1,769評(píng)論 0 5
  • 概念 首先要說(shuō)明幾個(gè)概念: 用戶空間和內(nèi)核空間 進(jìn)程切換 進(jìn)程的阻塞 文件描述符 緩存 I/O 用戶空間與內(nèi)核空間...
    jiangmo閱讀 994評(píng)論 0 9

友情鏈接更多精彩內(nèi)容