blktap(1)
tapdisk2.c
main()函数:
c = getopt(argc, argv, “s:Dh”)
int getopt(int argc, char * const argv[], const char *optstring);参考
这里表示有s,D,h三种选项,s的后面跟一个参数。
s:memshr_set_domid(atoi(optarg))
optarg这时指向参数,把vhd_info的domid设置为这个参数。
27 typedef struct {
28 int enabled;
29 domid_t domid;
30 xc_interface *xc_handle;
31 } memshr_vbd_info_t;
32
33 memshr_vbd_info_t vbd_info = {0, DOMID_INVALID};
46 void memshr_set_domid(int domid)
47 {
48 vbd_info.domid = domid;
49 }
d:nodaemon=1
h:usage(argv[0],0)
42 static void
43 usage(const char *app, int err)
44 {
45 fprintf(stderr, "usage: %s [-D] <-u uuid> <-c control socket>\n", app) ;
46 exit(err);
47 }
输出错误提示,目的?
tapdisk_server_init()
280 int
281 tapdisk_server_init(void)
282 {
283 memset(&server, 0, sizeof(server));
284 INIT_LIST_HEAD(&server.vbds);
285
286 scheduler_initialize(&server.scheduler);
287
288 return 0;
289 }
60 typedef struct tapdisk_server {
61 int run;
62 struct list_head vbds;
63 scheduler_t scheduler;
64 struct tqueue aio_queue;
65 } tapdisk_server_t;
66
253 void
254 scheduler_initialize(scheduler_t *s)
255 {
256 memset(s, 0, sizeof(scheduler_t));
257
258 s->uuid = 1;
259
260 FD_ZERO(&s->read_fds);
261 FD_ZERO(&s->write_fds);
262 FD_ZERO(&s->except_fds);
263
264 INIT_LIST_HEAD(&s->events);
265 }
43 typedef struct scheduler {
44 fd_set read_fds;
45 fd_set write_fds;
46 fd_set except_fds;
47
48 struct list_head events;
49
50 int uuid;
51 int max_fd;
52 int timeout;
53 int restart;
54 int max_timeout;
55 } scheduler_t;
初始化server:初始化scheduler和vbds
继续main
96 if (!nodaemon) {
97 err = daemon(0, 1);
98 if (err) {
99 DPRINTF("failed to daemonize: %d\n", errno);
100 goto out;
101 }
102 }
如果nodaemon为0,则daemon。所以如果有选项D则代表不要daemon.
在Linux中专门提供了一个函数来完成这个daemon化的过程,这个函数的原型如下
int daemon (int __nochdir, int __noclose);
如果__nochdir的值为0,则将切换工作目录为根目录;如果__noclose为0,则将标准输入,输出和标准错误都重定向到/dev /null。参考
104 err = tapdisk_control_open(&control);
829 int
830 tapdisk_control_open(char **path)
831 {
832 int err;
833 //初始化socket,event_id为-1
//signal(SIGPIPE, SIG_IGN);
//ignore SIGPIPE
834 tapdisk_control_initialize();
835
836 return tapdisk_control_create_socket(path);
837 }
51 struct tapdisk_control {
52 char *path;
53 int socket;
54 int event_id;
55 };
62 static struct tapdisk_control td_control;
758 static int
759 tapdisk_control_create_socket(char **socket_path)
760 {
761 int err, flags;
762 struct sockaddr_un saddr;
763 // 47 #define BLKTAP2_CONTROL_NAME "blktap-control"
//48 #define BLKTAP2_CONTROL_DIR "/var/run/"BLKTAP2_CONTROL_NAME
764 err = tapdisk_control_mkdir(BLKTAP2_CONTROL_DIR);
785 td_control.socket = socket(AF_UNIX, SOCK_STREAM, 0);
792 memset(&saddr, 0, sizeof(saddr));
793 strncpy(saddr.sun_path, td_control.path, sizeof(saddr.sun_path));
794 saddr.sun_family = AF_UNIX;
795
796 err = bind(td_control.socket,
797 (const struct sockaddr *)&saddr, sizeof(saddr));
804 err = listen(td_control.socket, 10);
811 err = tapdisk_server_register_event(SCHEDULER_POLL_READ_FD,
812 td_control.socket, 0,
813 tapdisk_control_accept, NULL);
819 td_control.event_id = err;
820 *socket_path = td_control.path;
821
初始化tapdisk_control,其中tapdisk_control_create_socket创建了socket赋值给tapdisk_control的socket,把path返回到返回到参数path,并且赋值给tapdisk_control的path。在main里面,path就是control
这里的细节先不看了。
接下来,如果是有daemon的,把/dev/null的东西复制到STDIN_FILENO等地方,为什么??先跳过
113 if (!nodaemon) {
114 int fd;
115
116 fd = open("/dev/null", O_RDWR);
117 if (fd != -1) {
118 dup2(fd, STDIN_FILENO);
119 dup2(fd, STDOUT_FILENO);
120 dup2(fd, STDERR_FILENO);
121 if (fd > 2)
122 close(fd);
123 }
124 }
126 err = tapdisk_server_complete();
291 int
292 tapdisk_server_complete(void)
293 {
294 int err;
295
296 err = tapdisk_server_init_aio();
297 if (err)
298 goto fail;
299 //run置1
300 server.run = 1;
301
302 return 0;
303
304 fail:
305 tapdisk_server_close_aio();
306 return err;
307 }
208 static int
209 tapdisk_server_init_aio(void)
210 {
211 return tapdisk_init_queue(&server.aio_queue, TAPDISK_TIOCBS,
212 TIO_DRV_LIO, NULL);
213 }
56 struct tqueue {
57 int size;
58
59 const struct tio *tio;
60 void *tio_data;
61
62 struct opioctx opioctx;
63
64 int queued;
65 struct iocb **iocbs;
66
67 /* number of iocbs pending in the aio layer */
68 int iocbs_pending;
69
70 /* number of tiocbs pending in the queue --
71 * this is likely to be larger than iocbs_pending
72 * due to request coalescing */
73 int tiocbs_pending;
74
75 /* iocbs may be deferred if the aio ring is full.
76 * tapdisk_queue_complete will ensure deferred
77 * iocbs are queued as slots become available. */
78 struct tlist deferred;
79 int tiocbs_deferred;
80
81 /* optional tapdisk filter */
82 struct tfilter *filter;
83
84 uint64_t deferrals;
85 };
607 int
608 tapdisk_init_queue(struct tqueue *queue, int size,
609 int drv, struct tfilter *filter)
610 {
611 int i, err;
612
613 memset(queue, 0, sizeof(struct tqueue));
614
615 queue->size = size;
616 queue->filter = filter;
617
618 if (!size)
619 return 0;
620
621 err = tapdisk_queue_init_io(queue, drv);
622 if (err)
623 goto fail;
624
625 queue->iocbs = calloc(size, sizeof(struct iocb *));
626 if (!queue->iocbs) {
627 err = -errno;
628 goto fail;
629 }
630
631 err = opio_init(&queue->opioctx, size);
632 if (err)
633 goto fail;
634
635 return 0;
看到这里,可以猜测tapdisk_server_complete初始化server:将run置1;初始化aoiqueue。这个aoiqueue是干嘛的,以后再看。
132 err = tapdisk_server_run();