xd96dx Docs
  • c/c++
    • 网络编程
      • linux 网络
        • linux 网络io模型
        • Signal-Driven I/O Model(信号驱动)
        • Asynchronous I/O Model(异步IO)
      • IO多路复用
        • select 示例
        • poll 示例
        • epoll 示例
      • Reactor实例之 muduo 源码分析
    • stl实现
      • 容器(Containers)
        • Vector(动态数组)
        • List(双向链表)
        • Deque(二级动态数组)
  • 游戏开发
    • skynet 从demo到源码
      • server-client demo
      • skynet 源码分析-启动流程之初始化
      • skynet 源码分析-启动流程之创建service
      • skynet 源码分析-启动流程之线程池启动
Powered by GitBook
On this page
  1. c/c++
  2. 网络编程
  3. linux 网络

Signal-Driven I/O Model(信号驱动)

信号驱动I/O是通过内核发送信号(如SIGIO)来通知进程某个I/O操作已准备好,而不需要进程主动去检查文件描述符的状态。该模型通常用于异步通知I/O事件的发生,避免了轮询操作,从而减少了CPU的浪费。

code

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

#define PORT 8080

int sockfd;

// 信号处理函数
void sigio_handler(int signo) {
    char buffer[1024];
    int n;

    // 读取套接字数据
    n = read(sockfd, buffer, sizeof(buffer) - 1);
    if (n < 0) {
        if (errno == EAGAIN) {
            printf("No data available\n");
        } else {
            perror("Read error");
        }
        return;
    }
    buffer[n] = '\0';  // Null terminate the string
    printf("Received data: %s\n", buffer);
}

int main() {
    struct sockaddr_in server_addr;
    struct sigaction sa;

    // 创建一个套接字
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("Socket failed");
        exit(EXIT_FAILURE);
    }

    // 配置服务器地址
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(PORT);

    // 绑定套接字到端口
    if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        perror("Bind failed");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    // 设置套接字为非阻塞模式
    if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0) {
        perror("fcntl failed");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    // 设置套接字为异步I/O模式,信号SIGIO将在I/O事件发生时发送
    if (fcntl(sockfd, F_SETFL, FASYNC) < 0) {
        perror("fcntl failed");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    // 注册SIGIO信号处理函数
    sa.sa_handler = sigio_handler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_RESTART;
    if (sigaction(SIGIO, &sa, NULL) < 0) {
        perror("sigaction failed");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    // 启动监听
    if (listen(sockfd, 5) < 0) {
        perror("Listen failed");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    printf("Server listening on port %d...\n", PORT);

    // 服务器主循环,等待SIGIO信号
    while (1) {
        pause();  // 等待信号到达
    }

    close(sockfd);
    return 0;
}
  1. 代码中, 定义了 sigio_handler函数,用于处理SIGIO信号,当I/O操作准备好时,内核会发送此信号,并触发该函数,读取数据并进行处理

  2. fcntl(sockfd, F_SETFL, O_NONBLOCK):设置套接字为非阻塞模式 fcntl(sockfd, F_SETFL, FASYNC):使套接字支持异步I/O,进程可以通过信号接收I/O事件通知

  3. 通过sigaction注册处理SIGIO信号的回调函数。每当I/O事件发生时,内核会发送SIGIO信号,进程就会执行该信号处理函数

Previouslinux 网络io模型NextAsynchronous I/O Model(异步IO)

Last updated 4 months ago