EPollArrayWrapper
EPollArrayWrapper类在jdk\src\solaris\classes\sun\nio\ch目录下。用于linux平台下,操作一个本地epoll_event结构数组。主要封装了epoll的相关函数调用。
EPollArrayWrapper
普通方法
initInterrupt
putEventOps
putData
putDescriptor
getEventOps
getDescriptor
setInterest
add
release
closeEPollFD
poll
updateRegistrations
interrupt
interruptedIndex
interrupted
clearInterrupted
EPollArrayWrapper
EPollArrayWrapper通过Native方法与JVM交互。Native实现在jdk\src\solaris\native\sun\nio\ch目录下,对应EPollArrayWrapper.c。
EPollArrayWrapper
Native方法
epollCreate
epollCtl
epollWait
sizeofEPollEvent
offsetofData
fdLimit
interrupt
init
EPollArrayWrapper
初始化init
执行一些初始化操作:
通过dlsym方式将
epoll_create_func指向epoll_create
epoll_ctl_func指向epoll_ctl
epoll_wait_func指向epoll_wait
EPollArrayWrapper
源代码如下:
JNIEXPORT void JNICALL
Java_sun_nio_ch_EPollArrayWrapper_init(JNIEnv *env, jclass this)
{
epoll_create_func = (epoll_create_t) dlsym(RTLD_DEFAULT, "epoll_create");
epoll_ctl_func = (epoll_ctl_t) dlsym(RTLD_DEFAULT, "epoll_ctl");
epoll_wait_func = (epoll_wait_t) dlsym(RTLD_DEFAULT, "epoll_wait");
if ((epoll_create_func == NULL) || (epoll_ctl_func == NULL) ||
(epoll_wait_func == NULL)) {
JNU_ThrowInternalError(env, "unable to get address of epoll functions, pre-2.6 kernel?");
}
}
EPollArrayWrapper
创建epoll epollCreate
源代码如下:
JNIEXPORT jint JNICALL
Java_sun_nio_ch_EPollArrayWrapper_epollCreate(JNIEnv *env, jobject this)
{
/*
* epoll_create expects a size as a hint to the kernel about how to
* dimension internal structures. We can't predict the size in advance.
*/
int epfd = (*epoll_create_func)(256);
if (epfd < 0) {
JNU_ThrowIOExceptionWithLastError(env, "epoll_create failed");
}
return epfd;
}
EPollArrayWrapper
获取文件句柄上限 fdLimit
用于获取打开的文件句柄上限,这里是socket句柄。这个限制实际上可以通过ulimit 进行查看和设置。可以通过ulimit –a查看open files (-n),也可以通过ulimit –n直接查看。
EPollArrayWrapper
源代码如下:
JNIEXPORT jint JNICALL
Java_sun_nio_ch_EPollArrayWrapper_fdLimit(JNIEnv *env, jclass this)
{
struct rlimit rlp;
if (getrlimit(RLIMIT_NOFILE, &rlp) < 0) {
JNU_ThrowIOExceptionWithLastError(env, "getrlimit failed");
}
return (jint)rlp.rlim_max;
}
EPollArrayWrapper
epoll_event结构大小
源代码如下:
JNIEXPORT jint JNICALL
Java_sun_nio_ch_EPollArrayWrapper_sizeofEPollEvent(JNIEnv* env, jclass this)
{
return sizeof(struct epoll_event);
}
EPollArrayWrapper
用户数据data字段在epoll_event结构中的偏移量 offsetofData
JNIEXPORT jint JNICALL
Java_sun_nio_ch_EPollArrayWrapper_offsetofData(JNIEnv* env, jclass this)
{
return offsetof(struct epoll_event, data);
}
EPollArrayWrapper
在epfd 上执行操作 epollCtl
源代码如下:
JNIEXPORT void JNICALL
Java_sun_nio_ch_EPollArrayWrapper_epollCtl(JNIEnv *env, jobject this, jint epfd,
jint opcode, jint fd, jint events)
{
struct epoll_event event;
int res;
event.events = events;
event.data.fd = fd;
RESTARTABLE((*epoll_ctl_func)(epfd, (int)opcode, (int)fd, &event), res);
/*
* A channel may be registered with several Selectors. When each Selector
* is polled a EPOLL_CTL_DEL op will be inserted into its pending update
* list to remove the file descriptor from epoll. The "last" Selector will
* close the file descriptor which automatically unregisters it from each
* epoll descriptor. To avoid costly synchronization between Selectors we
* allow pending updates to be processed, ignoring errors. The errors are
* harmless as the last update for the file descriptor is guaranteed to
* be EPOLL_CTL_DEL.
*/
if (res < 0 && errno != EBADF && errno != ENOENT && errno != EPERM) {
JNU_ThrowIOExceptionWithLastError(env, "epoll_ctl failed");
}
}
EPollArrayWrapper
epoll_wait
源代码如下:
JNIEXPORT jint JNICALL
Java_sun_nio_ch_EPollArrayWrapper_epollWait(JNIEnv *env, jobject this,
jlong address, jint numfds,
jlong timeout, jint epfd)
{
struct epoll_event *events = jlong_to_ptr(address);
int res;
if (timeout <= 0) { /* Indefinite or no wait */
RESTARTABLE((*epoll_wait_func)(epfd, events, numfds, timeout), res);
} else { /* Bounded wait; bounded restarts */
res = iepoll(epfd, events, numfds, timeout);
}
if (res < 0) {
JNU_ThrowIOExceptionWithLastError(env, "epoll_wait failed");
}
return res;
}
EPollArrayWrapper
中断操作 interrupt
源代码如下:
JNIEXPORT void JNICALL
Java_sun_nio_ch_EPollArrayWrapper_interrupt(JNIEnv *env, jobject this, jint fd)
{
int fakebuf[1];
fakebuf[0] = 1;
if (write(fd, fakebuf, 1) < 0) {
JNU_ThrowIOExceptionWithLastError(env,"write to interrupt fd failed");
}
}