令牌桶的实现 使用sigaction 屏蔽非内核发出的信号

mytbf.h

#ifndef MYTBF_H__
#define MYTBF_H__

#define MYTBF_MAX   1024


typedef void mytbf_t;
mytbf_t * mytbf_init(int cps,int burst);

int mytbf_fetchtoken(mytbf_t* ,int);
int mytbf_returntoken(mytbf_t*,int);
int mytbf_destroy(mytbf_t *);

#endif

mytbf.c

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include "mytbf.h"
#include <sys/time.h>

struct mytbf_st
{
    
    int cps;
    int token;
    int burst;

    int pos;
};
static struct mytbf_st* job[MYTBF_MAX];
static int inited = 0;
//typedef void(*sighandler_t)(int);
//static sighandler_t alrm_handler_save;
struct sigaction alrm_sigaction_save;
static void alrm_sigaction(int signo,siginfo_t* info,void*)
{
	if( info->si_code != SI_KERNEL)
	{
		return ;
	}
    for( int i = 0; i < MYTBF_MAX; i++)
    {
        if( job[i] != NULL)
        {
            job[i]->token += job[i]->cps;
            if( job[i]->token > job[i]->burst)
                job[i]->token = job[i]->burst;
        }
    }
   // alarm(1);
}
static void module_unload()
{
   // signal(SIGALRM,alrm_handler_save);
   // alarm(0);

    sigaction(SIGALRM,&alrm_sigaction_save,NULL);
    
	struct itimerval timeval;
	timeval.it_interval.tv_sec = 0;
	timeval.it_interval.tv_usec = 0;
	timeval.it_value.tv_sec = 0;
	timeval.it_value.tv_usec = 0;
	setitimer(ITIMER_REAL,&timeval,NULL);
    for( int i = 0; i < MYTBF_MAX;i++)
    {
        free(job[i]);
    }

}
static void module_load()
{
  //  alrm_handler_save =  signal(SIGALRM,alrm_handler);
  //  alarm(1);
	struct sigaction sa;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = SA_SIGINFO;
	sa.sa_sigaction = alrm_sigaction;
    sigaction(SIGALRM,&sa,&alrm_sigaction_save);
    
	struct itimerval timeval;
	timeval.it_interval.tv_sec = 1;
	timeval.it_interval.tv_usec = 0;
	timeval.it_value.tv_sec = 1;
	timeval.it_value.tv_usec = 0;
	setitimer(ITIMER_REAL,&timeval,NULL);
	atexit(module_unload);
}
static int get_free_pos(void)

{
    int i = 0;
    for( ;i < MYTBF_MAX; i++)
    {
        if( job[i] == NULL)
        {
            
            return i;
        }
    }
    return -1;
}
mytbf_t * mytbf_init(int cps,int burst)
{
    struct mytbf_st* me;
    if( !inited)
    {
        module_load();
        inited = 1;
    }
    int pos = get_free_pos();
    if(pos <0)
        return NULL;
    me = malloc(sizeof(*me));
    if( me == NULL)
    {
        return NULL;
    }


    me->token= 0;
    me->cps = cps;
    me->burst = burst;
    me->pos = pos;
    job[pos] = me;
    return me;
}
static int min(int a,int b)
{
    return a > b? b: a;
}
int mytbf_fetchtoken(mytbf_t*ptr ,int size)
{
    struct mytbf_st * me = ptr;
       if( size <=0)
       {
           return -EINVAL;
       }

    while(me->token <=0)
        pause();
      int n = min(me->token , size);
        me->token -= n;
        return n;
}

int mytbf_returntoken(mytbf_t*ptr,int size)
{
    struct mytbf_st * me = ptr;
    if( size <= 0)
    {
        return -EINVAL;
    }
    me->token += size;
    if( me->token > me->burst)
        me->token = me->burst;
        return size;
}
int mytbf_destroy(mytbf_t *ptr)
{
     struct mytbf_st * me = ptr;
     job[me->pos] = NULL;
     free(ptr);
     return 0;
}

 main.c

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <stdbool.h>
#include <errno.h>
#include <fcntl.h>
#define CPS     100
#define BUFFSIZE  10240
#define  BURST   1000
volatile static int token =0;

#include "mytbf.h"
int main( int argc, char** argv)
{


    if( argc < 2)
    {
        fprintf(stderr,"Usage:%s <src_file> \n",argv[0]);

        exit(0);
    }
    

    int sfd,dfd = 1;
    char buff[BUFFSIZE];
    mytbf_t *tbf;
    int size;
    tbf = mytbf_init(CPS,BURST);
    if( tbf == NULL)
    {   
        fprintf(stderr,"mytbf_init() error");
        exit(0);
    }
    if( (sfd = open(argv[1],O_RDONLY))<0)
    {
        perror("open()");
        exit(1);
    }
    while(1)
    {
      size = mytbf_fetchtoken(tbf,BUFFSIZE);
      ssize_t read_size;
      errno =0;
      while((read_size =  read(sfd,buff,size)) < 0)
      {
       
            if( errno == EINTR)
          {
                continue;
         }
      }
      if( size - read_size > 0)
           mytbf_returntoken(tbf,size - read_size);
  
    
//      read_size =  read(sfd,buff,BUFFSIZE);
      
      if( read_size == 0)
          break;
      if( read_size < 0)
          break;
      ssize_t write_size = 0;
      errno = 0;
      while( read_size)
      {
          ssize_t ret = write(dfd,buff+write_size,read_size);
          if( ret < 0 && errno != EINTR)
          {
              break;
          }
          errno =0;
          read_size -= ret;
      }
    }


    mytbf_destroy(tbf);
    close(sfd);
    exit(0);

}

makefile

all:mytbf

mytbf: main.o mytbf.o
	gcc $^ -o $@

clean:
	rm *.o mytbf

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值