学习到了 常用函数 system
This commit is contained in:
25
C16-并发/parallel/signal/5sec.c
Normal file
25
C16-并发/parallel/signal/5sec.c
Normal file
@@ -0,0 +1,25 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
/***********************************************************************
|
||||
* @brief 使用time函数实现计时功能
|
||||
* @param argc
|
||||
* @param argv
|
||||
* @return int
|
||||
***********************************************************************/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
time_t end;
|
||||
long long count = 0;
|
||||
|
||||
end = time(NULL) + 5;
|
||||
|
||||
while (time(NULL) <= end)
|
||||
count++;
|
||||
|
||||
printf("%lld\n", count);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
35
C16-并发/parallel/signal/5sec_sig.c
Normal file
35
C16-并发/parallel/signal/5sec_sig.c
Normal file
@@ -0,0 +1,35 @@
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
//!!! 不加volatile关键字,loop变量的值不会被修改,导致死循环!!!
|
||||
static volatile int loop = 1;
|
||||
|
||||
static void alrm_handler(int sig)
|
||||
{
|
||||
loop = 0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* @brief 用sig实现计时
|
||||
* @param argc
|
||||
* @param argv
|
||||
* @return int
|
||||
***********************************************************************/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
long long count = 0;
|
||||
|
||||
//!!!
|
||||
signal(SIGALRM, alrm_handler);
|
||||
alarm(5);
|
||||
//!!! signal注册时钟信号的行为需要在alarm之前
|
||||
|
||||
while (loop)
|
||||
count++;
|
||||
|
||||
printf("%lld \n", count);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
20
C16-并发/parallel/signal/alarm.c
Normal file
20
C16-并发/parallel/signal/alarm.c
Normal file
@@ -0,0 +1,20 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
alarm(10);
|
||||
alarm(1);
|
||||
alarm(5);
|
||||
|
||||
// alarm(10);
|
||||
// alarm(5);
|
||||
// alarm(1);
|
||||
|
||||
// 效果不一样
|
||||
|
||||
for (;;)
|
||||
pause();
|
||||
|
||||
exit(0);
|
||||
}
|
||||
35
C16-并发/parallel/signal/anytimer/Makefile
Normal file
35
C16-并发/parallel/signal/anytimer/Makefile
Normal 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)
|
||||
0
C16-并发/parallel/signal/anytimer/anytimer.c
Normal file
0
C16-并发/parallel/signal/anytimer/anytimer.c
Normal file
47
C16-并发/parallel/signal/anytimer/anytimer.h
Normal file
47
C16-并发/parallel/signal/anytimer/anytimer.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#ifndef __ANYTIMER__H__
|
||||
#define __ANYTIMER__H__
|
||||
|
||||
#define JOB_MAX 1024
|
||||
typedef void at_jobfunc_t(void *);
|
||||
|
||||
/********************************************************************
|
||||
* @brief 创建定时器
|
||||
* @details
|
||||
* @param sec
|
||||
* @param jobp
|
||||
* @param arg
|
||||
* @return int
|
||||
* >= 0 成功,返回定时器ID
|
||||
* == -EINVAL 失败,参数错误
|
||||
* == -ENOMEM 失败,内存不足
|
||||
* == -ENOSPC 失败,数组满
|
||||
********************************************************************/
|
||||
int at_addjob(int sec, at_jobfunc_t *jobp, void *arg);
|
||||
|
||||
/********************************************************************
|
||||
* @brief 取消定时器
|
||||
* @details
|
||||
* @param id
|
||||
* @return int
|
||||
* == 0 成功,定时器已取消
|
||||
* == -EINVAL 失败,参数错误
|
||||
* == -EBUSY 失败,指定任务已完成
|
||||
* == -ECANCELED 失败,定时器重复取消
|
||||
********************************************************************/
|
||||
int at_canceljob(int id);
|
||||
|
||||
/*********************************************************************
|
||||
* @brief 回收任务
|
||||
* @details
|
||||
* @param id
|
||||
* @return int
|
||||
* == 0 成功,任务已回收
|
||||
* == -EINVAL 失败,参数错误
|
||||
********************************************************************/
|
||||
int at_waitjob(int id);
|
||||
|
||||
|
||||
int at_pausejob(int id);
|
||||
int at_resumejob(int id);
|
||||
|
||||
#endif //!__ANYTIMER__H__
|
||||
40
C16-并发/parallel/signal/anytimer/main.c
Normal file
40
C16-并发/parallel/signal/anytimer/main.c
Normal file
@@ -0,0 +1,40 @@
|
||||
#include "anytimer.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void f1(void *p)
|
||||
{
|
||||
printf("f1():%s\n", (char *)p);
|
||||
}
|
||||
|
||||
static void f2(void *p)
|
||||
{
|
||||
printf("f1():%s\n", (char *)p);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int job1;
|
||||
|
||||
puts("Begin!");
|
||||
|
||||
job1 = at_addjob(5, f1, "aaa");
|
||||
if (job1 < 0)
|
||||
{
|
||||
fprintf(stderr, "at_addjob() failed!:%s\n", strerror(-job1));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
puts("End!");
|
||||
|
||||
while (1)
|
||||
{
|
||||
write(1, ".", 1);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
|
||||
exit(0);
|
||||
}
|
||||
94
C16-并发/parallel/signal/mycpy.c
Normal file
94
C16-并发/parallel/signal/mycpy.c
Normal file
@@ -0,0 +1,94 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define BUFSIZE 1024
|
||||
/**
|
||||
* 可以用 time 命令找到 BUFSIZE 最佳值
|
||||
*
|
||||
* time ./mycpy /etc/services /tmp/out
|
||||
*/
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int sfd, dfd;
|
||||
char buf[BUFSIZE];
|
||||
int len, ret, pos;
|
||||
|
||||
if (argc < 3)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s <src> <dst>\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
do //!!!
|
||||
{
|
||||
sfd = open(argv[1], O_RDONLY);
|
||||
if (sfd < 0)
|
||||
{
|
||||
//!!!
|
||||
if (errno != EINTR)
|
||||
{
|
||||
perror("open");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
} while (sfd < 0);
|
||||
|
||||
|
||||
do //!!!
|
||||
{
|
||||
dfd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
||||
if (dfd < 0)
|
||||
{
|
||||
// !!!
|
||||
if (errno != EINTR)
|
||||
{
|
||||
close(sfd);
|
||||
perror("open");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
} while (dfd < 0);
|
||||
|
||||
|
||||
while (1)
|
||||
{
|
||||
len = read(sfd, buf, BUFSIZE);
|
||||
if (len < 0)
|
||||
{
|
||||
//!!!
|
||||
if (EINTR == errno)
|
||||
continue;
|
||||
|
||||
perror("read");
|
||||
break;
|
||||
}
|
||||
if (len == 0)
|
||||
break;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
close(dfd);
|
||||
close(sfd);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
35
C16-并发/parallel/signal/mytbf/Makefile
Normal file
35
C16-并发/parallel/signal/mytbf/Makefile
Normal 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)
|
||||
99
C16-并发/parallel/signal/mytbf/main.c
Normal file
99
C16-并发/parallel/signal/mytbf/main.c
Normal 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);
|
||||
}
|
||||
155
C16-并发/parallel/signal/mytbf/mytbf.c
Normal file
155
C16-并发/parallel/signal/mytbf/mytbf.c
Normal file
@@ -0,0 +1,155 @@
|
||||
/***********************************************************************
|
||||
* @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 <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 __sighandler_t alrm_handler_save; //!!! 保存原来的alarm行为
|
||||
|
||||
|
||||
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_handler(int s)
|
||||
{
|
||||
int i;
|
||||
|
||||
alarm(1);
|
||||
|
||||
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;
|
||||
|
||||
signal(SIGALRM, alrm_handler_save);
|
||||
alarm(0);
|
||||
for (i = 0; i < MYTBF_MAX; i++)
|
||||
free(job[i]);
|
||||
}
|
||||
|
||||
static void module_load()
|
||||
{
|
||||
alrm_handler_save = signal(SIGALRM, alrm_handler);
|
||||
alarm(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;
|
||||
}
|
||||
26
C16-并发/parallel/signal/mytbf/mytbf.h
Normal file
26
C16-并发/parallel/signal/mytbf/mytbf.h
Normal 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__
|
||||
108
C16-并发/parallel/signal/slowcat.c
Normal file
108
C16-并发/parallel/signal/slowcat.c
Normal file
@@ -0,0 +1,108 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define CPS 10
|
||||
#define BUFSIZE CPS
|
||||
|
||||
static volatile int loop = 0;
|
||||
|
||||
static void alrm_handler(int s)
|
||||
{
|
||||
// alarm(1); //!! 产生新的alarm
|
||||
loop = 1;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* @brief slowcat
|
||||
* @details 流量控制,漏筒实现
|
||||
* @param argc
|
||||
* @param argv
|
||||
* @return int
|
||||
***********************************************************************/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int sfd, dfd = 1;
|
||||
char buf[BUFSIZE];
|
||||
int len, ret, pos;
|
||||
struct itimerval itv;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s <src>\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
signal(SIGALRM, alrm_handler);
|
||||
// alarm(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;
|
||||
if (setitimer(ITIMER_REAL, &itv, NULL) < 0)
|
||||
{
|
||||
perror("setitimer");
|
||||
exit(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(); //!
|
||||
loop = 0;
|
||||
|
||||
while ((len = read(sfd, buf, BUFSIZE)) < 0)
|
||||
{
|
||||
//!!!
|
||||
if (EINTR == errno)
|
||||
continue;
|
||||
|
||||
perror("read");
|
||||
break;
|
||||
}
|
||||
if (len == 0)
|
||||
break;
|
||||
|
||||
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);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
102
C16-并发/parallel/signal/slowcat2.c
Normal file
102
C16-并发/parallel/signal/slowcat2.c
Normal file
@@ -0,0 +1,102 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define CPS 10
|
||||
#define BUFSIZE CPS
|
||||
#define BURST 100 //!! token上限
|
||||
|
||||
// static volatile int token = 0;
|
||||
static volatile sig_atomic_t token = 0; //!!! 保证原子
|
||||
|
||||
static void alrm_handler(int s)
|
||||
{
|
||||
alarm(1); //!! 产生新的alarm
|
||||
token++;
|
||||
if (token > BURST)
|
||||
token = BURST;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* @brief slowcat
|
||||
* @details 流量控制,令牌桶实现
|
||||
* @param argc
|
||||
* @param argv
|
||||
* @return int
|
||||
***********************************************************************/
|
||||
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>\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 (token <= 0)
|
||||
pause(); //!
|
||||
|
||||
token--; //!!! 这条指令不一定原子
|
||||
|
||||
//* 阻塞在这里的时候,token会自增
|
||||
while ((len = read(sfd, buf, BUFSIZE)) < 0)
|
||||
{
|
||||
//!!!
|
||||
if (EINTR == errno)
|
||||
continue;
|
||||
|
||||
perror("read");
|
||||
break;
|
||||
}
|
||||
if (len == 0)
|
||||
break;
|
||||
|
||||
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);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
26
C16-并发/parallel/signal/star.c
Normal file
26
C16-并发/parallel/signal/star.c
Normal file
@@ -0,0 +1,26 @@
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void int_hander(int s)
|
||||
{
|
||||
write(1, "!", 1);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
//* ignore SIGINT
|
||||
// signal(SIGINT, SIG_IGN);
|
||||
|
||||
signal(SIGINT, int_hander);
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
write(1, "*", 1);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
Reference in New Issue
Block a user