So what's the difference with io_uring?
In contrast io_uring is a completion notification API. You give it a buffer to read or write from/to, and it'll notify you when the IO has been completed.
Io_uring is also more flexible, and can for example be used for disk IO which epoll can't.