Linux - io多路复用(poll和epoll)

本文介绍了Linux系统编程中的三种I/O多路复用技术:select、poll和epoll。select使用描述符集合,poll利用链表管理,而epoll通过事件注册避免轮询,提高效率。详细讲解了三者的编程模型,包括它们的使用方法、事件类型及优缺点。epoll以其高效性成为现代Linux系统编程的首选。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

No.1 pool:轮询

    1. 没有最大描述符好的限制 ()
    1. select在操作描述符号的时候用的是描述符号集合(数组) fd_set
      poll在操作描述符号的时候用的是链表
    1. select 阻塞 poll 把动静赋值到结构体的链表中,然后返回

         poll编程模型:
         	+ 1. 创建fd结构体数组(实际上是一个链表)
         			struct pollfd fds[300]; 
         	+ 2. 把描述符号设置好
         			struct pollfd {
           			 int   fd;         /* 描述符号 */
           			 short events;     /* 请求事件 */
           			 short revents;    /* 返回事件 */
       			 	};
         			
         			POLLIN     		有数据可以读
         		    POLLRDNORM		有普通数据可以读
         		    POLLRDBAND 		有优先数据可以读
         		
         		    POLLPRI  	    有紧急数据可以读
         		
         		    POLLOUT			写数据不会阻塞  可以写
         		    POLLWRNORM  	可以写普通数据
         		    POLLWRBAND 	    可以写优先数据
         		
         		    POLLMSGSIGPOLL 	消息可以使用
         		    POLLER			指定的fd出现错误
         		    POLLHUP			指定的fd被挂起
         		    POLLNVAL		指定的fd是错误的
         	+ 3. 监视
         			poll
         	+ 4. 根据poll的返回值针对性操作
      
 #include <sys/select.h>
/* According to earlier standards */
#include <sys/time.h>
#include <poll.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
    struct pollfd fds[10]={0};
    
    fds[0].fd = 0;//监控终端标准输入设备
    fds[0].events = POLLIN;//监控 有数据可读行为
    char buff[256];
    while(1)
    {
        int r = poll(fds,1,0);
        // printf("r:%d\n",r);
        if(r>0)
        {
            printf("%d有动静了\n",r);
            if(fds[0].revents&POLLIN)
            {
                scanf("%s",buff);
                printf("接收到了:%s\n",buff);
            }
           
        }
    }

    return 0;
}

No.2 eploo:中断

  • select和poll没有本质的区别,他们都是轮询fd是否有动静
    + select是没有动静就阻塞,有动静就返回
    + poll是没有动静都写结构体成员revents然后返回
    + 效率受描述符号个数的影响(监视的描述符号越多,效率越低)

  • epoll是优化后的poll,通过注册事件来避开轮询,有变化会发消息

  • epoll的编程模型 :
    1. 创建epoll
    epoll_create
    2. 注册描述符号的事件
    epoll_ctl
    3. 等待消息的到来,挨个处理事件
    epoll_wait

     #include <sys/epoll.h>
     int epoll_create(int size);
     int epoll_create1(int flags);
     int epoll_ctl(
     	int epfd, 					//epoll的返回值,epoll的id
     	int op,						//操作方式
     			EOPLL_CTL_ADD
     			EPOLL_CTL_MOD
     			EPOLL_CTL_DEL
     	int fd, 					//需要监视的fd
     	struct epoll_event *event);	//监视描述符号信息链表 链表头
     	typedef union epoll_data {
            void        *ptr;
            int          fd;
            uint32_t     u32;
            uint64_t     u64;
        } epoll_data_t;
    
        struct epoll_event {
            uint32_t     events;      /* Epoll events */
            epoll_data_t data;        /* User data variable */
        };
     	int epoll_wait(
     		int epfd,						//epoll的idepoll_creat的返回值 
     		struct epoll_event *events,//监视描述符号信息链表 链表头
             int maxevents,			//事件结构体数量,第二个参数的结构体数量
             int timeout);
    

    如果等到了,返回有动静的描述符号数量

epoll的简单使用

 #include <sys/select.h>
/* According to earlier standards */
#include <sys/time.h>
#include <sys/epoll.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
    //1. 创建epoll
    int epfd = epoll_create(2);
    //2. 注册事件
    struct epoll_event ev;
    ev.events = EPOLLIN;
    ev.data.fd = 0;

    int r = epoll_ctl(epfd,EPOLL_CTL_ADD,0,&ev);
    if(r==-1)printf("注册失败!%m\n"),exit(-1);
    printf("注册事件成功!%m\n");
   
    char buff[256];
    struct epoll_event events[2];
    while(1)
    {
        r = epoll_wait(epfd,events,2,1000);
        // printf("r:%d\n",r);
        if(r>0)
        {
            printf("%d有动静了\n",r);
            if(events[0].data.fd==0)
            {
                scanf("%s",buff);
                printf("接收到了:%s\n",buff);
            }
           
        }
        else if(0==r)
        {
            continue;
        }
        else
        {
            printf("出问题了!\n");
        }
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值