APUE 第三版 习题 10.5

这是书本上的答案:

See ‘‘Implementing Software Timers’’ by Don Libes (C Users Journal, vol. 8, no. 11, Nov. 1990) for an example. A copy of this paper is available online at http://www.kohala.com/start/libes.timers.txt.

我参考上面提到的文档,使用 alarm() 以及time() 简略测试了一下。

仅在在macOS High Sierra10.13.6上测试过,在linux上应该也是没有问题的。

希望可以帮到和我一样是菜鸟的人。

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Menlo; color: #990000; background-color: #bfbfbf }
span.s1 { }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Menlo; color: #990000; background-color: #bfbfbf }
span.s1 { }

  1 #include <stdio.h>
  2 #include <time.h>
  3 #include <signal.h>
  4 #include <unistd.h>
  5
  6 #define TRUE    1
  7 #define FALSE    0
  8
  9 #define MAX_TIMERS    100    /* number of timers */
 10 typedef time_t TIME;        /* how time is actually stored */
 11 ///#define TIME time_t        /* how time is actually stored */
 12 #define VERY_LONG_TIME    0xffff    /* longest time possible */
 13
 14 struct timer {
 15     int inuse;        /* TRUE if in use */
 16     TIME time;        /* relative time to wait */
 17     char *event;        /* set to TRUE at timeout */
 18 } timers[MAX_TIMERS];        /* set of timers */
 19
 20 void
 21 timers_init() {
 22     struct timer *t;
 23
 24     for (t=timers;t<&timers[MAX_TIMERS];t++)
 25         t->inuse = FALSE;
 26 }
 27
 28 static TIME s_tt;
 29 time_t ttime(time_t *t)
 30 {
 31     return time(t);
 32 }
 33 #define time_now ((TIME)(ttime(NULL) - s_tt))
 34
 35 struct timer *timer_next = NULL;/* timer we expect to run down next */
 36 static TIME time_timer_set;        /* time when physical timer was set */
 37
 38 void timers_update();        /* see discussion below */
 39
 40 static void disable_interrupts(void)
 41 {;}
 42 static void enable_interrupts(void)
 43 {;}
 44
 45 #define start_physical_timer alarm
 46
 47 void
 48 timer_undeclare(t)
 49 struct timer *t;
 50 {
 51     disable_interrupts();
 52     if (!t->inuse) {
 53         enable_interrupts();
 54         return;
 55     }
 56
 57     t->inuse = FALSE;
 58
 59     /* check if we were waiting on this one */
 60     if (t == timer_next) {
 61         timers_update(time_now - time_timer_set);
 62         if (timer_next) {
 63             start_physical_timer(timer_next->time);
 64             time_timer_set = time_now;
 65         }
 66     }
 67     enable_interrupts();
 68 }
 69
 70 /* subtract time from all timers, enabling any that run out along the way */
 71 void
 72 timers_update(time)
 73 TIME time;
 74 {
 75     static struct timer timer_last = {
 76         FALSE            /* in use */,
 77         VERY_LONG_TIME        /* time */,
 78         NULL            /* event pointer */
 79     };
 80
 81     struct timer *t;
 82
 83     timer_next = &timer_last;
 84
 85     for (t=timers;t<&timers[MAX_TIMERS];t++) {
 86         if (t->inuse) {
 87             if (time < t->time) { /* unexpired */
 88                 t->time -= time;
 89                 if (t->time < timer_next->time)
 90                     timer_next = t;
 91             } else { /* expired */
 92                 /* tell scheduler */
 93                 *t->event = TRUE;
 94                 t->inuse = 0;    /* remove timer */
 95             }
 96         }
 97     }
 98
 99     /* reset timer_next if no timers found */
100     if (!timer_next->inuse) timer_next = 0;
101 }
102
103 struct timer *
104 timer_declare(time,event)
105 unsigned int time;        /* time to wait in 10msec ticks */
106 char *event;
107 {
108     struct timer *t;
109
110     disable_interrupts();
111
112     for (t=timers;t<&timers[MAX_TIMERS];t++) {
113         if (!t->inuse) break;
114     }
115
116     /* out of timers? */
117     if (t == &timers[MAX_TIMERS]) {
118         enable_interrupts();
119         return(0);
120     }
121
122     /* install new timer */
123     t->event = event;
124     t->time = time;
125     if (!timer_next) {
126         /* no timers set at all, so this is shortest */
127         time_timer_set = time_now;
128
129         start_physical_timer((timer_next = t)->time);
130     } else if ((time + time_now) < (timer_next->time + time_timer_set)) {
131         /* new timer is shorter than current one, so */
132         timers_update(time_now - time_timer_set);
133         time_timer_set = time_now;
134         start_physical_timer((timer_next = t)->time);
135     } else {
136         /* new timer is longer, than current one */
137     }
138     t->inuse = TRUE;
139     enable_interrupts();
140     return(t);
141 }
142
143 void
144 timer_interrupt_handler(int m) {
145     timers_update(time_now - time_timer_set);
146
147     /* start physical timer for next shortest time if one exists */
148     if (timer_next) {
149         time_timer_set = time_now;
150         start_physical_timer(timer_next->time);
151         printf("@[email protected]%d--\n", (int)timer_next->time);
152     }
153 }
154
155 int
156 main(void)
157 {
158     s_tt = time(NULL);
159     char _4s, _5s, _11s, _19s;
160
161     signal(SIGALRM, timer_interrupt_handler);
162     start_physical_timer(1);
163
164     timer_declare(4,    &_4s);
165     timer_declare(5,    &_5s);
166     timer_declare(11,    &_11s);
167     timer_declare(19,    &_19s);
168     timer_declare(20,    &_19s);
169     timer_declare(21,    &_19s);
170     timer_declare(23,    &_19s);
171
172     while(1);
173
174     return 0;
175 }

原文地址:https://www.cnblogs.com/petter-xy/p/9521021.html

时间: 2024-10-17 19:40:44

APUE 第三版 习题 10.5的相关文章

读书笔记-APUE第三版-(7)进程环境

本章关注单进程运行环境:启动&终止.参数传递和内存布局等. 进程启动终止 如图所示: 启动:内核通过exec函数执行程序,在main函数运行之前,会调用启动例程(start-up routine),取得命令行参数和环境变量.可以把启动例程理解为exit(main(argc,argv)). 终止:五种正常终止方式(从main方法返回/exit/_exit/最后一个线程返回/最后一个线程退出):三种异常终止方式(abort/接收到信号/最后一个线程接收到取消请求). exit与_exit关系:exi

读书笔记-APUE第三版-(5)标准IO库

ISO C标准I/O库使用流的概念读写文件.流是对数据传输的抽象,可以把流理解为从起点到终点间的字节序列. 标准I/O库通过维护进程空间内的缓冲区,减少read/write系统调用次数来提高I/O效率.之前介绍的Unbuffered I/O和文件描述符fd打交道,标准I/O则使用FILE指针. typedef struct{ short level;/*缓冲区满程度*/ unsigned flags;/*文件打开状态标志*/ char fd;/*文件描述符*/ unsigned char hol

读书笔记-APUE第三版-(8)进程控制

进程ID 每一个进程都有一个唯一的进程ID.几个特殊进程: 0号进程是内核进程,一般是调度进程swapper. 1号进程init,是用户进程(以root权限执行/sbin/init),负责初始化. 几个重要函数:getpid(进程ID)/getppid(父进程ID)/getuid(进程真有用户ID)/geteuid(进程有效用户ID)/getgid(进程真有用户组ID)/getegid(进程有效用户组ID). fork/exec/wait例程 fork家族函数用于创建子进程(父子进程关系下节详细

读书笔记-APUE第三版-(6)系统数据文件和信息

常见系统数据文件 下表列出了常见的系统数据文件及其查找函数. 以/etc/passwd文件为例,读取数据的程序基本框架如下: void get_pw_entry() { struct passwd *ptr; setpwent(); while ((ptr = getpwent()) != 0) { -- } endpwent(); return ptr; } 每个数据文件都提供了一个get方法返回文件下一个记录项. set方法充值当前位置到文件开始处. end方法关闭数据文件. 表格中的get

apue第三章习题的一些拙见(不定时更新)

写在前面:本人通信专业大二,自学apue,时间有限,这个系列都是抽时间写的,目前已经看到15章,现在从头做题,如有错误还请指教. 第一题: write和read这样的函数都属于系统调用,这里具体所指的没有缓冲区是没有用户缓冲区,而不是指没有内核缓冲区,这里以我个人的认识认为,这里write和read将数据拷贝到缓冲区后并不直接写到文件中,而是等一定条件发生后才写进去,但是具体机制还需研究.同时这里也暴露了一个问题,每次进行I/O都需要进行系统调用,这无疑是对系统资源的一种浪费,所以这也为后来的标

读书笔记-APUE第三版-(9)进程关系

登录过程 终端登录 init从/etc/ttys中读取终端信息,对每个允许登录的终端,都fork子进程,并执行getty.getty打开终端设备,执行login: execle("/bin/login,"login", "-p", username, (char *)0, envp) login进行用户名密码验证,同时还会进行切换到用户主目录/修改终端设备属主&读写权限/创建进程组/setuid等动作,然后运行login shell. execl(

王爽汇编第三版检测点10.5

(1)下面的程序执行后,ax 中的数值是多少? 1 assume cs:code 2 stack segment 3 dw 8 dup (0) 4 stack ends 5 code segment 6 start: mov ax,stack 7 mov ss,ax 8 mov sp,16 9 mov ds,ax 10 mov ax,0 11 call word ptr ds:[0] 12 inc ax 13 inc ax 14 inc ax 15 mov ax,4c00h 16 int 21h

王爽汇编第三版实验10

1. 显示字符串 1 assume cs:code 2 3 data segment 4 db 'Welcome to masm!',0 5 data ends 6 7 stack segment 8 db 16 dup (0) 9 stack ends 10 11 code segment 12 start: 13 mov dh,8 14 mov dl,3 15 mov cl,2 16 mov ax,data 17 mov ds,ax 18 mov si,0 19 call show_str

问题 1042: C语言程序设计教程(第三版)课后习题9.10

/******************************************************************** @file Main.cpp @date 2017-05-28 22:10:10 @author Zoro_Tiger @brief 问题 1042: C语言程序设计教程(第三版)课后习题9.10 http://www.dotcpp.com/oj/problem1042.html ***************************************