I believe poll and epoll have been used to read this article. Let's look at the source code of the poll system call.
asmlinkage long sys_poll(struct pollfd __user * ufds, unsigned int nfds, long timeout){struct poll_wqueues table;int fdcount, err;unsigned int i;struct poll_list *head;struct poll_list *walk;/* Do a sanity check on nfds ... */if (nfds > current->files->max_fdset && nfds > OPEN_MAX) //(1)return -EINVAL;if (timeout) { //(2)/* Careful about overflow in the intermediate values */if ((unsigned long) timeout < MAX_SCHEDULE_TIMEOUT / HZ)timeout = (unsigned long)(timeout*HZ+999)/1000+1;else /* Negative or overflow */timeout = MAX_SCHEDULE_TIMEOUT;}poll_initwait(&table); //(3)head = NULL;walk = NULL;i = nfds;err = -ENOMEM;while(i!=0) { //(4)struct poll_list *pp;pp = kmalloc(sizeof(struct poll_list)+sizeof(struct pollfd)*(i>POLLFD_PER_PAGE?POLLFD_PER_PAGE:i),GFP_KERNEL);if(pp==NULL)goto out_fds;pp->next=NULL;pp->len = (i>POLLFD_PER_PAGE?POLLFD_PER_PAGE:i);if (head == NULL)head = pp;elsewalk->next = pp;walk = pp;if (copy_from_user(pp->entries, ufds + nfds-i, sizeof(struct pollfd)*pp->len)) {err = -EFAULT;goto out_fds;}i -= pp->len;}fdcount = do_poll(nfds, head, &table, timeout);(5)/* OK, now copy the revents fields back to user space. */walk = head;err = -EFAULT;while(walk != NULL) {(6)struct pollfd *fds = walk->entries;int j;for (j=0; j < walk->len; j++, ufds++) {if(__put_user(fds[j].revents, &ufds->revents))goto out_fds;}walk = walk->next;}err = fdcount;if (!fdcount && signal_pending(current))err = -EINTR;out_fds:walk = head;while(walk!=NULL) {struct poll_list *pp = walk->next;kfree(walk);walk = pp;}poll_freewait(&table);return err;}
(1) check whether the maximum number of file descriptor sets meets the requirements.
(2) Check timeout and process it.
(3) The function initialization type is poll_wqueues table,
1. Void poll_initwait (structpoll_wqueues * pwq)
2 .{
3. init_poll_funcptr (& pwq-> PT, _ pollwait );
4. pwq-> error = 0;
5. pwq-> table = NULL;
6 .}
We can see that the poll_wqueues struct is initialized in the function. Let's look at its meaning.
1. struct poll_wqueues {
2. poll_table pt;
3. struct poll_table_page * table;
4. Int error;
5 .};
Each poll_wqueue corresponds to each poll call. PT is an external interface.
Next let's look at poll_table:
1. typedef struct poll_table_struct {
2. poll_queue_proc qproc;
3.} poll_table;
We can see that during initialization, the _ pollwait function is assigned to the poll queue processing function in poll_table (literally translated ). This function is called in the poll_wait function. The poll function in the driver calls the poll_wait function. What does _ pollwait do? Here we reference others' figures:
Someone may ask why an array with a number of 0 is needed, which is the next structure that facilitates finding the neighbor.
Let's go back to sys_poll and look down.
(4) The function of this loop is to copy the file descriptor to the kernel state from the user State. Note that a linked list is created here. If you want to listen to many descriptors and more than one page, you need to allocate multiple pages, which may affect the performance.
(5) Here is a do_poll function. View Source Code:
static int do_poll(unsigned int nfds, struct poll_list *list,struct poll_wqueues *wait, long timeout){int count = 0;poll_table* pt = &wait->pt;if (!timeout)pt = NULL;for (;;) {struct poll_list *walk;set_current_state(TASK_INTERRUPTIBLE);walk = list;while(walk != NULL) {do_pollfd( walk->len, walk->entries, &pt, &count);walk = walk->next;}pt = NULL;if (count || !timeout || signal_pending(current))break;count = wait->error;if (count)break;timeout = schedule_timeout(timeout);}__set_current_state(TASK_RUNNING);return count;}
Do_pollfd is used to call the corresponding poll functions for each uploaded FD. The Calling process is simplified as follows:
Struct file * file = fget (FD );
File-> f_op-> poll (file, & (Table-> pt ));
"If FD corresponds to a socket, do_pollfd calls the poll implemented by the network device driver. If FD corresponds to an ext3 File
Do_pollfd calls the poll implemented by the ext3 file system driver. In a word, this file-
> F_op-> poll is implemented by the device driver. What is the poll Implementation of the device driver? In fact, the device driver
The standard implementation of the program is: Call poll_wait, that is, the device's own waiting queue as the parameter (usually the device has its own waiting queue, no
However, a device that does not support asynchronous operations will be very depressing) Call the structpoll_table callback function ."
(6) copy the result back to the user State.