网络模型之IO信号驱动IO模型

一、什么是信号驱动 IO

  信号驱动 I/O(Signal-Driven I/O) 是一种比较少见但很经典的 I/O 模型。它利用 Unix 信号机制,当 I/O 事件发生时,内核主动向进程发送信号通知。核心思想:当 socket 有数据时,内核向进程发送一个信号,进程在信号处理函数中进行读取。

常用信号:

SIGIO

流程:

进程注册 SIGIO 信号
        ↓
设置 socket 为异步模式
        ↓
当 socket 可读
        ↓
内核发送 SIGIO
        ↓
信号处理函数执行 recv()

特点:

  • 不需要轮询
  • 不需要阻塞等待
  • 内核主动通知

二、信号驱动 IO 工作流程

完整流程如下:

应用程序
    │
    │ 注册 SIGIO 信号处理函数
    │
    │ 设置 socket 为 O_ASYNC
    │
    │ 指定信号接收进程
    ▼
内核
    │
    │ 监听 socket
    │
    │ 数据到达
    │
    ▼
发送 SIGIO 信号
    │
    ▼
用户进程收到信号
    │
    ▼
信号处理函数执行
    │
    ▼
recv() 读取数据

在这里插入图片描述

三、需要的三个关键步骤

① 注册信号处理函数

signal(SIGIO, sigio_handler);

或者更安全:

sigaction(SIGIO, &act, NULL);

② 设置 socket 所属进程

fcntl(fd, F_SETOWN, getpid());

告诉内核:SIGIO 信号发给哪个进程

③ 开启异步通知

int flags = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, flags | O_ASYNC);

O_ASYNC 表示:

当 socket 有 IO 事件时
发送 SIGIO 信号

四、完整示例代码

1️⃣ 信号处理函数

void sigio_handler(int signo)
{
    char buf[1024];
    int n = recv(sockfd, buf, sizeof(buf), 0);

    if (n > 0)
    {
        printf("receive: %s\n", buf);
    }
}

2️⃣ 初始化 socket

int sockfd = socket(AF_INET, SOCK_STREAM, 0);

signal(SIGIO, sigio_handler);

fcntl(sockfd, F_SETOWN, getpid());

int flags = fcntl(sockfd, F_GETFL);
fcntl(sockfd, F_SETFL, flags | O_ASYNC);

3️⃣ 主线程

while (1)
{
    printf("doing other work...\n");
    sleep(1);
}

五、信号驱动 IO 的优点与缺点

优点:

  • 不需要轮询:CPU 不需要遍历 fd。
  • 不阻塞线程:程序可以继续执行其它逻辑。
  • 响应速度快:信号立即触发。

缺点:

  • 信号处理复杂:不能执行复杂逻辑、不能调用很多系统函数
  • 信号可能丢失:如果信号触发过快;如(SIGIO SIGIO SIGIO);可能只处理一次。
  • 可扩展性差:高并发服务器、多线程程序
  • 调试困难:信号是异步触发的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值