eventepoll3
지금부터 이 걸 보 겠 습 니 다. 여러분 이 가장 막 아야 한다 고 생각 하 는 함수. , 지금부터 시작 하 겠 습 니 다. 소스 코드 를 통 해 분석 해 보 겠 습 니 다.
모두 epoll 흐릿 한 곳
SYSCALL_DEFINE4(epoll_wait, int, epfd, struct epoll_event __user *, events,
int, maxevents, int, timeout)
{
int error;
struct file *file;
struct eventpoll *ep;
/* 이것 괜찮아요? 걱정 하지 마. , 너 는 영원히 이런 다 중 접속 이 없 을 것 이다. , 그때 까지 는 epoll 붕괴 가 아니 었 어 요. 니 시스템 이 야. 다른 데 가 먼저 무 너 져. */
if (maxevents <= 0 || maxevents > EP_MAX_EVENTS)
return -EINVAL;
/* 입력 주소 공간의 유효성 검사 */
if (!access_ok(VERIFY_WRITE, events, maxevents * sizeof(struct epoll_event))) {
error = -EFAULT;
goto error_return;
}
/* 얻다 들 어 오 는 file fd 대응 하 는 struct file 구조 * /
error = -EBADF;
file = fget(epfd);
if (!file)
goto error_return;
/*
* 검사 하 다. file fd 의 file operations 구조 가 epoll 인지 아 닌 지 라 고 말 했다. anon inode getfd 기억 나 요. 그래?
*/
error = -EINVAL;
if (!is_file_epoll(file))
goto error_fput;
/* 보존했어 "전역" struct eventpoll 구조 가 짜이다 */
ep = file->private_data;
/* Time to fish for events ... */
error = ep_poll(ep, events, maxevents, timeout);
error_fput:
fput(file);
error_return:
return error;
}
자, 이제 보 자. ep_poll(ep, events, maxevents, timeout); 이 친절 한 함수 말 이 야.
static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
int maxevents, long timeout)
{
int res, eavail;
unsigned long flags;
long jtimeout;
wait_queue_t wait;
/*-1 사실 영구 수면 이에 요. */
jtimeout = (timeout < 0 || timeout >= EP_MAX_MSTIMEO) ?
MAX_SCHEDULE_TIMEOUT : (timeout * HZ + 999) / 1000;
retry:
/ * 여 기 는 전역 적 인 spin 을 사 용 했 습 니 다. 두루 다니다 */
spin_lock_irqsave(&ep->lock, flags);
res = 0;
/ * 아직 준비 되 지 않 은 이벤트 * /
if (list_empty(&ep->rdllist)) {
/*
* We don't have any available event to return to the caller.
* We need to sleep here, and we will be wake up by
* ep_poll_callback() when events will become available.
*/
/ * 초기 화 * /
init_waitqueue_entry(&wait, current);
wait.flags |= WQ_FLAG_EXCLUSIVE;
__add_wait_queue(&ep->wq, &wait);
for (;;) {
/ * 받 아들 이 기 를 바 랍 니 다. ep_poll_callback() 단말 무슨 일이 일 어 났 는 지 알려 주세요 * /
set_current_state(TASK_INTERRUPTIBLE);
/ * 잠 자기 전에 대기 열 에 물건 이 있 는 지 확인 하고, 기다 릴 시간 이 없 거나. 바로 뛰 기 * /
if (!list_empty(&ep->rdllist) || !jtimeout)
break;
/ * 현재 스 레 드 를 연결 상태 ,등 사건 발생 * /
if (signal_pending(current)) {
res = -EINTR;
break;
}
/ * 인 터 럽 트 를 풀 고 선택 한 자 물 쇠 를 복원 합 니 다. 커 널 스케줄 을 받 아들 이 고 남 은 시간 을 계산 합 니 다 * /
spin_unlock_irqrestore(&ep->lock, flags);
jtimeout = schedule_timeout(jtimeout);
/ * 돌아 와 서 다시 잠 그 고 기 다 려 * /
spin_lock_irqsave(&ep->lock, flags);
}
/ * 드디어 상황 이 발생 했 습 니 다. ,자신 이 대기 열 에서 떼 어 내기 * /
__remove_wait_queue(&ep->wq, &wait);
set_current_state(TASK_RUNNING);
/ * 과연 맞 는 지 뒤 돌아 보 자 대기 열 에 이벤트 가 있 습 니 다. */
}
/* 작가 님 조심 하 시 네요. ...자 물 쇠 를 돌려 주기 전에 TMD 를 보 세 요. 도대체 준 비 된 사건 이 효과 가 있 는 지 없 는 지 */
eavail = !list_empty(&ep->rdllist) || ep->ovflist != EP_UNACTIVE_PTR;
spin_unlock_irqrestore(&ep->lock, flags);
/ * 기회 가 없어 요... * /
/ * 사용자 공간 으로 돌아 가 는 마지막 자체 검 측, */
if (!res && eavail &&
!(res = ep_send_events(ep, events, maxevents)) && jtimeout)
goto retry;
return res;
}
이제 이 걸 보 겠 습 니 다. ep_send_events 도대체 뭘 했 길 래
/ * 하 나 를 초기 화 하 는 것 입 니 다. 프 라이 비트 struct ep_send_events_data, 기억 epsend_events_proc
* 이 리 셋 방법 에는 그것 이 필요 합 니 다 * /
static int ep_send_events(struct eventpoll *ep,
struct epoll_event __user *events, int maxevents)
{
struct ep_send_events_data esed;
esed.maxevents = maxevents;
esed.events = events;
return ep_scan_ready_list(ep, ep_send_events_proc, &esed);
}
/ * 저자 가 덧 붙 인 주석 은 이 함수 의 목적 은
* 스캐닝 준비 링크 (rdlist) 동시에 호출 하 다. f_op - > poll () 함수, O (n) 의 복잡 도 내 에서 * /
static int ep_scan_ready_list(struct eventpoll *ep,
int (*sproc)(struct eventpoll *,
struct list_head *, void *),
void *priv)
{
int error, pwake = 0;
unsigned long flags;
struct epitem *epi, *nepi;
LIST_HEAD(txlist);
/*
* eventpoll_release_file() and epoll_ctl().
*/
mutex_lock(&ep->mtx);
/*
* Steal the ready list, and re-init the original one to the
* empty list. Also, set ep->ovflist to NULL so that events
* happening while looping w/out locks, are not lost. We cannot
* have the poll callback to queue directly on ep->rdllist,
* because we want the "sproc" callback to be able to do it
* in a lockless way.
*/
spin_lock_irqsave(&ep->lock, flags);
/* ep->rdlist txlist */
list_splice_init(&ep->rdllist, &txlist);
/* ep->ovflist , */
ep->ovflist = NULL;
spin_unlock_irqrestore(&ep->lock, flags);
/* ep_send_events_proc , ,
*/
error = (*sproc)(ep, &txlist, priv);
spin_lock_irqsave(&ep->lock, flags);
/*
* During the time we spent inside the "sproc" callback, some
* other events might have been queued by the poll callback.
* We re-insert them inside the main ready-list here.
*/
/* ovflist */
for (nepi = ep->ovflist; (epi = nepi) != NULL;
nepi = epi->next, epi->next = EP_UNACTIVE_PTR) {
/* file fd , */
if (!ep_is_linked(&epi->rdllink))
list_add_tail(&epi->rdllink, &ep->rdllist);
}
/* */
ep->ovflist = EP_UNACTIVE_PTR;
/* */
list_splice(&txlist, &ep->rdllist);
if (!list_empty(&ep->rdllist)) {
/* eventpoll ( ) poll ( ) < , >* /
if (waitqueue_active(&ep->wq))
wake_up_locked(&ep->wq);
if (waitqueue_active(&ep->poll_wait))
pwake++;
}
spin_unlock_irqrestore(&ep->lock, flags);
mutex_unlock(&ep->mtx);
/* We have to call this outside the lock */
if (pwake)
ep_poll_safewake(&ep->poll_wait);
return error;
}
static int ep_send_events_proc(struct eventpoll *ep, struct list_head *head,
void *priv)
{
struct ep_send_events_data *esed = priv;
int eventcnt;
unsigned int revents;
struct epitem *epi;
struct epoll_event __user *uevent;
/* , */
/*uevent epoll_wait struct epoll_event
*head rdlist txlist, eventcnt */
for (eventcnt = 0, uevent = esed->events;
!list_empty(head) && eventcnt < esed->maxevents;) {
/* struct epitem*/
epi = list_first_entry(head, struct epitem, rdllink);
/* */
list_del_init(&epi->rdllink);
/* file fd poll , ( )*/
revents = epi->ffd.file->f_op->poll(epi->ffd.file, NULL) &
epi->event.events;
/* */
if (revents) {
if (__put_user(revents, &uevent->events) ||
__put_user(epi->event.data, &uevent->data)) {
list_add(&epi->rdllink, head);
return eventcnt ? eventcnt : -EFAULT;
}
eventcnt++;
uevent++;
/* */
if (epi->event.events & EPOLLONESHOT)
epi->event.events &= EP_PRIVATE_BITS;
/* : , file fd * */
else if (!(epi->event.events & EPOLLET)) {
list_add_tail(&epi->rdllink, &ep->rdllist);
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JAVA 다 중 스 레 드 메커니즘 의 스 레 드 생 성target 을 실행 대상 으로 지정 한 name 을 이름 으로 하고 group 에서 참조 하 는 스 레 드 그룹의 일원 으로 새 Thread 대상 을 할당 합 니 다. 이 스 레 드 가 독립 된 Runnable 실...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.