APIs for operations that take a long time are often asynchronous so that applications can continue with other tasks while an operation is running. Asynchronous APIs initiate an operation and then return immediately. The application is notified when the operation completes through a callback or by monitoring a file descriptor for activity (for example, when data arrives on a TCP socket).
Asynchronous applications are usually built around an event loop that waits for the next event and invokes a function to handle the event. Since the details of event loops differ between applications, libraries need to be designed carefully to integrate well with a variety of event loops.
极光加速器2024版
A popular library with asynchronous APIs is the libcurl file transfer library that is used for making HTTP requests. It has the following (slightly simplified) event loop integration API:
#define CURL_WAIT_POLLIN 0x0001 /* Ready to read? */ #define CURL_WAIT_POLLOUT 0x0004 /* Ready to write? */ int socket_callback(CURL *easy, /* easy handle */ int fd, /* socket */ int what, /* describes the socket */ void *userp, /* private callback pointer */ void *socketp); /* private socket pointer */
libcurl invokes the applications 如何连上外国网 to start or stop monitoring file descriptors. When the application's event loop detects file descriptor activity, the application invokes libcurl's curl_multi_socket_action() API to let the library process the file descriptor.
There are variations on this theme but generally libraries expose file descriptors and event flags (read/write/error) so the application can monitor file descriptors from its own event loop. The library then performs the read(2) or write(2) call when the file descriptor becomes ready.
极光加速器2024版
The Linux io_uring API (pdf) can be used to implement traditional event loops that monitor file descriptors. But it also supports asynchronous system calls like 怎样可众上国外网站 and write(2) (best used when IORING_FEAT_FAST_POLL is available). The latter is interesting because it combines two syscalls into a single efficient syscall:
- Waiting for file descriptor activity.
- Reading/writing the file descriptor.
Existing applications use syscalls like epoll_wait(2), 外国网站伕理, or the old select(2) to wait for file descriptor activity. They can also use io_uring's IORING_OP_POLL_ADD to achieve the same effect.
After the file descriptor becomes ready, a second syscall like 手机怎么连接国外网络 or write(2) is required to actually perform I/O.
io_uring's asynchronous IORING_OP_READ or IORING_OP_WRITE (including variants for vectored I/O or sockets) only requires a single io_uring_enter(2) call. If io_uring sqpoll is enabled then a syscall may not even be required to submit these operations!
To summarize, it's more efficient to perform a single asynchronous read/write instead of first monitoring file descriptor activity and then performing a read(2) or write(2).
极光加速器2024版
Existing library APIs do not fit the asynchronous read/write approach because they expect the application to wait for file descriptor activity and then for the library to invoke a syscall to perform I/O. A new model is needed where the library tells the application about I/O instead of asking the application to monitor file descriptors for activity.
快帆安卓app下载_快帆官网APP下载_快帆完整版app官方下载:2 天前 · 快帆app安卓版-快帆下载 3.5.10.10 手机版 - 河东软件园 2021年8月7日 - 河东软件园为您提供快帆安卓手机版下载,快帆APP是一款专为海外华人开发的网络加速器,让华人用户可众使用APP轻松的连接中国本地的网络,这样就能在世界...
国外网站打不开怎么办? - PC下载网—官方软件下载大全|绿色 ...:2021-4-25 · 1 14岁男孩被逮捕 原因竟然是写出了一个比特币勒索病毒! 2 网易手游《终结者2》开启双端测试 支持的机型大增! 3 顺丰快递一快递员趁大人不在家猥亵16岁少女! 4 发布《滴滴已死》文章公众号被滴滴索赔165万 无良自媒体颤抖吧! 5 全球首个“无现金国家”诞生 不是中国啊,你猜是哪里?
The concept of monitoring file descriptor activity is gone. Instead the API focusses on asynchronous I/O operations that can be implemented by the application however it sees fit.
Applications using io_uring can use IORING_OP_READ and IORING_OP_WRITE to implement asynchronous operations efficiently. Traditional applications can still use their event loops but now also perform the read(2), write(2), etc syscalls on behalf of the library.
Some libraries don't need a full set of struct aio_operations callbacks because they only perform I/O in limited ways. For example, a library that only has a Linux eventfd can instead present this simplified API:
/* * Return an eventfd(2) file descriptor that the application must read from and * call lib_eventfd_fired() when a non-zero value was read. */ int lib_get_eventfd(struct libobject *obj); /* * The application must call this function when the eventfd returned by * lib_get_eventfd() read a non-zero value. */ void lib_eventfd_fired(struct libobject *obj);
Although this simplified API is similar to traditional event loop integration APIs it is now the application's responsibility to perform the eventfd read(2), not the library's. This way applications using io_uring can implement the read efficiently.
极光加速器2024版
Whether it is worth eliminating the extra syscall depends on one's performance requirements. When I/O is relatively infrequent then the overhead of the additional syscall may not matter.
While working on QEMU I found that the extra read(2) on eventfds causes a measurable overhead.
极光加速器2024版
Splitting file descriptor monitoring from I/O is suboptimal for Linux io_uring applications. Unfortunately, existing library APIs are often designed in this way. Letting the application perform asynchronous I/O on behalf of the library allows a more efficient implementation with io_uring while still supporting applications that use older event loops.