色偷偷偷亚洲综合网另类,亚洲欧美另类在线观看,欧美午夜激情在线,久久久精品一区

Hi,歡迎來到嵌入式培訓(xùn)高端品牌 - 華清遠見教育科技集團<北京總部官網(wǎng)>,專注嵌入式工程師培養(yǎng)15年!
當(dāng)前位置: > 華清遠見教育科技集團 > 嵌入式學(xué)習(xí) > 講師博文 > 多路復(fù)用select與poll
多路復(fù)用select與poll
時間:2017-01-04作者:華清遠見

在UNIX/linux中有4中IO模型,分別為:
        1、 阻塞IO
        2、 非阻塞IO
        3、 IO多路復(fù)用
        4、 信號驅(qū)動IO

這幾種IO模型,阻塞IO是長用到的,并且操作相對簡單,但是缺點在于效率低下,尤其是在,同時操作多個IO的時候,不能隨時的處理各個IO操作。而非阻塞IO可以解決這個問題,但是同樣也存在的問題,因為使用非阻塞IO模型的時候,就需要對每個IO操作進行輪訓(xùn)操作,而實際上輪空的幾率是很大的,多以非阻塞IO模型是在那種輪空幾率相對較小的的時候才會使用。因為輪訓(xùn)是會占用相當(dāng)多的cpu時間片的。基于這種考慮多路復(fù)用模型變產(chǎn)生了。

多路復(fù)用模型是對多個IO操作進行檢測,返回可操作集合,這樣就可以對其進行操作了。這樣就避免了阻塞IO不能隨時處理各個IO和非阻塞占用系統(tǒng)資源的確定。下面就多路復(fù)用中兩個常用的系統(tǒng)調(diào)用select和poll進行簡單的說明。

1、 select

select函數(shù)的原型為:

#include <sys/select.h>
        #include <sys/time.h>
        #include <sys/types.h>
        #include <unistd.h>
        int select(int nfds,
                fd_set *readfds, 
                fd_set *writefds,
                fd_set *exceptfds, 
                struct timeval *timeout);

select的使用需要維護三類文件描述符集合,分別是:
        readfds:用于存放我們要檢測的可讀的文件描述符。
        writefds:用于存放我們要檢測的可寫的文件描述符。
        exceptfds:用于存放我們要檢測的是否發(fā)生異常的文件描述符。

在使用select的時候需要注意,在調(diào)用select后者幾個集合就會變化,變?yōu)槭遣僮鞯募希纯勺x寫或發(fā)生異常,所以在調(diào)用select之前需要保存以前的集合。

系統(tǒng)為我們提供了下面四個宏來操作這些文件描述符集合:

void FD_SET(int fd, fd_set *set);
        void FD_CLR(int fd, fd_set *set);
        I int FD_ISSET(int fd, fd_set *set);
        void FD_ZERO(fd_set *set);

其中FD_SET用來將一個文件描述符加入到文件描述符集合里,F(xiàn)D_CLR是刪除,F(xiàn)D_ISSET是判斷文件描述符是否在這個集合里,而FD_ZERO是將這個集合清零。

下面我們以一個簡單的例子來說明select的使用。

#include <stdio.h>
        #include <stdlib.h>
        #include <unistd.h>
        #include <string.h>
        #include <sys/types.h>
        #include <sys/select.h>
        #include <sys/socket.h>
        #include <netinet/in.h>
        #include <arpa/inet.h>

#define N 64

int main(int argc, char *argv[])
        {
                if(argc != 2)
                {
                        printf(“format: server <server ip> <server port>”);
                        exit(0);
                }
                int i, servsock, connfd, maxfd;
                char buf[N];
                fd_set rdfd,rdfd1;

        struct sockaddr_in servaddr;

        if((servsock = socket(PF_INET, SOCK_STREAM, 0)) < 0)
                {
                        perror("socket");
                        exit(1);
                }

        memset(&servaddr, 0, sizeof(servaddr));
                servaddr.sin_family = PF_INET;
                servaddr.sin_addr.s_addr = inet_addr("192.168.1.203");
                servaddr.sin_port = htons(8889);

        if(bind(servsock, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
                {
                        perror("bind");
                        exit(1);
                }

        listen(servsock, 5);
                maxfd = servsock;

                FD_ZERO(&rdfd1);
                FD_SET(0, &rdfd1);
                FD_SET(servsock, &rdfd1);

        for(;;)
                {

                        rdfd = rdfd1;
                        if(select(maxfd+1, &rdfd, NULL, NULL, NULL) < 0)
                        {
                                perror("select");
                                exit(1);
                        }

                for(i = 0; i <= maxfd; i++)
                        {
                                if(FD_ISSET(i, &rdfd))
                                {
                                        if( i == STDIN_FILENO)
                                        {
                                                fgets(buf, N, stdin);
                                                printf("%s", buf);
                                        }
                                        else if(i == servsock)
                                        {
                                                connfd = accept(servsock, NULL, NULL);
                                                printf("New Connection %d is comming\n", connfd);
                                                send(connfd, buf, strlen(buf), 0);
                                                sleep(1);
                                                close(connfd);
                                        }
                                }
                        }
                }

        return 0;
        }

上面這段程序在select會阻塞,這個時候我們可以定義一個時間結(jié)構(gòu)體變量,如下:

struct timeval timeout;
        timeval的原型為:
        struct timeval {
                                long        tv_sec;        /* seconds */
                                long        tv_usec;        /* microseconds */
        };

這個變量可以提供一個微秒級的時間,我們可以使用這個作為超時處理。使用方式就是把這個變量作為select系統(tǒng)調(diào)用的后一個參數(shù)。

2、 poll

poll的原型為:

#include <poll.h>
        int poll(struct pollfd *fds, nfds_t nfds, int timeout);

poll的使用不需要分別維護幾個表,只需要維護一個結(jié)構(gòu)體數(shù)組,這個結(jié)構(gòu)體為:

struct pollfd {
                                int        fd;        /* file descriptor */
                                short events;        /* requested events */
                                short revents;        /* returned events */
        };

這個結(jié)構(gòu)體幾個成員分別是我們要監(jiān)測的文件描述符,和我們請求的事件及后返回的事件。

poll事件的類型為:

POLLIN There is data to read.
        POLLPRI There is urgent data to read .
        POLLOUT Writing now will not block.
        POLLERR Error condition (output only).
        POLLHUP Hang up (output only).
        POLLNVAL Invalid request: fd not open (output only).

上面這些事件下面三種在events中沒有用的,只能在revents中才能出現(xiàn)。我們可以調(diào)用poll并且查看每個文件描述符的返回狀態(tài)進行相應(yīng)的操作。

下面以一個簡單的實力說明poll的使用:

#include <stdio.h>
        #include <stdlib.h>
        #include <unistd.h>
        #include <poll.h>
        #include <sys/socket.h>
        #include <netinet/in.h>
        #include <arpa/inet.h>
        #include <sys/types.h>
        #include <errno.h>
        #include <string.h>

#define OPEN_MAX openmax
        #define BUFSIZE 1024

int main(int argc, char **argv)
        {
                if(argc != 3)
                {
                        printf("format: server-poll <server ip> <port>");
                        exit(0);
                }

        int openmax = getdtablesize();

        int listensock, connsock;
                struct sockaddr_in servaddr;
                struct pollfd fds[OPEN_MAX];
                int i, count = 0, ready, reval;
                char readbuf[BUFSIZE];

        for(i = 0; i < OPEN_MAX; i++)
                {
                        fds[i].fd = -1;
                }

        if((listensock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
                {
                        perror("socket");
                        exit(0);
                }

        memset(&servaddr, 0, sizeof(servaddr));
                servaddr.sin_family = AF_INET;
                servaddr.sin_addr.s_addr = inet_addr(argv[1]);
                servaddr.sin_port = htons(atoi(argv[2]));

        if(bind(listensock, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
                {
                        perror("bind");
                        exit(1);
                }

        listen(listensock, 5);

        fds[0].fd = 0;
                fds[0].events = POLLIN;
                count++;
                fds[1].fd = listensock;
                fds[1].events = POLLIN;
                count++;

                for(;;)
                {
                        memset(readbuf, 0, BUFSIZE);
                        ready = poll(fds, count, 0);
                        for(i = 0; i < count; i++)
                        {
                                if(fds[i].revents & POLLIN)
                                {
                                        if(fds[i].fd == 0)
                                        {
                                                fgets(readbuf, BUFSIZE, stdin);
                                                printf("read buf:%s\n", readbuf);
                                        }
                                        else if(fds[i].fd == listensock)
                                        {
                                                connsock = accept(listensock, NULL, NULL);
                                                printf("client connect\n");
                                                fds[count].fd = connsock;
                                                fds[count].events = POLLIN;
                                                count++;
                                                }
                                                else
                                                {
                                                        reval = recv(fds[i].fd, readbuf, BUFSIZE, 0);
                                                        printf("recv buf:%s\n", readbuf);
                                                        send(fds[i].fd, readbuf, reval, 0);
                                                }
                                        }
                                }
                       }
                }
                return 0;
        }

發(fā)表評論
評論列表(網(wǎng)友評論僅供網(wǎng)友表達個人看法,并不表明本站同意其觀點或證實其描述)
色偷偷偷亚洲综合网另类,亚洲欧美另类在线观看,欧美午夜激情在线,久久久精品一区
主站蜘蛛池模板: 国产精品久久久久久影视| 日韩在线免费视频| 92裸体在线视频网站| 成人高h视频在线| 亚洲国产精品va在线| 日韩av在线免播放器| 日韩精品视频免费在线观看| 日韩精品免费在线| 中文字幕一区电影| 欧美人与物videos| 亚州欧美日韩中文视频| 日本免费久久高清视频| 国产日韩欧美另类| 精品亚洲一区二区三区在线观看| 亚洲免费成人av电影| 欧美成人精品激情在线观看| 欧美日韩性视频| 欧美一级大片视频| 成人亚洲欧美一区二区三区| 国产亚洲精品综合一区91| 欧美老女人xx| 青青a在线精品免费观看| 成人国产精品日本在线| 亚洲欧洲国产精品| 欧美大片网站在线观看| 青青草成人在线| 亚洲色图五月天| 欧美性生交大片免网| 国产精品久久久久久久久粉嫩av| 亚洲成av人片在线观看香蕉| 久久亚洲精品国产亚洲老地址| 91av在线影院| 日韩激情片免费| 日韩欧美中文字幕在线播放| 91精品久久久久久久久久久久久久 | 欧美日韩国产专区| 国产精品入口尤物| 久久影院免费观看| 国产自摸综合网| 九九九久久久久久| 91丨九色丨国产在线|