linux epoll/select使用区分和实例对比

这篇具有很好参考价值的文章主要介绍了linux epoll/select使用区分和实例对比。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


Linux内核poll,ppoll,epoll,select代码位置:

poll,ppoll,select相关内核实现在在fs/select.c中;

epoll_ctl和epoll_wait相关函数在fs/eventpoll.c中

epoll实测不支持监听普通文件,select可以,但是发现无论是可读、可写,其一直会返回准备就绪状态,所以select也无法实际用来监控普通文件,可用来监听物理设备如uart对应的ttyS0等。

epoll_ctl控制普通文件会返回-1,即EPERM,添加的fd不支持epoll。比如添加的是普通文件描述符内核设备文件poll file operations定义类似如下:

linux epoll/select使用区分和实例对比,linux,运维,服务器

linux epoll/select使用区分和实例对比,linux,运维,服务器

如下通过epoll实现监控IO变化:

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <pthread.h>
#include <time.h>
#include <signal.h>
#include <semaphore.h>
#include <stdarg.h>
#include <errno.h>
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>
#include <regex.h>
#include <libgen.h>
#include <poll.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdbool.h>
#include <stdarg.h>
#include <math.h>
#include <getopt.h>
#include <ctype.h>
#include <sys/epoll.h>
#include <sys/timerfd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/syscall.h>
#include <sys/eventfd.h>
#include <sys/socket.h>
#include <sys/reboot.h>
#include <sys/resource.h>
#include <sys/prctl.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <sys/un.h>
#include <sys/shm.h>
#include <stddef.h>

#include <linux/input.h>
#include <linux/types.h>
#include <linux/sockios.h>
#include <linux/ethtool.h>
#include <linux/netlink.h>


static bool thread_start = 0;
static int32_t epoll_fd  = -1;
static int32_t g_test_gpio_fd = -1;
static int32_t g_test_status_fd = -1;
static int test_action  = 1;

typedef struct{
    int8_t              thread_name[OWN_THREAD_NAME_SIZE];     //thread name
    pthread_t     m_thead;                                //thread hanle
    uint32_t            thread_priority;                        //thread priority
    uint32_t            stack_depth;                            //stack size
    void                *thread_func;                           //thread func
    void                *para;                                  
}OWN_thread_t;

#define OWN_THREAD_NAME_SIZE      20
#define TEST_PATH      "/etc/test_value"
#define OWN_WAKE_GPIO_MAX_SIZE             (10)
#define OWN_MIN_STACK         100*1024
#define F_FAIL -1
#define F_SUCCESS 1
#define EPOLL_TIMEOUT (1000)
#define OWN_BUFSIZE_4                  4
#define OWN_THREAD_PRIORITY            3
#define OWN_test_THREAD_STACK_SIZE       (18 * 1024)//byte(18kb)

int32_t OWN_thread_create(OWN_thread_t *threadin)
{
    int32_t ret = -1;

    if(threadin == NULL)
    {
        printf("threadin is null\n");
    }
        pthread_attr_t attr;
        ret = pthread_attr_init(&attr);
        if (ret != 0)
        {
           printf("pthread_attr_init Error\n");
           return -1;
        }
        if(threadin->stack_depth < OWN_MIN_STACK)
        {
            threadin->stack_depth = OWN_MIN_STACK;
        }
        ret = pthread_attr_setstacksize(&attr, threadin->stack_depth);
        if(ret != 0)
        {
           printf("pthread_attr_setstacksize %d Error=%d\n",threadin->stack_depth,ret);
           return -1;
        }
        ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
        if(ret != 0)
        {
           printf("pthread_attr_setdetachstate Error=%d\n",ret);
           return -1;
        }
        ret = pthread_create(&(threadin->m_thead), &attr, threadin->thread_func, (void *)(threadin->para));
        pthread_attr_destroy (&attr);
        if(ret != 0)
        {
            printf("pthread_create Error, ret=%d, err:%s\n", ret, strerror(errno));
            return F_FAIL;
        }
        else
        {
            return F_SUCCESS;
        }

    return F_FAIL;
}

static void *OWN_thread_handler(void *arg)
{
    static int32_t first_reload = 1;
    int32_t fd_cnt = 0;
    int32_t ret = 0;
    int32_t i = 0;
    int8_t value[OWN_BUFSIZE_4] = {0};
    struct epoll_event events[OWN_WAKE_GPIO_MAX_SIZE];
    int8_t value_status = 0;

    while (thread_start)
    {
        memset(events, 0x0, sizeof(events));
        fd_cnt = epoll_wait(epoll_fd, events, OWN_WAKE_GPIO_MAX_SIZE, EPOLL_TIMEOUT);
        if(fd_cnt <= 0)
        {
            continue;
        }

        for(i = 0; i < fd_cnt; i++)
        {
            memset(value, 0x0, sizeof(value));
            lseek(events[i].data.fd, 0, SEEK_SET);
            ret = read(events[i].data.fd, value, sizeof(value));
            value_status = atoi((const char *)value);
            printf("value =%s value_status =%d ret : %d\n", value, value_status, ret);

            if (events[i].events & EPOLLPRI  && events[i].data.fd == g_test_gpio_fd)
            {
                printf("gpio test file \r\n");
                if (test_action != NULL)
                {

                    printf("callback test value =%s value_status =%d ret : %d\n", value, value_status, ret);
                }
            }
        }
    }

    return NULL;
}

int main()
{
    int ret = 0;

    struct epoll_event evd = {0};
    OWN_thread_t test_gpio_thread;
    epoll_fd = epoll_create(OWN_WAKE_GPIO_MAX_SIZE);
    if (epoll_fd < 0)
    {
        printf("epoll error \n");
    }
    g_test_gpio_fd = open(TEST_PATH , O_RDONLY | O_NONBLOCK);
    if (g_test_gpio_fd < 0)
    {
        printf("open error \n");
    }

    memset(&evd, 0x0, sizeof(evd));
    evd.data.fd = g_test_gpio_fd;
    evd.events = EPOLLPRI;

    ret = epoll_ctl(g_test_epoll_fd, EPOLL_CTL_ADD, epoll_fd, &evd);
    if (ret < 0)
    {
        printf("epoll_ctl error \n");
    }

    thread_start = 1;
    memset(&test_gpio_thread, 0, sizeof(test_gpio_thread));
    snprintf((char*)test_gpio_thread.thread_name,OWN_THREAD_NAME_SIZE - 1, "Notify handle");
    test_gpio_thread.thread_priority  = OWN_THREAD_PRIORITY;
    test_gpio_thread.stack_depth      = OWN_test_THREAD_STACK_SIZE;
    test_gpio_thread.thread_func      = OWN_thread_handler;
    test_gpio_thread.para             = NULL;

    ret = OWN_thread_create(&test_gpio_thread);
    if (ret != F_SUCCESS) {
        printf("OWN_thread_handler creation failure !\n");
    }
    while(1)
    {
        sleep(2);
    }

    return 0;
}

select应用示例:如下实例为监听普通文件,发现返回值一直大于0,监听意义不大。可以将监听的设备改为ttyS0,则可以正常监控。

函数返回值如下:

>0:就绪描述字的正数目

-1:出错

0 :超时

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <pthread.h>
#include <time.h>
#include <signal.h>
#include <semaphore.h>
#include <stdarg.h>
#include <errno.h>
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>
#include <regex.h>
#include <libgen.h>
#include <poll.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdbool.h>
#include <stdarg.h>
#include <math.h>
#include <getopt.h>
#include <ctype.h>


#include <sys/epoll.h>
#include <sys/timerfd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/syscall.h>
#include <sys/eventfd.h>
#include <sys/socket.h>
#include <sys/reboot.h>
#include <sys/resource.h>
#include <sys/prctl.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <sys/un.h>
#include <sys/shm.h>
#include <stddef.h>
#include <linux/input.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#include <linux/sockios.h>
#include <linux/ethtool.h>
#include <linux/netlink.h>

static pthread_t test_thread;
int fd = 0;
static void *thread_func(void * arg);

int main(int argc, char * argv [ ])
{
    int ret;
    char buf[] = "hello test! ";

    if (argc < 2)
    {
        return -1;
    }

    setbuf(stdout, NULL);

    fd = open("/etc_rw/test_select", O_RDWR  | O_NONBLOCK);
    if (fd > 0)
    {
        printf("Open success! \n");
    }
    else
    {
        printf("Open failure! \n");
    }

    if (pthread_create(&test_thread, NULL, thread_func, NULL) != 0)
    {
        printf("Failed to creat thread \n");
    }

    while (fd >= 0)
    {
        //ret = write(fd, (uint8_t*)buf, strlen(buf));
        printf("Write fd value = %d, ret value = %d \n", fd, ret);
        sleep(2);
    }

    return 0;
}

static void *thread_func(void * arg)
{
    int ret;
    fd_set fdset;
    struct timeval timeout = {4, 0};
    char buf[100] = {0};

    timeout.tv_sec = 5;
    timeout.tv_usec = 0;
    while (fd >= 0)
    {
        FD_ZERO(&fdset);
        FD_SET(fd, &fdset);
        ret = select(fd + 1, &fdset, NULL, NULL, &timeout);
        if (ret == -1)
        {
            printf("Failed to select \n");
        }
        else if (ret == 0)
        {
            printf("ret value is 0 \n");
            timeout.tv_sec = 4;
            timeout.tv_usec = 0;
        }
        else
        {
            if (FD_ISSET(fd, &fdset))
            {
                //do
               // {
                    memset(buf, 0, 100);
                    ret = read(fd, buf, 100);
                    printf("Read ret = %d buf = %s \n", ret, buf);
               // }while(ret == 200);
            }
        }
    }

    return (void *)1;
}


 文章来源地址https://www.toymoban.com/news/detail-523945.html

到了这里,关于linux epoll/select使用区分和实例对比的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • linux poll,epoll,select的区别

    epoll中红黑树的作用? 红黑树(rbtree)、以及epoll的实现原理_epoll 红黑树_For Nine的博客-CSDN博客 红黑树和epoll_wait的关系? epoll_wait/就绪list和红黑树的关系 - 知乎 其他区别: 1. select 在linux内核中限制了能监听的数目上限。32位是1024,64位是2048 2. poll是将监听的对象改成了链表

    2024年02月03日
    浏览(40)
  • 【Linux】高级IO --- 多路转接,select,poll,epoll

    所有通过捷径所获取的快乐,无论是金钱、性还是名望,最终都会给自己带来痛苦 1. 后端服务器最常用的网络IO设计模式其实就是Reactor,也称为反应堆模式,Reactor是单进程,单线程的,但他能够处理多客户端向服务器发起的网络IO请求,正因为他是单执行流,所以他的成本就

    2024年02月09日
    浏览(66)
  • 华为云云耀云服务器L实例评测 | Linux系统宝塔运维部署H5游戏

    本章节内容,我们主要介绍华为云耀服务器L实例,从云服务的优势讲起,然后讲解华为云耀服务器L实例资源面板如何操作,如何使用宝塔运维服务,如何使用运维工具可视化安装nginx,最后部署一个自研的H5的小游戏(6岁的小朋友玩的很开心😁)。 前端的同学如果想把自己

    2024年02月07日
    浏览(58)
  • 02-Linux-IO多路复用之select、poll和epoll详解

    前言: 在linux系统中,实际上所有的 I/O 设备都被抽象为了文件这个概念,一切皆文件,磁盘、网络数据、终端,甚至进程间通信工具管道 pipe 等都被当做文件对待。 在了解多路复用 select、poll、epoll 实现之前,我们先简单回忆复习以下两个概念: 一、什么是多路复用: 多路

    2024年02月10日
    浏览(58)
  • 手撕测试tcp服务器效率工具——以epoll和io_uring对比为例

    服务器的性能测试主要包括2部分: 并发量。能容纳多大的连接 效率。在不崩坏的情况下能对报文的处理效率。 本文主要进行效率测试,看看基于epoll模型和io_uring模型的tcp服务器,谁的效率更高。 测试思路 客户端(一个或多个)大量地向服务器发送报文,测试服务器的处理

    2024年01月18日
    浏览(102)
  • select,poll,epoll阻塞IO使用示例介绍

    epoll 打开设备文件或套接字,并确保设备或套接字处于可读或可写状态。 创建一个 epoll 实例,使用 epoll_create 函数创建一个 epoll 文件描述符。 将设备文件或套接字的文件描述符添加到 epoll 实例中,使用 epoll_ctl 函数将设备文件或套接字的文件描述符添加到 epoll 实例中,并设

    2024年02月12日
    浏览(42)
  • Linux多路IO复用技术——epoll详解与一对多服务器实现

    本文详细介绍了Linux中epoll模型的优化原理和使用方法,以及如何利用epoll模型实现简易的一对多服务器。通过对epoll模型的优化和相关接口的解释,帮助读者理解epoll模型的工作原理和优缺点,同时附带代码实现和图解说明。

    2024年02月05日
    浏览(44)
  • epoll与select区别

    首先select是posix支持的,而epoll是linux特定的系统调用,因此,epoll的 可移植性 就没有select好,但是考虑到epoll和select一般用作服务器的比较多,而服务器中大多又是linux,所以这个可移植性的影响应该不会很大。 其次,select可以监听的 文件描述符有限 ,最大值为1024,而epo

    2024年02月01日
    浏览(41)
  • Linux学习记录——사십삼 高级IO(4)--- Epoll型服务器(1)

    poll依然需要OS去遍历所有fd。一个进程去多个特定的文件中等待,只要有一个就绪,就使用select/poll系统调用,让操作系统把所有文件遍历一遍,哪些就绪就加上哪些fd,再返回。一旦文件太多了,遍历效率就显而易见地低。epoll是为处理大批量句柄而作了改进的poll,句柄就是

    2024年01月18日
    浏览(52)
  • Linux学习记录——사십사 高级IO(5)--- Epoll型服务器(2)(Reactor)

    本篇基于上篇代码继续改进,很长。关于Reactor的说明在后一篇 上面的代码在处理读事件时,用的request数组是临时的,如果有数据没读完,那么下次再来到这里,就没有这些数据了。所以得让每一个fd都有自己的缓冲区。建立一个Connection类,然后有一个map结构,让这个类和每

    2024年01月20日
    浏览(60)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包