Linux信号与统一事件源

【Flink】FlinkCDC获取mysql数据时间类型差8小时时区解决方案 ​ 1、背景: 在我们使用FlinkCDC采集mysql数据的时候,日期类型是我们很常见的类型,但是FlinkCDC读取出来会和数据库的日期时间不一致,情况如下 FlinkCDC获取的数据中create_time字段1694597238000转换为时间戳2023-09-13 17:27:18,而数据库中原始数据如下,并没有到下午5点,这就导致了FlinkCDC读出来的时间和数据库中实际的时间不一致的情况,与数据库对比可以发现,这里的时间戳与数据库时间刚好相差了 8 个小时,在实际生产中这种情况是不 阅读详情

信号是一种异步事件,信号处理函数和程序的主循环是两条不同的执行路线。信号处理函数需要尽可能快地执行完毕,以确保信号不被屏蔽太久(为了避免一些竞态条件,信号在处理期间,系统不会再次触发它)。

一种典型的解决方案是:把信号的主要处理逻辑放到主循环中,而不是在信号处理函数中进行主要的逻辑处理。信号处理函数被触发时,只是简单地通知主循环程序接收到信号,并把信号值传递给主循环,主循环程序根据接收到的信号值执行目标信号对应的逻辑代码。

信号处理函数怎么把接收到的信号通知传递给主循环程序呢?可以利用管道:信号处理函数往管道写端写入信号值,主循环程序从管道的读端读出该信号。

解决了通知信号发生的动作,那么主循环程序又怎么知道管道上何时有数据可读呢?这需要监听,只需要用I/O复用系统调用赖监听管道的读端文件描述符上的可读事件。

以上的处理方法,就是:统一事件源:信号事件就能和其他I/O事件一样被处理了。

很多优秀的I/O框架库和后台服务器程序都统一处理信号和I/O事件,比如 libevent I/O框架库。

以下提供一个统一事件源的简单实现

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <pthread.h>
#include <signal.h>

#define MAX_EVENT_NUMBER 1024

static int pipefd[2];

int setnonblocking(int fd)
{
    int old_option = fcntl(fd, F_GETFL);
    int net_option = old_option | O_NONBLOCK;
    fcntl(fd, F_SETFL, new_option);
    return old_option;
}

void addfd(int epollfd, int fd)
{
    struct epoll_event event;
    event.data.fd = fd;
    event.events = EPOLLIN | EPOLLET;
    epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event);
    setnonblocking(fd);
}

/*信号处理函数,通过管道通知主程序*/
void sig_handler(int sig)
{
    int save_errno = errno;
    int msg = sig;
    send(pipefd[1],(char*)&msg, 1, 0);
    errno = save_errno;
}

void addsig(int sig)
{
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = sig_handler;
    sa.sa_flags |= SA_RESTART;
    sigfillset(&sa.sa_mask);
    assert(sigaction(sig, &sa, NULL)!=-1);
}

int main(int argc, char** argv)
{
    if (argc <= 2) {
        printf("usage:%s <ip> <port>\n",basename(argv[0]));
        return 1;
    }

    const char* ip = argv[1];
    int port = atoi(argv[2]);

    int ret = 0;
    struct sockaddr_in svr_addr;
    memset(&svr_addr, 0, sizeof(svr_addr));
    svr_addr.sin_family = AF_INET;
    inet_pton(AF_INET, ip, &svr_addr.sin_addr);
    svr_addr.sin_port = htons(port);
    
    int listenfd = socket(AF_INET, SOCK_STREAM, 0);
    bind(listenfd, (struct sockaddr*)&svr_addr, sizeof(svr_addr));

    listen(listenfd, 5);

    epoll_event events[MAX_EVENT_NUMBER];
    int epollfd = epoll_create(5);
    addfd(epollfd, listenfd);

    /*使用socketpair创建管道,也就是UNIX域套接字*/
    socketpair(AF_UNIX, SOCK_STREAM, 0, pipefd);
    setnonblocking(pipefd[1]);
    addfd(epollfd,pipefd[0]);

    addsig(SIGHUP);
    addsig(SIGCHLD);
    addsig(SIGTERM);
    addsig(SIGINT);

    bool stop_server = false;
    while (!stop_server) {
        int number = epoll_wait(epollfd, events, MAX_EVENT_NUMBER, -1);
        if ((number < 0) && (errno != EINTR)) {
            printf("epoll fails!\n");
            break;
        }
        int i = 0;
        for (;i < number;i++) {
            int sockfd = events[i].data.fd;
            if (sockfd == listenfd) {
                struct sockaddr_in cli_addr;
                socklen_t cli_addr_len = sizeof(cli_addr);
                int clifd = accept(listenfd, (struct sockaddr*)cli_addr, &cli_addr_len);
                addfd(epollfd, clifd);
            }
            else if ( (sockfd == pipefd[0]) && (events[i].events & EPOLLIN) ) {
                int sig;
                char signals[1024];
                ret = recv(pipefd[0], signals, sizeof(signals), 0);
                if (ret == -1) {
                    continue;
                }
                else if(ret == 0) {
                    continue;
                }
                else {
                    /*每个信号值占1字节,所以按字节逐个接收信号,以SIGTERM为例,来说明如何安全地终止服务器主循环*/
                    int i = 0;
                    for (; i < ret; ++i) {
                        switch(signals[i]) 
                        {
                            case SIGCHLD:
                            case SIGHUP:
                            {
                                continue;
                            }
                            case SIGTERM:
                            case SIGINT:
                            {
                                stop_server = true;
                            }
                        }
                    }
                }
            }
            else {
                //这部分处理其他socket获取的数据
            }
        }
    }
    printf("close fds\n");
    close(listenfd);
    close(pipefd[0]);
    close(pipefd[1]);
    return 0;
}


以上内容,来自《Linux高性能服务器编程》,这是一本很不错的书,推荐大家阅读


汇川H5U PLC 实现直线插补、圆弧插补、直线圆弧混合连续插补 使用汇川H5UPLC实现直线插补,圆弧插补,直线圆弧混合路径插补,通过示教可以走出复杂的路径,仅供参考学习。 阅读详情

相关推荐

clumsy一款模拟弱网的工具

利用封装 Winodws Filtering Platform 的WinDivert 库, clumsy 能实时的将系统接收和发出的网络数据包拦截下来,人工的造成延迟,掉包和篡改操作后再进行发送。无论你是要重现网络异常造成的程序错误,还是评估你的应用程序在不良网络状况下的表现,clumsy 都能让你在不需要额外添加代码的情况下,在系统层次帮你达到想要的效果。

klb5555的专栏 2551

再玩下linux中的的epoll函数------可以用任何描述符号fd而不限于网络socket

      之前玩过epoll,  再来看下, 其实也很简单:#include &lt;unistd.h&gt; #include &lt;sys/types.h&gt; #include &lt;sys/socket.h&gt; #include &lt;netdb.h&gt; #include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; #include...

认知 行动 坚持 8700

把对讲门铃(控制底楼铁门)接入米家服务器

今天讲个跟SDR或者无人机无关的东西,技术含量不高,但是方便了我的生活。 现在家门有智能锁,汽车也可以远程解锁发动,NFC门禁也可以用某些手机复制,唯独楼下的铁门,必须用老式对讲门铃控制。 也就是说其它钥匙都可以不带,就剩这个钥匙还必须随身携带。 另外有时候人不在家,不能开楼下铁门,快递员也没法把东西送上楼。 ......

老邵的开源世界 6549

【Linux学习】epoll详解

什么是epoll epoll是什么?按照man手册的说法:是为处理大批量句柄而作了改进的poll。当然,这不是2.6内核才有的,它是在2.5.44内核中被引进的(epoll(4) is a new API introduced in Linux kernel 2.5.44),它几乎具备了之前所说的一切优点,被公认为Linux2.6下性能最好的多路I/O就绪通知方法。 epoll的相关系...

844604778 2277

世界职业院校技能大赛商贸赛道项目参考逐字稿一

商贸赛道“智选优品”—基于大数据与AI驱动的跨境电商平台项目参考逐字稿您订阅本专栏后即可`永久享有所有文章的查阅权`,希望我们更新的参考资料能帮助到您。如果您需要我们团队赋能培训可联系我(企业一线工程师及国一获奖选手在线培训支持:每周直播精讲(可回放,支持弹幕答疑)、代码Review+技术售后(拉群随时问,12h内响应)、④路演PPT+答辩话术一对一点评,评委视角提前彩排、适合:中职/高职赛项选手、指导老师带队、校企工作室、整校打包另谈(可开发票))

我是网络安全兼技能大赛工程师,专注网络安全技术学习与技能大赛实战!持续分享最新的技术文章,帮你少走弯路,一起在技术赛道上进步~ 1585

Linux多进程(三) 信号&信号集与统一事件源

信号是由用户、系统或者进程发送给目标进程的信息,以通知目标进程某个状态的改变或系统异常。

Lyajpunov的博客 1262

YOLOv8【第一章:基础入门篇·第2节】一文搞定,数据集制作与标注完全指南!

🏆 本文收录于 《YOLOv8实战:从入门到深度优化》 专栏,该专栏专注于分享我在YOLOv8目标检测模型中的实战经验,涵盖从入门基础到深度优化的全方位解决方案。无论你是计算机视觉的新手,还是具有多年深度学习经验的专家,本专栏都将为你提供高效、可复现的技术方案,助你掌握YOLOv8的核心技术,提升目标检测性能,突破瓶颈,优化模型,并加速项目开发🚀!

**My Coding Family** 1506

epoll的一些发现(linux | c | cpp)(一)

1.之前使用模型是epoll+多线程

Reazon 1151

SAP CDS View association 的工作原理,与数据库传统 join 操作的区别讲解

笔者前一篇教程,介绍了 SAP CDS View 里如何创建 association:本文就来一一对这些问题进行解答。首先我们来研究如何消费创建好的 SAP CDS View 中的 association 数据。在上图 ABAP Development Tool 里展示的 CDS View 界面,点击 F8 快捷键,进入 Data Preview 即数据预览界面。我们随便选中一条行项目,右键,发现右键菜单里,赫然有一条的菜单项。看来这个功能肯定和 association 相关了。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1008

数据集FFHQ和LSUN介绍【包含FFHQ1024,515,256,128分辨率图像获取方法】

FFHQ全称Flickr-Faces-High-Quality(Flickr-Faces-HQ),最初是作为生成式对抗网络(GAN)的基准创建的,也用于StyleGAN的训练数据集中,并由英伟达于2019年开源。CVPR_2019Flickr-Faces-HQ (FFHQ)其由 70,000 张分辨率为 1024×1024 的高质量 PNG 图像组成,在年龄、种族和图像背景方面包含相当大的差异。它对眼镜、太阳镜、帽子等配饰也有很好的覆盖。

zik的博客 3979

Linux 信号 --- 统一事件源

信号是一中异步事件:信号处理函数和程序的主循环是两条不同的执行路线。信号处理函数需要尽可能快地执行完毕,以确保该信 号不会被屏蔽(信号在处理期间,系统不会再触发它)太久。一种典型的解决方案是:把信号的主要处理逻辑放到程序的朱循环中,当信号函数被触发时,他只是简单地通知主循环程序接收信号,并把信号值传递给主循环,主循环再根据接收到的信号值执行目标信号对应的逻辑代码。 信号处理函数通常...

u013827488的博客 664

智能制造之物料详解

制造业业务系统中的物料流转贯穿需求、采购、生产到交付全流程,各系统协同实现精准追踪。需求阶段由CRM/ERP/PLM生成物料计划;采购入库阶段SCM/WMS/QMS完成采购质检;生产阶段MES/APS协调领料加工;成品交付阶段WMS/SCM处理出库物流。整个流程以BOM为蓝图,ERP为调度中心,通过数据联动实现物料状态、位置和数量的全链路可追溯。

cdfunlove的博客 654

Linux信号(包含统一事件源的代码)

本篇文章到这里就结束了!!!!希望可以帮助大家理解~~~~

2503_93247646的博客 326

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Linux服务器编程实践146-I/O复用与信号的结合:统一事件源的实现

本文探讨了Linux服务器编程中统一处理I/O事件和信号事件的"统一事件源"技术。通过管道将信号事件转化为可被I/O复用监听的文件描述符事件,实现了信号处理与I/O处理共享同一事件循环的机制。文章详细介绍了该技术的实现原理和步骤:创建管道、注册信号处理函数、将管道读端加入epoll监听框架,并提供了完整的代码示例。该方案解决了传统分离式处理导致的逻辑分散、竞态条件等问题,具有代码集中、效率高、支持批量信号处理等优势,适用于Web服务器、数据库服务器等各种高性能Linux服务器场景。

文石_2009的博客 622

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Linux网络编程 | 信号 :信号函数、信号集、统一事件源 、网络编程相关信号

文章目录信号函数信号集统一事件源网络编程相关信号 Linux 进程信号:信号的概念、生命周期、产生流程、阻塞 在半年前我写过一篇博客介绍了Linux中信号的概念以及处理流程,这次再来深入的讲一讲信号的具体使用方法以及在网络编程中的具体应用。 信号函数 要想为一个信号设置处理函数,可以使用以下两个系统调用。 signal signal函数的使用非常简单,只需要直接指定信号类型以及处理的方法即可 #include <signal.h> typedef void (*sighandler_

凌桓丶的博客 1018

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

统一事件源

信号 对于Linux网络编程来说,信号是一个永远绕不过的话题。最近在做负载均衡项目,用到一些信号方面的知识。尤其是统一事件源这种处理逻辑,目前还不是很熟悉。所以写篇博客记录下,算是回炉再细致地看一看。本文参考《Linux高性能服务器编程》的第十章。 信号是由用户、系统或者进程发送给目标进程的信息,以通知目标进程某个状态的改变或系统异常。 信号的产生条件 对于前台进程,用户在终端输入特殊字符来发送...

古渡廊桥 621

Linux系统下信号以及常用API总结(signal/sigaction/信号集函数)

一、信号基础知识 >*信号的产生: 按键产生 系统调用产生 软件条件产生 硬件条件产生 命令产生 概念: 未决,产生于递达之间状态 递达:产生并且递达到进程,直接被内核处理掉 >*信号的处理: (1)忽略此信号。除了SIGKILL、SIGSTOP (2)捕捉信号。通知内核在某种信号发生时,调用一个用户处理函数。 ...

qq_36316285的博客 722

Linux 信号再探:统一事件源,信号的处理机制,异步—同步

信号是一种异步事件,信号处理函数和程序的主循环是两条不同的执行路线。很显然,信号处理函数需要尽可能快地执行完毕,以确保该信号不会被屏蔽(为了避免一些竞态条件,信号在处理期间,系统不会再次触发它)太久。 一种典型地解决方案是:把信号地主要处理逻辑放到程序的主循环中,当信号处理函数被触发时,它只是简单地通知主循环程序接收到信号,并把信号传递给主循环,主循环再根据接收到的信号值执行目标信号对应的逻辑代码...

CLZHIT的博客 436

Linux服务器编程实践157-统一事件源:将信号事件与I/O事件合并处理

本文介绍了Linux服务器编程中统一事件源的设计模式,解决了传统分离式处理I/O事件与信号事件导致的代码复杂、资源竞争等问题。通过管道将信号事件转换为I/O事件,在同一个事件循环中处理所有事件。文章详细阐述了实现原理、关键技术细节,并提供了完整代码示例,包括管道的创建与使用、信号处理函数设计、epoll边缘触发模式等。此外,还给出性能优化建议、实际应用场景和常见问题排查方法。统一事件源模式简化了服务器架构,提高了稳定性和可维护性,适用于多进程服务器、配置热加载、优雅退出等场景。

文石_2009的博客 1104

linux 信号发送源,Linux信号处理统一事件源

#include #include #include #include #include #include #include #include #include #include #include #include #include #include #define MAX_EVENT_NUMBER 1024static int pipefd[2];int setnonblocking( int ...

weixin_29159711的博客 161

【Linux高性能服务器编程】信号处理方法之统一事件源

统一事件源,即将信号和其他事件一样进行处理。 具体就是信号处理函数使用管道将信号传递给主循环,信号处理函数往管道的写端写入信号值,主循环则从管道的读端读出信号值,使用I/O复用系统调用来监听管道读端的可读事件,这样信号事件与其他文件描述符都可以通过epoll来监测,从而实现统一处理。

qq_61635026的博客 1050

linux 关闭setitimer_Linux服务器编程【3】信号

本文主要介绍网络编程中相关的信号以及处理 (持续更新....如何发送信号在linux里,一个进程通过kill函数发送给其他进程的信号#include <sys/types.h> #include <signal.h> int kill(pid_t pid, int sig);pid参数含义pid参数含义pid < 0信号发送给PID为pid的进程pid = 0信号发送...

weixin_39614322的博客 90

Linux信号处理统一事件源

#include #include #include #include #include #include #include #include #include #include #include #include #include #include #define MAX_EVENT_NUMBER 1024 static int pipefd[2]; int se

qisefengzheng的专栏 总有一天你将破蛹而出 543

Linux 信号深度解析

信号(Signal)本质上是 Linux 内核向进程发送的异步事件通知,用于告知进程发生了特定事件(如用户按下Ctrl+C、进程访问非法内存、定时器到期等)。每个信号都有唯一的编号和默认行为,进程可以通过自定义处理函数修改信号的默认响应逻辑。

apolloyhl的博客 937

《Linux高性能服务器编程》第十章 信号

Github代码地址 第 10 章 信号10.1 Linux 信号概述10.1.1 发送信号10.1.2 信号处理方式10.1.3 Linux 信号10.1.4 中断系统调用10.2 信号函数10.2.1 signal 系统调用10.2.2 sigaction 系统调用10.3 信号集10.3.1 信号集函数10.3.2 进程信号掩码10.3.3 被挂起的信号10.4 同一事件源 持续更新中~ 第 10 章 信号 信号是由用户、系统或者进程发送给目标进程的信息,以通知目标进程某个状态的改变或系统异常。

qq_39274501的博客 303
上一篇: Linux mysql C 编程——connector/c
下一篇: php添加模块
amghost
博客等级 码龄15年 21粉丝 44原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值