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

news2025/1/11 10:01:06


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定义类似如下:

7205909642d848d2977fb361489ab5cb.png

 

如下通过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_LISTEN_TIMEOUT                (1000)
#define OWN_BUFSIZE_4                  4
#define OWN_THREAD_PRIORITY            3
#define OWN_test_THREAD_STACK_SIZE       (16 * 1024)//byte(16kb)

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_wake_gpio_monitor_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_LISTEN_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_wake_gpio_monitor_handler;
    test_gpio_thread.para             = NULL;

    ret = OWN_thread_create(&test_gpio_thread);
    if (ret != F_SUCCESS) {
        printf("OWN_thread_wake_gpio_monitor_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;
}


 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/717102.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

医院中医临床护理中医理论考试题库及答案

本题库是根据最新考试大纲要求&#xff0c;结合近年来考试真题的重难点进行汇编整理组成的全真模拟试题&#xff0c;考生们可以进行专项训练&#xff0c;查漏补缺巩固知识点。本题库对热点考题和重难点题目都进行了仔细的整理和编辑&#xff0c;相信考生在经过了针对性的刷题练…

测试员拒绝当“背锅侠”,软件质量不是“测”出来的!

以前有个朋友跟我说&#xff1a;做测试这行就是在隐忍中负重前行。因为测试是软件发布前的最后一个环节&#xff0c;被称作质量出口儿&#xff0c;测试环节之前所有未做好的工作所带来的不良后果&#xff0c;似乎都能被轻松甩锅给测试人员。软件一旦出现问题&#xff0c;我们经…

django疫情防控常态化下疫情物资管理可视化系统-计算机毕设 附源码73893

django疫情防控常态化下疫情物资管理可视化系统 摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。…

YOLOv5改进系列(13)——更换激活函数之SiLU,ReLU,ELU,Hardswish,Mish,Softplus,AconC系列等

【YOLOv5改进系列】前期回顾: YOLOv5改进系列(0)——重要性能指标与训练结果评价及分析 YOLOv5改进系列(1)——添加SE注意力机制

javaWeb中的Ajax_待后期增加

前言&#xff1a; Ajax是一种在JavaWeb开发中常用的技术&#xff0c;通过它可以实现异步通信和动态加载数据&#xff0c;提升用户体验。 正文&#xff1a; 首先我们得明白异步通信&#xff0c;客户端发出请求后可以继续执行其他操作 由于原生的Ajax过于复杂 so&#xff1a; …

FastDFS【SpringBoot操作FastDFS、复习】(三)-全面详解(学习总结---从入门到深化)

目录 SpringBoot操作FastDFS 复习&#xff1a; SpringBoot操作FastDFS 由GitHub大牛tobato在原作者YuQing与yuqih发布的JAVA客户端基 础上进行了大量重构工作&#xff0c;并于GitHub上发布了FastDFS-Client1.26.5。 主要特性 1 对关键部分代码加入了单元测试&#xff0c;便于…

leetcode 21.合并两个有序链表

⭐️ 往期相关文章 &#x1f4ab;链接1&#xff1a;链表中倒数第k个结点(快慢指针问题) &#x1f4ab;链接2&#xff1a;leetcode 876.链表的中间结点(快慢指针问题) &#x1f4ab;链接3&#xff1a;leetcode 206.反转链表 &#x1f4ab;链接4&#xff1a;leetcode 203.移除链…

蓝牙Beacon+Loa网关推出人员隔离监管解决方案

三年新冠已经过去&#xff0c;以空间换时间的防疫策略让疑似、确诊、有接触史人员得以有效控制&#xff0c;其中居家隔离的防疫措施对新冠的防控是行之有效的。 不过&#xff0c;在“画地为牢”的隔离区也有些需隔离观察人员私自外出&#xff0c;对防疫工作带来相当程度上的影…

数据库性能测试报告总结模板

目录 1计划概述 2参考资料 3术语解释 4系统简介 5测试环境 6测试指标 7测试工具和测试策略 8测试数据收集 9测试结果数据以及截图 9.1Jmeter性能指标 9.2硬件指标图 10 测试结论 需要完整报告模板记得文章末尾找我哦。 1计划概述 目的&#xff1a;找出系统潜在的…

Android Studio中配置aliyun maven库

Android Studio中配置aliyun maven库 在项目的根build.gradle里面&#xff08;不是module&#xff09;buildscriptde对应位置添加配置&#xff1a; buildscript {repositories {maven {url http://maven.aliyun.com/nexus/content/groups/public/allowInsecureProtocol true…

深入了解gradio库的Interpretation模块

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

解码大数据时代的信息安全:低代码开发平台的先锋之道

前言 随着大数据时代的到来&#xff0c;信息安全成为了不可忽视的重要议题。随之而来的是技术的迅速发展和创新&#xff0c;为信息安全领域带来了挑战&#xff0c;也为其提供了前所未有的机遇。在这个背景下&#xff0c;低代码开发平台作为一种创新的解决方案崭露头角&#xff…

速看,多设备上使用 WhatsApp的最完整指南

速看&#xff01;多设备上使用 WhatsApp的最完整指南&#xff01; 在过去的几年里&#xff0c;WhatsApp一直在不断更新。最近它正在推出一项新功能&#xff1a;允许移动和非手机设备使用该服务&#xff0c;而不需要将注册的手机连接到互联网。也就是说&#xff0c;您可以不再需…

cancal 同步mysql数据到es中

1.环境&#xff1a; windocs service2012 、 jdk版本1.8 、canal版本1.5、mysql版本5.7、 注意&#xff1a;canal版本1.5需要的jdk是1.8 如果你下载的是canal1.6&#xff0c;jdk是1.8&#xff0c;那样会报错。 下载地址 Releases alibaba/canal GitHub 下载并上传到服…

CAP结构体之字节对齐

&#x1f345; 我是蚂蚁小兵&#xff0c;专注于车载诊断领域&#xff0c;尤其擅长于对CANoe工具的使用&#x1f345; 寻找组织 &#xff0c;答疑解惑&#xff0c;摸鱼聊天&#xff0c;博客源码&#xff0c;点击加入&#x1f449;【相亲相爱一家人】&#x1f345; 玩转CANoe&…

No10.精选前端面试题,享受每天的挑战和学习

文章目录 Linux 中五种 IO 模型四次挥手之后为什么还要等待 2mslcookie 和 session 的区别是什么tcp 怎么保证可靠性css实现图片自适应宽高的几种方法 Linux 中五种 IO 模型 在 Linux 中&#xff0c;常见的五种 I/O&#xff08;Input/Output&#xff09;模型包括&#xff1a; …

机器学习19:多类别神经网络-Multi-Class Neural Networks

在【机器学习12&#xff1a;分类 Classification】一文中&#xff0c;笔者介绍了二元分类模型&#xff0c;它可以在两个可能的选择之一之间进行选择&#xff0c;例如&#xff1a; 电子邮件是垃圾邮件还是非垃圾邮件。肿瘤是恶性的或良性的。 在本文中&#xff0c;我们将研究多类…

将ChatGPT变成Midjourney提示生成器

已经有人总结过可以让ChatGPT作为Midjourney图像生成的模板。在本文中&#xff0c;我们将展示如何根据个人用例创建这些提示&#xff0c;这可以让ChatGPT生成的提示可控性更高。 选择提示模板 Midjourney的模板结构性很强&#xff0c;所以我们这里使用一下的结构&#xff1a; …

rsync远程同步(可爱可抵漫长岁月)

文章目录 一、简介二、部署rsync主客服务器1.关闭防火墙&#xff08;真的老生常谈了 一生之敌&#xff01;&#xff09;2.建立/etc/rsyncd.conf 配置文件3.客户端配置4.发起端配置 rsyncinotify 三、拓展使用rsync来实现快速删除大量文件。 一、简介 什么是rsync&#xff1f; …

【Linux】Linux项目自动化构建工具-make/makefile

Linux项目自动化构建工具-make/makefile 什么是make/makefile&#xff1f;make/makefile的使用依赖关系依赖方法makefile是如何工作的&#xff1f;为什么要使用makefile呢&#xff1f;makefile是怎么做到的呢&#xff1f;make和make clean.PHONY&#xff1a;伪目标 特殊符号&am…