blktap(2)

接下来从tapdisk_server_run()入手,看看tapdisk怎么运行的。

327 int
328 tapdisk_server_run()
329 {
330         int err;
331 //资源锁?
332         err = tapdisk_set_resource_limits();
333         if (err)
334                 return err;
335 //注册信号处理函数
336         signal(SIGBUS, tapdisk_server_signal_handler);
337         signal(SIGINT, tapdisk_server_signal_handler);
338         signal(SIGUSR1, tapdisk_server_signal_handler);
339         signal(SIGXFSZ, tapdisk_server_signal_handler);
340     //运行server
341         __tapdisk_server_run();
342         tapdisk_server_close();
343 
344         return 0;
345 }
245 static void
246 __tapdisk_server_run(void)
247 {   //初始化1了
248         while (server.run)
249                 tapdisk_server_iterate();
250 }
Created with Raphaël 2.1.0 main() main() tapdisk_server_run() tapdisk_server_run() __tapdisk_server_run() __tapdisk_server_run() tapdisk_server_iterate() tapdisk_server_iterate() 资源锁?注册信号处理程序 while(server.run)
227 void
228 tapdisk_server_iterate(void)
229 {
230         int ret;
231     //空函数??可能是以后要添加的
232         tapdisk_server_assert_locks();
233         tapdisk_server_set_retry_timeout();
234         tapdisk_server_check_progress();
235 
236         ret = scheduler_wait_for_events(&server.scheduler);
237         if (ret < 0)
238                 DBG(TLOG_WARN, "server wait returned %d\n", ret);
239 
240         tapdisk_server_check_vbds();
241         tapdisk_server_submit_tiocbs();
242         tapdisk_server_kick_responses();
243 }
150 static void
151 tapdisk_server_set_retry_timeout(void)
152 {
153         td_vbd_t *vbd, *tmp;
154 
155         tapdisk_server_for_each_vbd(vbd, tmp)
156                 if (tapdisk_vbd_retry_needed(vbd)) {
157                         tapdisk_server_set_max_timeout(TD_VBD_RETRY_INTERVAL);
158                         return;
159                 }
160 }

vbd?virtual block device?
56 typedef struct td_vbd_handle td_vbd_t;

//从server.vbds当前保存的list_head开始,遍历所有的vbd
45 #define tapdisk_server_for_each_vbd(vbd, tmp)                           
 46         list_for_each_entry_safe(vbd, tmp, &server.vbds, next)

list_for_each_entry_safe

遍历所有的vbd,找到需要retry的vbd(通过vbd->state)
869 int
870 tapdisk_vbd_retry_needed(td_vbd_t *vbd)
871 {
//&
87: return td_flag_test(vbd->state, TD_VBD_RETRY_NEEDED);
873 }
设置最大超时。

Created with Raphaël 2.1.0 tapdisk_server_set_retry_timeout() tapdisk_server_set_retry_timeout() tapdisk_server_set_max_timeout() tapdisk_server_set_max_timeout() scheduler_set_max_timeout() scheduler_set_max_timeout() s->max_timeout = MIN(s->max_timeout, timeout)

但是server变量只有一个,tapdisk_server_set_max_timeout只有一个常量ian量,为什么要遍历vbd?

162 static void
163 tapdisk_server_check_progress(void)
164 {
165         struct timeval now;
166         td_vbd_t *vbd, *tmp;
167     //获取时间到now里,干嘛用?
168         gettimeofday(&now, NULL);
169 
170         tapdisk_server_for_each_vbd(vbd, tmp)
171                 tapdisk_vbd_check_progress(vbd);
172 }
1107 void
1108 tapdisk_vbd_check_progress(td_vbd_t *vbd)
1109 {
1110         int diff;
1111         struct timeval now;
1112    //vbd的pending_requests指向自身,说明没有加入队列,即非peding
1113         if (list_empty(&vbd->pending_requests))
1114                 return;
1115 
1116         gettimeofday(&now, NULL);
1117         diff = now.tv_sec - vbd->ts.tv_sec;
1118    //10,idle超时
1119         if (diff >= TD_VBD_WATCHDOG_TIMEOUT) {
1120                 DBG(TLOG_WARN, "%s: watchdog timeout: pending requests "
1121                     "idle for %d seconds\n", vbd->name, diff);
1122                 tapdisk_vbd_drop_log(vbd);
1123                 return;
1124         }
1125//更新剩下的时间 
1126         tapdisk_server_set_max_timeout(TD_VBD_WATCHDOG_TIMEOUT - diff);
1127 }
Created with Raphaël 2.1.0 tapdisk_server_check_progress() tapdisk_server_check_progress() tapdisk_vbd_check_progress() tapdisk_vbd_check_progress() tapdisk_server_set_max_timeout() tapdisk_server_set_max_timeout() scheduler_set_max_timeout() scheduler_set_max_timeout() tapdisk_server_for_each_vbd 是pending且没有超时

check_progress检查所有的vbd是否超时,根据vbd设置server的max_timeout

接下来终于开始处理event

Created with Raphaël 2.1.0 tapdisk_server_iterate() tapdisk_server_iterate() scheduler_wait_for_events() scheduler_wait_for_events() scheduler_prepare_events() scheduler_prepare_events() scheduler_run_events() scheduler_run_events() 设置scheduler
224 int
225 scheduler_wait_for_events(scheduler_t *s)
226 {
227         int ret;
228         struct timeval tv;
229 
230         scheduler_prepare_events(s);
231 
232         tv.tv_sec  = s->timeout;
233         tv.tv_usec = 0;
234 
235         DBG("timeout: %d, max_timeout: %d\n",
236             s->timeout, s->max_timeout);
237 
238         ret = select(s->max_fd + 1, &s->read_fds,
239                      &s->write_fds, &s->except_fds, &tv);
240 
241         s->restart     = 0;
242         s->timeout     = SCHEDULER_MAX_TIMEOUT;
243         s->max_timeout = SCHEDULER_MAX_TIMEOUT;
244 
245         if (ret < 0)
246                 return ret;
247 
248         scheduler_run_events(s);
249 
250         return ret;
251 }

ret = select(s->max_fd + 1, &s->read_fds,&s->write_fds, &s->except_fds, &tv);
设置select函数,监听读写异常文件,如果集合中有文件可读/可写/异常发生则返回大于0的数;如果没有则根据timeout参数再判断是否超时,若超出timeout的时间,select返回0,若发生错误返回负值,没有超时则等待。即select程序最多在tv时间内阻塞。
select()

64 static void
 65 scheduler_prepare_events(scheduler_t *s)
 66 {
 67         int diff;
 68         struct timeval now;
 69         event_t *event, *tmp;
 70 //清空文件描述符
 71         FD_ZERO(&s->read_fds);
 72         FD_ZERO(&s->write_fds);
 73         FD_ZERO(&s->except_fds);
 74 
 75         s->max_fd  = 0;
 //设置超时
 76         s->timeout = SCHEDULER_MAX_TIMEOUT;
 77 
 78         gettimeofday(&now, NULL);
 79
  //47 #define scheduler_for_each_event(s, event, tmp) \
 //48         list_for_each_entry_safe(event, tmp, &(s)->events, next)
 //通过s->events为list_head找到列表,遍历所有的event
 80         scheduler_for_each_event(s, event, tmp) {
 81                 if (event->mode & SCHEDULER_POLL_READ_FD) {
 82                         FD_SET(event->fd, &s->read_fds);
 83                         s->max_fd = MAX(event->fd, s->max_fd);
 84                 }
 85 
 86                 if (event->mode & SCHEDULER_POLL_WRITE_FD) {
 87                         FD_SET(event->fd, &s->write_fds);
 88                         s->max_fd = MAX(event->fd, s->max_fd);
 89                 }
 90 
 91                 if (event->mode & SCHEDULER_POLL_EXCEPT_FD) {
 92                         FD_SET(event->fd, &s->except_fds);
 93                         s->max_fd = MAX(event->fd, s->max_fd);
 94                 }
 95 
 96                 if (event->mode & SCHEDULER_POLL_TIMEOUT) {
 97                         diff = event->deadline - now.tv_sec;
 98                         if (diff > 0)
 99                                 s->timeout = MIN(s->timeout, diff);
100                         else
101                                 s->timeout = 0;
102                 }
103         }
104 
105         s->timeout = MIN(s->timeout, s->max_timeout);
106 }

scheduler_prepare_events先清空文件描述符,将设置timeout(600)。
遍历event,根据event->mode设置s。比如event是读,把event->fd添加到s的读文件描述符集中,设置s的max_fd。
fd_set是一个unsigned long类型的数组。每一个里面的每一位记录一个fd(位图)。FD_SET就是把对应位变为1
FD_SET(600,master_set_read);=> master_set_read->fds_bits[(600)/32] |= (1<<(600%32));
除了读写还有except,这个是什么情况,先放着。如果event是SCHEDULER_POLL_TIMEOUT(有限制时间的),检查现在是否超时,更新s的timeout(超时为0)
最后s->timeout = MIN(s->timeout, s->max_timeout);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值