# [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`