libevent代码阅读(7)——“hello-world.c”之 io复用机制的初始化

选择完成最适合的io复用机制之后,就要开始进行初始化设置,即调用eventop的init回调函数,以epoll为例,epoll_init的定义如下:

// epoll初始化
static void *
epoll_init(struct event_base *base)
{
	// epoll的文件描述符
	int epfd;

	// 用于存放epoll的文件描述符以及一些事件
	struct epollop *epollop;

	/* Initialize the kernel queue.  (The size field is ignored since
	 * 2.6.8.) */
	// 创建epoll文件描述符
	// 这里直接使用了底层的系统调用,而不是linux提供的api接口
	if ((epfd = epoll_create(32000)) == -1) {
		if (errno != ENOSYS)
			event_warn("epoll_create");
		return (NULL);
	}
	// 当调用exec时 关闭该描述符
	evutil_make_socket_closeonexec(epfd);

	// 创建epollop结构
	if (!(epollop = mm_calloc(1, sizeof(struct epollop)))) {
		close(epfd);
		return (NULL);
	}

	// 初始化epollop的字段
	epollop->epfd = epfd;


	/* Initialize fields */
	// 初始化epoll事件数组
	epollop->events = mm_calloc(INITIAL_NEVENT, sizeof(struct epoll_event));
	if (epollop->events == NULL) {
		mm_free(epollop);
		close(epfd);
		return (NULL);
	}
	epollop->nevents = INITIAL_NEVENT;

	// 如果设置了使用changelist,那么就使用changelist
	// 使用了changelist可以减少系统调用的次数
	if ((base->flags & EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST) != 0 ||
	    ((base->flags & EVENT_BASE_FLAG_IGNORE_ENV) == 0 &&
		evutil_getenv("EVENT_EPOLL_USE_CHANGELIST") != NULL))
		base->evsel = &epollops_changelist;

	// 信号处理器初始化
	evsig_init(base);

	return (epollop);
}

我们看到epoll_init函数的最后调用了evsig_init,这个函数的作用是初始化信号处理器,它定义如下:

/*
 * 信号处理器初始化
 */
int
evsig_init(struct event_base *base)
{
	/*
	 * Our signal handler is going to write to one end of the socket
	 * pair to wake up our event loop.  The event loop then scans for
	 * signals that got delivered.
	 */
	/*
	 * 创建用于通知信号到来的管道
	 * 当程序受到信号的时候,并不直接处理,而是通过管道将其传递到事件多路分发器中
	 * 这样信号就能够像其他事件那样可以被统一处理了
	 */
	if (evutil_socketpair( AF_UNIX, SOCK_STREAM, 0, base->sig.ev_signal_pair) == -1)
	{
#ifdef WIN32
		/* Make this nonfatal on win32, where sometimes people
		   have localhost firewalled. */
		event_sock_warn(-1, "%s: socketpair", __func__);
#else
		event_sock_err(1, -1, "%s: socketpair", __func__);
#endif
		return -1;
	}

	// 调用exec的时,关闭高套接字
	evutil_make_socket_closeonexec(base->sig.ev_signal_pair[0]);
	evutil_make_socket_closeonexec(base->sig.ev_signal_pair[1]);

	// 设置旧的信号处理函数数组和数量
	base->sig.sh_old = NULL;
	base->sig.sh_old_max = 0;

	// 设置套接字为非阻塞
	evutil_make_socket_nonblocking(base->sig.ev_signal_pair[0]);
	evutil_make_socket_nonblocking(base->sig.ev_signal_pair[1]);

	// 事件处理器赋值
	event_assign(&base->sig.ev_signal, base, base->sig.ev_signal_pair[1],
		EV_READ | EV_PERSIST, evsig_cb, base);

	base->sig.ev_signal.ev_flags |= EVLIST_INTERNAL;

	// 优先级设置
	event_priority_set(&base->sig.ev_signal, 0);

	// 保存针对信号的操作(evsigops和epollops一样是一个操作的集合)
	base->evsigsel = &evsigops;

	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值