add epoll
This commit is contained in:
89
notes/advanced-techniques.md
Normal file
89
notes/advanced-techniques.md
Normal file
@@ -0,0 +1,89 @@
|
||||
# Advanced Techniques
|
||||
|
||||
- [Advanced Techniques](#advanced-techniques)
|
||||
- [Blocking](#blocking)
|
||||
- [poll() - Synchronous I/O Multiplexing](#poll---synchronous-io-multiplexing)
|
||||
- [epoll() - I/O Event Notification (Async)](#epoll---io-event-notification-async)
|
||||
|
||||
### Blocking
|
||||
All the Unix networking functions are **blocking**. What does it mean? It means that if you write `accept()` or `recv()` it will wait until some data appears. So how we can avoid this? Making the socket non blocking so we can poll the socket for info:
|
||||
|
||||
```c
|
||||
fcntl(sockfd, F_SETFL, O_NONBLOCK);
|
||||
```
|
||||
|
||||
`F_SETFL`: set the file descriptor flags
|
||||
`O_NONBLOCK`: make the fd non blocking
|
||||
|
||||
### poll() - Synchronous I/O Multiplexing
|
||||
The plan is to have a `struct pollfd` with the info about which sockets fd we want to monitor. The Operating System will block on the `poll()` call until one event occurs (e.g. "socket ready to write/read").
|
||||
|
||||
```c
|
||||
#include <poll.h>
|
||||
|
||||
int poll(struct pollfd fds[], nfds_t nfds, int timeout);
|
||||
```
|
||||
|
||||
`fds` is our array of info (which sockets to monitor)
|
||||
`nfds` the elements in the array
|
||||
`timeout` in milliseconds (-1 to wait forever)
|
||||
|
||||
```c
|
||||
struct pollfd {
|
||||
int fd; // the socket descriptor
|
||||
short events; // bitmap of events we're interested in
|
||||
short revents; // when poll() returns, bitmap of events that occurred
|
||||
};
|
||||
```
|
||||
|
||||
`events` is a bitmap of the following values:
|
||||
- `POLLIN` (alert when I can read data)
|
||||
- `POLLOUT` (alert when I can send data)
|
||||
|
||||
**I won't continue this section, read below**
|
||||
|
||||
### epoll() - I/O Event Notification (Async)
|
||||
It is similar to `poll()` but more efficient when dealing with lots of fds. The array is in the kernel space, no further copies. Nice explaination [here](https://copyconstruct.medium.com/the-method-to-epolls-madness-d9d2d6378642).
|
||||
|
||||
```c
|
||||
#include <sys/epoll.h>
|
||||
|
||||
int epoll_create1(int flags);
|
||||
```
|
||||
|
||||
Just pass 0 for the `flags`, it is an improved version of the `epoll_create()`. It creates a new epoll instance nad returns the fd of that instance.
|
||||
|
||||
```c
|
||||
#include <sys/epoll.h>
|
||||
|
||||
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
|
||||
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
|
||||
```
|
||||
|
||||
- `epoll_ctl()` is used to register new fds and add them to the interest list:
|
||||
- `epfd` epoll file descriptor
|
||||
- `op` the operation: `EPOLL_CTL_ADD`, `EPOLL_CTL_MOD` or `EPOLL_CTL_DEL`
|
||||
- `fd` the file descriptor to check
|
||||
- `event` a pointer to the `epoll_event` struct
|
||||
|
||||
- `epoll_wait()` waits for I/O events, blocking the calling thread if no events are availables.
|
||||
- `epfd` epoll file descriptor
|
||||
- `events` array where there will be saved ready events
|
||||
- `maxevents` max events per array
|
||||
- `timeout` in milliseconds (-1 forever)
|
||||
|
||||
```c
|
||||
struct epoll_event {
|
||||
uint32_t events; // bitmap
|
||||
epoll_data_t data;
|
||||
};
|
||||
|
||||
union epoll_data {
|
||||
void *ptr;
|
||||
int fd; // just use this
|
||||
uint32_t u32;
|
||||
uint64_t u64;
|
||||
};
|
||||
```
|
||||
|
||||
**TODO: improve the notes for epoll()**
|
||||
Reference in New Issue
Block a user