eventepoll2
다음 에 보 겠 습 니 다. epoll 조작 함수 epoll_ctl
SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
struct epoll_event __user *, event)
{
int error;
struct file *file, *tfile;
struct eventpoll *ep;
struct epitem *epi;
struct epoll_event epds;
error = -EFAULT;
/* , struct epoll_event */
if (ep_op_has_event(op) &&
copy_from_user(&epds, event, sizeof(struct epoll_event)))
goto error_return;
/* Get the "struct file *" for the eventpoll file */
error = -EBADF;
/* epfd epoll fdtable : rcu */
file = fget(epfd);
if (!file)
goto error_return;
/* , file fd */
tfile = fget(fd);
if (!tfile)
goto error_fput;
/* The target file descriptor must support poll */
error = -EPERM;
/* poll , epoll EnhancePoll 。。 */
if (!tfile->f_op || !tfile->f_op->poll)
goto error_tgt_fput;
/*
* We have to check that the file structure underneath the file descriptor
* the user passed to us _is_ an eventpoll file. And also we do not permit
* adding an epoll file descriptor inside itself.
*/
/* , 。 , 11 3 kernel bug , */
error = -EINVAL;
if (file == tfile || !is_file_epoll(file))
goto error_tgt_fput;
/*
* , epoll_event
*/
ep = file->private_data;
/* , !*/
mutex_lock(&ep->mtx);
/* ( ep->rbr.rb_node ) RBTree fd struct epitem.
*/
epi = ep_find(ep, tfile, fd);
error = -EINVAL;
switch (op) {
case EPOLL_CTL_ADD:
if (!epi) {
/* , POLLERR | POLLHUP */
epds.events |= POLLERR | POLLHUP;/
/* : struct epitem. , 。 */
error = ep_insert(ep, &epds, tfile, fd);
} else
error = -EEXIST;
break;
case EPOLL_CTL_DEL:
if (epi)
error = ep_remove(ep, epi);
else
error = -ENOENT;
break;
case EPOLL_CTL_MOD:
if (epi) {
epds.events |= POLLERR | POLLHUP;
error = ep_modify(ep, epi, &epds);
} else
error = -ENOENT;
break;
}
mutex_unlock(&ep->mtx);
/* poll struct file 2 */
error_tgt_fput:
fput(tfile);
/* eventpoll , fput struct file , file_table ,
error_fput:dany
fput(file);
error_return:
return error;
}
자, 다음은 재 미 있 는 것 을 보 겠 습 니 다. ep_insert
보고 있다 epinert 이전 ,저희 가 일단 추억 을 떠 올 려 보도 록 하 겠 습 니 다. poll
우 리 는 모두 Liux 에 있다 는 것 을 안다. VFS 모델 struct file_operations 하나 있다 위대 하 다 poll 함수 포인터
unsigned int (*poll) (struct file *, struct poll_table_struct *);
예 를 들다 , 그냥 흔 한 걸 로. scsi 그래.
static unsigned int tgt_poll(struct file * file, struct poll_table_struct *wait)
{
//....
/*tgt_poll_wait 이 장치 의 대기 열 입 니 다. 일단 알 아야 돼. poll_wait 막 히 지 않 습 니 다. ,
* 그리고 사실은 호출 하 러 가 는 거 예요. struct poll_table 등록 qproc 함수 포인터 * /
poll_wait(file, &tgt_poll_wait, wait);
spin_lock_irqsave(&ring->tr_lock, flags);
idx = ring->tr_idx ? ring->tr_idx - 1 : TGT_MAX_EVENTS - 1;
ev = tgt_head_event(ring, idx);
if (ev - > hdr. status) / * 상부 에 사용 할 표지 위 치 를 설정 합 니 다 * /
mask |= POLLIN | POLLRDNORM;
spin_unlock_irqrestore(&ring->tr_lock, flags);
return mask;
}
사실 poll 딱 한 가지 일 을 했다. ,현재 file 로 돌아 가기 fd 상태 . select 비교적 멍청 하 다. 그 는 집합 안의 모든 자 리 를 한 번 옮 겨 다 녔 다. __FD SETSIZE 개) ACE 몇 가지 해결 방법 을 제 공 했 는데 그 중에서 가장 좋 은 것 은 ACE Select Reactor 입 니 다. 이 이후 의 분석 은 논문 한 편 을 인용 한 것 같 습 니 다. (ACE 사실은 많은 논문 의 실현 이다.)
좋다 다음은 재 미 있 는 ep insert 를 시작 하 겠 습 니 다.
static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
struct file *tfile, int fd)
{
int error, revents, pwake = 0;
unsigned long flags;
struct epitem *epi;
struct ep_pqueue epq;
/* epoll fd */
if (unlikely(atomic_read(&ep->user->epoll_watches) >=
max_user_watches))
return -ENOSPC;
/* struct epitem , file fd*/
if (!(epi = kmem_cache_alloc(epi_cache, GFP_KERNEL)))
return -ENOMEM;
/* ; struct file epoll ; */
INIT_LIST_HEAD(&epi->rdllink);
INIT_LIST_HEAD(&epi->fllink);
INIT_LIST_HEAD(&epi->pwqlist);
epi->ep = ep;/* */
/* struct epoll_filefd RBTree */
ep_set_ffd(&epi->ffd, tfile, fd);
/* epoll_event */
epi->event = *event;
epi->nwait = 0;
epi->next = EP_UNACTIVE_PTR;
/* Initialize the poll table using the queue callback */
epq.epi = epi;
/* poll , poll_wait ,
*ep_ptable_queue_proc , */
init_poll_funcptr(&epq.pt, ep_ptable_queue_proc);
/*
* Attach the item to the poll hooks and get current event bits.
* We can safely use the file* here because its usage count has
* been increased by the caller of this function. Note that after
* this operation completes, the poll callback can start hitting
* the new item.
*/
/* : , poll_wait , , */
revents = tfile->f_op->poll(tfile, &epq.pt);
/* poll_wait , */
error = -ENOMEM;
if (epi->nwait < 0)
goto error_unregister;
/* file fd , struct epitm file epoll */
spin_lock(&tfile->f_lock);
list_add_tail(&epi->fllink, &tfile->f_ep_links);
spin_unlock(&tfile->f_lock);
/* RBTree */
ep_rbtree_insert(ep, epi);
/* We have to drop the new item inside our item list to keep track of it */
spin_lock_irqsave(&ep->lock, flags);
/* stuct file , epi ready */
/* If the file is already "ready" we drop it inside the ready list */
if ((revents & event->events) && !ep_is_linked(&epi->rdllink)) {
/* " " eventpoll -> file fd */
list_add_tail(&epi->rdllink, &ep->rdllist);
/* eventpoll ( ) poll ( )
* , ep_insert ep_modify scan_ready_list */
if (waitqueue_active(&ep->wq))
wake_up_locked(&ep->wq);
if (waitqueue_active(&ep->poll_wait))
pwake++;
}
spin_unlock_irqrestore(&ep->lock, flags);
atomic_inc(&ep->user->epoll_watches);
/* ( ) poll */
if (pwake)
ep_poll_safewake(&ep->poll_wait);
return 0;
/* */
error_unregister:
ep_unregister_pollwait(ep, epi);
spin_lock_irqsave(&ep->lock, flags);
if (ep_is_linked(&epi->rdllink))
list_del_init(&epi->rdllink);
spin_unlock_irqrestore(&ep->lock, flags);
kmem_cache_free(epi_cache, epi);
return error;
}
,
init_poll_funcptr(&epq.pt, ep_ptable_queue_proc);
ep_ptable_queue_proc poll_wait
epoll file fd entry ,
struct eppoll_entry {
/* struct epitem poll */
struct list_head llink;
/* ... */
struct epitem *base;
/* */
wait_queue_t wait;
/* */
wait_queue_head_t *whead;
};
static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,
poll_table *pt)
{
/* poll_table ep_pqueue , ep_pqueue : struct epitem *epi;*/
struct epitem *epi = ep_item_from_epqueue(pt);
/* eppoll_entry , */
struct eppoll_entry *pwq;
/* slab eppoll_entry */
if (epi->nwait >= 0 && (pwq = kmem_cache_alloc(pwq_cache, GFP_KERNEL))) {
/* struct eppoll_entry , ep_poll_callback */
init_waitqueue_func_entry(&pwq->wait, ep_poll_callback);
pwq->whead = whead;
pwq->base = epi;
/* whead */
add_wait_queue(whead, &pwq->wait);
/* struct eppoll_entry pwq struct epitem epi pwqlist ,
entry */
list_add_tail(&pwq->llink, &epi->pwqlist);
epi->nwait++;
} else {
/* We have to signal that an error occurred */
epi->nwait = -1;
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
정수 반전Udemy 에서 공부 한 것을 중얼거린다 Chapter3【Integer Reversal】 (예) 문자열로 숫자를 반전 (toString, split, reverse, join) 인수의 수치 (n)가 0보다 위 또는 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.