UNP函数笔记十五: 信号驱动式I/O

58 篇文章 0 订阅
49 篇文章 0 订阅

第二十五章  信号驱动式I/O:


示例:

#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/socket.h>

#include "err_exit.h"
#include "my_signal.h"

static int  sockfd;

#define    QSIZE       8  /* size of input queue */
#define    MAXDG    4096  /* max datagram size */

typedef struct {
    void            * dg_data;   /* ptr to actual datagram */
    size_t            dg_len;    /* length of datagram */
    struct sockaddr * dg_sa;     /* ptr to sockaddr{} w/client's address */
    socklen_t         dg_salen;  /* length of sockaddr{} */
} DG;

static DG     dg[QSIZE];         /* queue of datagrams to process */
static long   cntread[QSIZE+1];  /* diagnostic counter */

static int       iget;    /* next one for main loop to process */
static int       iput;    /* next one for signal handler to read into */
static int       nqueue;  /* on queue for main loop to process */
static socklen_t clilen;  /* max length of sockaddr{} */

void 
sig_io(int signo)
{
    ssize_t   len;
    int       nread;
    DG      * ptr;

    for (nread = 0; ; ) {
        if (nqueue >= QSIZE) {
            printf("receive overflow\n");
            exit(1);
        }

        ptr = &dg[iput];
        ptr->dg_salen = clilen;
        len = recvfrom(sockfd, ptr->dg_data, MAXDG, 0,
                       ptr->dg_sa, &ptr->dg_salen);
        if (len < 0) {
            if (errno == EWOULDBLOCK) {
                break;  /* all done; no more queued to read */
            }
            else {
                err_exit("recvfrom error");
            }
        }
        ptr->dg_len = len;

        nread++;
        nqueue++;
        if (++iput >= QSIZE) {
            iput = 0;
        }
    }
    cntread[nread]++;  /* histogram of datagrams read per signal */
}

void 
sig_hup(int signo)
{
    int  i;

    for (i = 0; i <= QSIZE; i++) {
        printf("cntread[%d] = %ld\n", i, cntread[i]);
    }
}

void 
dg_echo(int sockfd_arg, struct sockaddr * pcliaddr, socklen_t clilen_arg)
{
    int        i;
    const int  on = 1;
    sigset_t   zeromask;
    sigset_t   newmask;
    sigset_t   oldmask;

    sockfd = sockfd_arg;
    clilen = clilen_arg;

    for (i = 0; i < QSIZE; i++) {  /* init queue of buffers */
        if ((dg[i].dg_data = malloc(MAXDG)) == NULL) {
            err_exit("malloc error");
        }
        if ((dg[i].dg_sa = (struct sockaddr *)malloc(clilen)) == NULL) {
            err_exit("malloc error");
        }
        dg[i].dg_salen = clilen;
    }
    iget = iput = nqueue = 0;

    if (my_signal(SIGHUP, sig_hup) == SIG_ERR) {
        err_exit("my_signal error");
    }
    if (my_signal(SIGIO, sig_io) == SIG_ERR) {
        err_exit("my_signal error");
    }
    if (fcntl(sockfd, F_SETOWN, getpid()) == -1) {
        err_exit("fcntl error");
    }
    if (ioctl(sockfd, FIOASYNC, &on) == -1) {
        err_exit("ioctl error");
    }
    if (ioctl(sockfd, FIONBIO, &on) == -1) {
        err_exit("ioctl error");
    }

    /* init three signal sets */
    if (sigemptyset(&zeromask) == -1) {
        err_exit("sigemptyset error");
    }
    if (sigemptyset(&oldmask) == -1) {
        err_exit("sigemptyset error");
    }
    if (sigemptyset(&newmask) == -1) {
        err_exit("sigemptyset error");
    }
    /* signal we want to block */
    if (sigaddset(&newmask, SIGIO) == -1) {
        err_exit("sigaddset error");
    }

    if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) == -1) {
        err_exit("sigprocmask error");
    }
    for ( ; ; ) {
        while (nqueue == 0) {
            sigsuspend(&zeromask);  /* wait for datagram to process */
        }

        /* unblock SIGIO */
        if (sigprocmask(SIG_SETMASK, &oldmask, NULL) == -1) {
            err_exit("sigprocmask error");
        }
        if (sendto(sockfd, dg[iget].dg_data, dg[iget].dg_len, 0,
                   dg[iget].dg_sa, dg[iget].dg_salen) == -1) {
            err_exit("sendto error");
        }

        if (++iget >= QSIZE) {
            iget = 0;
        }

        /* block SIGIO */
        if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) == -1) {
            err_exit("sigprocmask error");
        }
        nqueue--;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值