Linux系统编程46 信号 - 流量控制,通过漏桶,令牌桶实现

实验1: 漏桶实例,流量控制,每秒cat10个字符 输出到标准输出

signal + alarm + pause + 信号打断阻塞的系统调用

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>

#define BUFSIZE 10

static volatile int loop = 0;

static void alrm_handler(int s)
{
	alarm(1);//重新定时
	loop = 1;
}

int main(int argc,char *argv[])
{
	int sfd,dfd=1;
	char buf[BUFSIZE];
	int len,ret,pos;


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

	signal(SIGALRM,alrm_handler);
	alarm(1);

	do
	{
		sfd = open(argv[1],O_RDONLY);
		if(sfd < 0)
		{
			if(errno != EINTR)//防止是 信号打断阻塞的系统调用
			{
				perror("open()");
				exit(1);	
			}
		}
	}while(sfd < 0);

	while(1)
	{

//休眠挂起 直到收到信号,重新开始执行while(!loop)循环,实现一秒一输出
// 这里也可以 不用pause(),while()后 执行空,但是这样 CPU 占用率会很高,一秒钟会在这里执行循环上亿次,所以用pause()替换,直接休眠等待信号来唤醒
/*		
while(!loop)
			;
*/
		while(!loop)
			pause();
		loop = 0;

		while((len = read(sfd,buf,BUFSIZE)) < 0)
		{	
if(errno == EINTR)//防止是 信号打断阻塞的系统调用
				continue;
			perror("read()");
			break;
		}

		if(len == 0)
			break;

		//确保写进去 len 个字节
		pos = 0;
		while(len > 0)
		{
			ret = write(dfd,buf+pos,len);
			if(ret < 0)
			{
				if(errno == EINTR) //防止是 信号打断阻塞的系统调用
					continue;
				perror("write()");
				exit(1);

			}
			pos += ret;
			len -= ret;

		}

	}

	close(sfd);

}

缺点:
如果读取的是打印机类的设备,并且当时打印机上面没有数据,那么程序就会一直循环于 read处

while((len = read(sfd,buf,BUFSIZE)) < 0)
		{	
if(errno == EINTR)//防止是 信号打断阻塞的系统调用
				continue;
即 一直循环于:
 读阻塞 ,打断阻塞 判断是假错误(信号打断阻塞的系统调用) 返回重新读 。。。。
 读阻塞 ,打断阻塞 判断是假错误(信号打断阻塞的系统调用) 返回重新读 。。。。
 读阻塞 ,打断阻塞 判断是假错误(信号打断阻塞的系统调用) 返回重新读 。。。。

所以 漏桶的缺陷就是 如果没有数据的时候 就会一直循环等待,直到有数据,如果忽然来的数据量很大,也不能快速的去读数据,只能慢慢的一秒10个字节的去读n次


令牌桶的优势,就是 当没有数据可读的时候,会积攒自己的权限,意思是 如果之前30秒一直没有数据,读空了30秒,那么就存下30个权限,等到有数据的时候,快速使用前面30个权限,快速连续读30次。

实验2:令牌桶实例

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
 
#define CPS 10
#define BUFSIZE CPS
#define BURST 100

static volatile int token = 0;

static void alrm_handler(int s)
{
	alarm(1);
	token++;
	if(token > BURST)
		token = BURST;
}

int main(int argc,char *argv[])
{
	int sfd,dfd=1;
	char buf[BUFSIZE];
	int len,ret,pos;

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

	signal(SIGALRM,alrm_handler);
	alarm(1);

	do
	{
		sfd = open(argv[1],O_RDONLY);
		if(sfd < 0)
		{
			if(errno != EINTR)//signal
			{
				perror("open()");
				exit(1);	
			}

		}
	}while(sfd < 0);


	while(1)
	{

		while(token <= 0)
			pause();
		token--;

		while((len = read(sfd,buf,BUFSIZE)) < 0)
		{	if(errno == EINTR)//signal
				continue;
			perror("read()");
			break;
		}
		if(len == 0)
			break;

		//确保写进去 len 个字节
		pos = 0;
		while(len > 0)
		{
			ret = write(dfd,buf+pos,len);
			if(ret < 0)
			{
				if(errno == EINTR) //signal
					continue;
				perror("write()");
				exit(1);
			}
			pos += ret;
			len -= ret;
		}

	}
	
	close(sfd);
		
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
Linux令牌桶流量控制是一种网络流量控制机制,用于限制进入或离开系统的数据包速率。它基于一个令牌桶模型,在这个模型中,一个固定数量的令牌以固定速率被添加到令牌桶中。每当有一个数据包到达时,系统将从令牌桶中取出一个令牌,只有当令牌桶中有足够的令牌时才允许数据包通过。如果令牌桶中没有足够的令牌,那么数据包就会被丢弃或延迟。 通过配置Linux内核参数和使用工具如tc(Traffic Control),可以实现令牌桶流量控制。以下是一些关键步骤: 1. 启用Linux内核的Traffic Control子系统。这可以通过加载“sch_htb”模块实现。 ``` $ modprobe sch_htb ``` 2. 使用tc命令创建一个类别(class)和队列(qdisc)来实现流量控制。例如,以下命令将创建一个带宽为1mbps、延迟为10ms的队列。 ``` $ tc qdisc add dev eth0 root handle 1: htb default 1 $ tc class add dev eth0 parent 1: classid 1:1 htb rate 1mbit ceil 1mbit $ tc qdisc add dev eth0 parent 1:1 handle 10: netem delay 10ms ``` 3. 根据需求,可以添加过滤规则(filter)以便仅对特定的流量应用流量控制。例如,以下命令将对源IP为192.168.0.1的流量应用限制。 ``` $ tc filter add dev eth0 protocol ip parent 1: prio 1 u32 match ip src 192.168.0.1 flowid 1:1 ``` 通过以上步骤,你可以实现针对特定网络接口、IP地址或其他条件的流量控制。你可以根据具体需求进行调整和配置,以满足你的流量控制需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Linux老A

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值