令牌桶C语言代码实现
令牌桶实例
令牌桶三要素
cps 每秒钟传输字节数
burst 令牌桶内最多能传输的字节数,token的最大值
token 令牌的个数
之前是一个令牌(token)对应一个字节,现在将一个token变为一个cps,cps是解码速率,每攒到一个令牌,就token+=cps
不同的速率使用不同的令牌桶,将令牌桶存储在一个数组中。
代码
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 <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>#include "mytbf.h"typedef void (*sighandler_t)(int);//将令牌桶的数据结构存在数组中
static struct mytbf_st * job[MYTBF_MAX];
static int inited = 0;
#define MIN(A,B) (A < B ? A : B)
static sighandler_t alrm_handler_save;/*每个token代表一个字节,cps代表解码速率,burst应该是cps的倍数,token=token+cps*/
//这是令牌桶的数据结构,这个数据结构存在数组中
struct mytbf_st
{int cps; //每秒钟传输的字节数int burst; //令牌桶中令牌最大数量int token; //令牌的个数int pos; //记录令牌桶在数组的位置下标
};//信号捕捉函数
static void alrm_handler(int s)
{alarm(1);//为数组中的令牌桶中的令牌做累计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;}}
}
//关闭时钟发送信号,恢复
static void module_unload(void)
{int i;//恢复SIGALRM到之前的功能signal(SIGALRM,alrm_handler_save);//取消时钟发送信号alarm(0);//释放令牌桶for(i = 0;i < MYTBF_MAX;i++){free(job[i]);}}
//第一次发时钟信号的函数
static void module_load(void)
{//signal的返回值是注册新的行为之前的行为alrm_handler_save = signal(SIGALRM,alrm_handler);alarm(1);//注册钩子函数,这个不是函数调用,而是当调用exit的时候才会调用atexit(module_unload);
}static int get_free_pos(void)
{int i = 0;for(i = 0;i < MYTBF_MAX; i++){if(job[i] == NULL)return i;}return -1;
}mytbf_t *mytbf_init(int cps,int burst)
{int pos = 0;struct mytbf_st *me;//在数组中找到空位下标pospos = get_free_pos();if(pos < 0){return NULL;}if( !inited ){module_load();inited = 1;}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;
}//取令牌
int mytbf_fetchtoken(mytbf_t *ptr ,int size)
{int n;struct mytbf_st *me = ptr;if(size <= 0)return -1;while(me->token <= 0)pause();//当要取的令牌数大于最大令牌数量,给最大令牌数量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 -1;me->token +=size;if(me->token > me->burst)me->token = me->burst;return size;
}//销毁令牌桶
int mytbf_destroy(mytbf_t *ptr)
{ //因为mytbf_t 是void类型,转换下struct mytbf_st *me = ptr;job[me->pos] = NULL;free(me);return 0;
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include "mytbf.h"#define CPS 10
#define BUFSIZE 1024
#define BURST 100int main(int argc,char**argv)
{int sfd,dfd = 1;int size,errnor;char buf[BUFSIZE];int len,ret,pos;mytbf_t * tbf;if(argc < 2){fprintf(stderr,"Usage ....\n");exit(1);}//初始化令牌桶tbf = mytbf_init(CPS,BURST);//打开要读取的文件do{sfd = open(argv[1],O_RDONLY);if(sfd < 0){if(errno != EINTR){perror("open()");exit(1);}}}while(sfd < 0);while(1){size = mytbf_fetchtoken(tbf,BUFSIZE);if(size < 0){fprintf(stderr,"mytbf_fetchtoken is error\n");exit(1);}while((len = read(sfd,buf,size)) < 0){if(errno == EINTR)continue;perror("read()");break;}if(len == 0)break;//判断令牌是否用完if(size - len > 0)mytbf_returntoken(tbf,size-len);pos = 0;//使用循环读,因为是向终端写while(len > 0){ret = write(dfd,buf+pos,len);if(ret < 0){ //假错,继续读if(ret == EINTR)continue;perror("write()");exit(1);}pos += ret;len -= ret;}}mytbf_destroy(tbf);exit(0);
}
makefile
all:mytbf
mytbf:main.o mytbf.ogcc $^ -o $@
clean:rm *.o mytbf
相关文章:
令牌桶C语言代码实现
令牌桶实例 令牌桶三要素 cps 每秒钟传输字节数 burst 令牌桶内最多能传输的字节数,token的最大值 token 令牌的个数 之前是一个令牌(token)对应一个字节,现在将一个token变为一个cps,cps是解码速率,每攒到一个令牌ÿ…...
Mybatis 建立依赖失败:报错Dependency ‘mysql:mysql-connector-java:8.0.28‘ not found
Mybatis 建立依赖失败:报错Dependency ‘mysql:mysql-connector-java:8.0.28’ not found 解决办法: 写完依赖代码,直接重构,下载依赖。 图片: 和 UUID(Universally Unique Identifier)都是用于生成唯一标识符的方法,但它们在实现和适用场景上存在一些区别。 雪花算法: 雪花算法是Twitter开发的一种分布式ID生成算法…...
docker之DockerFile与网络
目录 DockerFile 构建步骤 基础知识 指令 实战:构建自己的centos 第一步:编写dockerfile文件 第二步:构建镜像文件 docker网络 原理 功能 网络模式 host模式 container模式 none模式 bridge模式 DockerFile dockerfile 是用来…...
知识蒸馏开山之作(部分解读)—Distilling the Knowledge in a Neural Network
1、蒸馏温度T 正常的模型学习到的就是在正确的类别上得到最大的概率,但是不正确的分类上也会得到一些概率尽管有时这些概率很小,但是在这些不正确的分类中,有一些分类的可能性仍然是其他类别的很多倍。但是对这些非正确类别的预测概率也能反…...
centos 7 安装 docker-compose curl 设置代理
sudo curl -x “http://192.168.1.2:3128” 需要验证的代理 sudo curl -x “http://username:password192.168.1.2:3128” 1.下载 sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/lo…...
3D姿态相关的损失函数
loss_mpjpe: 计算预测3D关键点与真值之间的平均距离误差(MPJPE)。 loss_n_mpjpe: 计算去除尺度后预测3D关键点误差(N-MPJPE),评估结构误差。 loss_velocity: 计算3D关键点的速度/移动的误差,评估运动的平滑程度。 loss_limb_var: 计算肢体长度的方差,引导生成合理的肢体长度…...
ChatGPT取代人类仍然是空想?有没有一种可能是AI在迷惑人类
ChatGPT自从去年发布以来,就掀起了这些大语言模型将如何颠覆一切的激烈讨论,从为学生写作文、输出SEO文章,甚至取代谷歌成为世界上最受欢迎的搜索引擎,影响领域无所不包,甚至可能取代编剧、小说家和音乐家等从事创意工…...
基于swing的旅游管理系统java jsp旅行团信息mysql源代码
本项目为前几天收费帮学妹做的一个项目,Java EE JSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。 一、项目描述 基于swing的旅游管理系统 系统有1权限:管…...
Windows wsl2支持systemd
背景 很多Linux发行版都是使用systemd来管理程序进程,但是在WSL中默认是用init来管理进程的。 为了符合长久的使用习惯,且省去不必要的学习成本,就在WSL的发行版(我这里安装的是Ubuntu20.04)中支持systemd࿰…...
NLP - 如何解决ModuleNotFoundError: No module named ‘jieba‘的问题
错误描述 在JUPYTER中,使用结巴分词,出错: ModuleNotFoundError: No module named jieba解决方案 在 Anaconda Prompt 中,执行以下指令(可以解决): pip install jieba -i https://pypi.tuna…...
Windows10上VS2022单步调试FFmpeg 4.2源码
之前在 https://blog.csdn.net/fengbingchun/article/details/103735560 介绍过通过VS2017单步调试FFmpeg源码的方法,这里在Windows10上通过VS2022单步调试FFmpeg 4.2的方法:基于GitHub上ShiftMediaProject/FFmpeg项目,下面对编译过程进行说明…...
【tkinter 专栏】菜单组件
文章目录 前言本章内容导图1. Menu 菜单组件Menu 组件的基本使用制作二级下拉菜单为菜单添加快捷键2. Treeview 树形菜单组件Treeview 组件的基本使用菜单项的获取与编辑前言 本专栏将参考《Python GUI 设计 tkinter 从入门到实践》书籍(吉林大学出版社 ISBN: 9787569275001)…...
【LeetCode-经典面试150题-day10】
目录 242.有效的字母异位词 49.字母异位词分组 202.快乐数 219.存在重复元素Ⅱ 383.赎金信 205.同构字符串 290.单词规律 242.有效的字母异位词 题意: 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。 注意:若 s 和…...
Transformer在医学影像中的应用综述-分类
文章目录 COVID-19 Diagnosis黑盒模型可解释的模型 肿瘤分类黑盒模型可解释模型 视网膜疾病分类小结 总体结构 COVID-19 Diagnosis 黑盒模型 Point-of-Care Transformer(POCFormer):利用Linformer将自注意的空间和时间复杂度从二次型降低到线性型。POCFormer有200…...
新服务器基本环境下载conda + docker + docker-compose + git
文章目录 Ubuntu 允许root用户登录 centos无所谓condadockerubuntucentos docker-compose官方下载docker-compose国内镜像 gitUbuntuCentos Ubuntu 允许root用户登录 centos无所谓 # 以普通用户登录系统,创建root用户的密码 sudo passwd root# SSH 放行 sudo sed -…...
IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...
遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
HTML 列表、表格、表单
1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...
学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
