信号完结

This commit is contained in:
lzy
2024-05-27 02:28:25 +08:00
parent a57bbdb4c1
commit 2336f88407
9 changed files with 703 additions and 8 deletions

View File

@@ -0,0 +1,35 @@
# 方便起见一般都会先定义编译器链接器
CC = gcc
LD = gcc
# 正则表达式表示目录下所有.c文件相当于SRCS = main.c a.c b.c
SRCS = $(wildcard *.c)
# OBJS表示SRCS中把列表中的.c全部替换为.o相当于OBJS = main.o a.o b.o
OBJS = $(patsubst %c, %o, $(SRCS))
# 可执行文件的名字
TARGET = main
# .PHONE伪目标具体含义百度一下一大堆介绍
.PHONY:all clean
# 要生成的目标文件
all: $(TARGET)
LDFLAGS=-L/usr/local/lib
# LDLIBS=-lqueue -lllist
# 第一行依赖关系冒号后面为依赖的文件相当于Hello: main.o a.o b.o
# 第二行规则:$@表示目标文件,$^表示所有依赖文件,$<表示第一个依赖文件
$(TARGET): $(OBJS)
$(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS)
# 上一句目标文件依赖一大堆.o文件这句表示所有.o都由相应名字的.c文件自动生成
%.o:%.c
$(CC) -c $^
# make clean删除所有.o和目标文件
clean:
rm -f $(OBJS) $(TARGET)

View File

@@ -0,0 +1,99 @@
#include "mytbf.h"
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#define CPS 10
#define BUFSIZE 1024
#define BURST 100 //!! token上限
int main(int argc, char** argv)
{
int sfd, dfd = 1;
char buf[BUFSIZE];
int len, ret, pos;
int size;
mytbf_t* tbf;
if (argc < 2)
{
fprintf(stderr, "Usage: %s <src>\n", argv[0]);
exit(1);
}
tbf = mytbf_init(CPS, BURST);
if (NULL == tbf)
{
fprintf(stderr, "mytbf_init failed\n");
exit(1);
}
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 failed: %s\n", strerror(errno));
}
//* 阻塞在这里的时候token会自增
while ((len = read(sfd, buf, size)) < 0)
{
//!!!
if (EINTR == errno)
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 (EINTR == errno)
continue;
perror("write");
exit(1);
}
pos += ret;
len -= ret;
}
// sleep(1); //! 能实现,但是移植性不好
}
close(sfd);
mytbf_destroy(tbf);
exit(0);
}

View File

@@ -0,0 +1,201 @@
/***********************************************************************
* @file mytbf.c
* @brief
* 令牌桶库实现
*
* @author lzy (lllzzzyyy@buaa.edu.cn)
* @url https://lzyyyyyy.fun
*
* @date 2024-05-26
*
***********************************************************************/
#include "mytbf.h"
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
struct mytbf_st
{
int cps;
int burst;
int token;
int pos;
};
static struct mytbf_st* job[MYTBF_MAX];
static int inited = 0;
static struct sigaction sa, alrm_sa_save;
static int get_free_pos( )
{
int i;
for (i = 0; i < MYTBF_MAX; i++)
{
if (NULL == job[i])
return i;
}
return -1;
}
static void alrm_action(int s, siginfo_t* infop, void* unused)
{
int i;
//* 判断信号来源
if (SI_KERNEL != infop->si_code)
return;
for (i = 0; i < MYTBF_MAX; i++)
{
if (NULL != job[i])
{
job[i]->token += job[i]->cps;
if (job[i]->token > job[i]->burst)
job[i]->token = job[i]->burst;
}
}
}
static void module_unload( )
{
int i;
struct itimerval itv;
sigaction(SIGALRM, &alrm_sa_save, NULL);
if (errno != 0)
{
perror("sigaction");
exit(1);
}
itv.it_interval.tv_sec = 0;
itv.it_interval.tv_usec = 0;
itv.it_value.tv_sec = 0;
itv.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &itv, NULL);
if (errno != 0)
{
perror("setitimer");
exit(1);
}
for (i = 0; i < MYTBF_MAX; i++)
free(job[i]);
}
static void module_load( )
{
struct sigaction sa;
struct itimerval itv;
sa.sa_sigaction = alrm_action;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO; // 表示使用sigaction三参数的形式
sigaction(SIGALRM, &sa, &alrm_sa_save);
if (errno != 0)
{
perror("sigaction");
exit(1);
}
itv.it_interval.tv_sec = 1;
itv.it_interval.tv_usec = 0;
itv.it_value.tv_sec = 1;
itv.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &itv, NULL);
if (errno != 0)
{
perror("setitimer");
exit(1);
}
atexit(module_unload); //!!! atexit()
}
mytbf_t* mytbf_init(int cps, int burst)
{
struct mytbf_st* me;
int pos;
if (!inited)
{
module_load( );
inited = 1;
}
pos = get_free_pos( );
if (pos < 0)
return NULL;
me = malloc(sizeof(*me));
if (NULL == me)
return NULL;
me->cps = cps;
me->burst = burst;
me->token = 0;
me->pos = pos;
job[pos] = me;
return me;
}
static int min(int a, int b)
{
return a < b ? a : b;
}
int mytbf_fetchtoken(mytbf_t* ptr, int size)
{
if (size <= 0)
return -EINVAL;
struct mytbf_st* me = ptr;
int n;
while (me->token <= 0)
pause( );
n = min(size, me->token);
me->token -= n;
return n;
}
int mytbf_returntoken(mytbf_t* ptr, int size)
{
if (size <= 0)
return -EINVAL;
struct mytbf_st* me = ptr;
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;
}

View File

@@ -0,0 +1,26 @@
/***********************************************************************
* @file mytbf.h
* @brief
* 令牌桶库
*
* @author lzy (lllzzzyyy@buaa.edu.cn)
* @url https://lzyyyyyy.fun
*
* @date 2024-05-26
*
***********************************************************************/
#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__H__