# [2020q1](http://wiki.csie.ncku.edu.tw/linux/schedule) 第 15 週測驗題
###### tags: `linux2020`
:::info
目的: 檢驗學員對 timerfd 系統呼叫的認知
:::
==[作答表單](https://docs.google.com/forms/d/e/1FAIpQLSfzJaBso-47uqCHbjiJ6LtrVak3HIO0aInUTJQFwC2pa1IF2w/viewform)==
---
## 測驗 `1`
考慮以下 GNU/Linux 程式,假設裡頭每個系統呼叫都可順利執行:
```c
#include <stdio.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <sys/timerfd.h>
#include <unistd.h>
struct posix_timer {
int tfd;
struct itimerspec ts;
timer_t timer;
};
static int efd;
static struct epoll_event ev;
static void do_handle(struct posix_timer *pt)
{
int tfd = pt->tfd;
pt->ts.it_value.tv_sec = 1;
pt->ts.it_value.tv_nsec = 0;
pt->ts.it_interval.tv_sec = 0;
pt->ts.it_interval.tv_nsec = 0;
timerfd_settime(tfd, 0, &pt->ts, NULL);
}
static void start_epoll(int fd, void *data)
{
efd = epoll_create(1);
struct epoll_event ev = {.events = EPOLLIN, .data.ptr = data};
if (epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ev) == -1) {
perror("epoll_ctl");
exit(1);
}
while (1) {
printf("start to epoll wait...\n");
struct epoll_event events;
int ret = epoll_wait(efd, &events, 1, -1);
if (ret < 0) {
perror("epoll_wait");
exit(1);
}
printf("read...\n");
struct posix_timer *pt = events.data.ptr;
/* events is overwritten by epoll_wait, and have ev.data.fd */
int buf;
read(pt->tfd, &buf, sizeof(uint64_t));
printf("[%s] ret %d buf %d \n", __FUNCTION__, ret, buf);
do_handle(pt);
}
exit(1);
}
int main()
{
struct posix_timer pt = {.tfd = timerfd_create(CLOCK_REALTIME, 0)};
if (pt.tfd < 0) {
perror("timerfd_create");
exit(1);
}
pt.ts.it_value.tv_sec = AAA;
pt.ts.it_value.tv_nsec = 0;
pt.ts.it_interval.tv_sec = 0;
pt.ts.it_interval.tv_nsec = 0;
// run timer with rel-timer mode.
if (timerfd_settime(pt.tfd, 0, &pt.ts, NULL)) {
perror("timerfd_settime");
exit(1);
}
if (BBB) start_epoll(pt.tfd, &pt);
while (1) {
puts(".");
sleep(3);
}
return 0;
}
```
並且 `$ cat /proc/sys/kernel/sched_child_runs_first` 的輸出為 `0`,該程式執行結果如下:
```
.
start to epoll wait...
.
read...
[start_epoll] ret 0 buf 1
start to epoll wait...
read...
[start_epoll] ret 0 buf 1
start to epoll wait...
.
read...
[start_epoll] ret 0 buf 1
start to epoll wait...
read...
[start_epoll] ret 0 buf 1
start to epoll wait...
read...
[start_epoll] ret 0 buf 1
start to epoll wait...
.
read...
[start_epoll] ret 0 buf 1
start to epoll wait...
read...
[start_epoll] ret 0 buf 1
start to epoll wait...
read...
[start_epoll] ret 0 buf 1
start to epoll wait...
.
read...
[start_epoll] ret 0 buf 1
start to epoll wait...
read...
[start_epoll] ret 0 buf 1
start to epoll wait...
read...
[start_epoll] ret 0 buf 1
start to epoll wait...
(後略)
```
請補完程式碼,使得輸出符合預期。
==作答區==
AAA = ?
* `(a)` 0
* `(b)` 1
* `(c)` 5
* `(d)` 10
* `(e)` 15
BBB = ?
* `(a)` `fork()`
* `(b)` `!fork()`
* `(c)` `1`