What is the difference between posix aio and freebsd aio? - linux

Could someone please explain the differences between posix AIO and freebsd AIO? Seems the functions are the same, aio_read/aio_write.
I understand that linux native AIO is only available in Linux, and uses io_setup/io_submit, etc

FreeBSD AIO is also kernel based, which means it doesn't try to emulate asynchronous operations by spawning user-mode thread and running IO operations there.
As the man page says:
the calling thread invokes one system call to request an asynchronous I/O operation.

Related

P/invoke and overlapped I/O in Core CLR on Unix?

I know that .Net Core can run on Mac and Unix.
What happens to Win32 classes like the overlapped I/O and how do an I/O request packet translate into Unix?
If I correctly understand, those win32 classes and structures are the basis of async/await with P/Invoke I/O instructions.
There is a platform abstraction layer implemented by the CoreCLR that handles the implementation using the appropriate OS capabilities for asynchronous I/O. For example, on platforms that support kevent (such as FreeBSD and macOS), they will use kqueue for queuing and raising I/O callbacks. This is one of the many areas, but a good place to start understanding the CoreCLR and tie it back to the managed implementations.
https://github.com/dotnet/coreclr/blob/dd1e7ab81221127e47d59052c51c09921007d607/src/pal/src/synchmgr/synchmanager.cpp#L2103

Is libuv under the hood use epoll or select(2) in unix

I have been reading around how nodejs uses libuv to perform asynchronous I/O. Reading more about it give me a feeling that it almost sound similar to how select(2) and epoll.
So, my question if I'm using libuv(via node) is it true internally I using select(2) or epoll.
Is libuv is wrapper over select(2) and epoll system call in unix.?
libuv uses the most performant polling mechanism for every platform: that means epoll on Linux, kqueue on macOS and BSDs, /dev/poll on SunOS, etc. One interesting trick libuv does is it uses select() on a thread for some fds kqueue is unable to handle. I gave some details about that here: http://code.saghul.net/index.php/2016/05/24/libuv-internals-the-osx-select2-trick/

What is the implementation detail of libevent? An encapsulation of poll mechanism?

libevent provides programmers the ability to write asynchronous programs due to the event notifications and callback function supports. I don't know if the linux kernel provides such system calls to notify user space applications when a particular event occurs. When people use non-blocking operations, they have to poll all the file descriptors to check whether some of them are ready. However, I think libevent maybe utilize some other advanced means to fulfill this task, e.g. with some unbeknown system calls.
So, 1) how does libevent check the status of different events? By polling or other mechanism? 2) Does libevent forks subprocesses of threads when it runs?
The libevent home page reads (in part),
Currently, libevent supports /dev/poll, kqueue(2), event ports, POSIX select(2), Windows select(), poll(2), and epoll(4).
For modern Linux the answer is thus epoll.

How to trap system calls in a userspace library in Linux?

I have a requirement to write a linux device driver in userspace.
How can I write a library which, when linked to an application, can handle system calls to a particular device.
The application should be able to use open(), read(), write(), ioctl() on a device such as /dev/mydev0, but these calls should terminate in a userspace library instead of a kernel module.
Please advise on if this is possible and how can I achieve this.
Linux is a monolithic kernel which means in general, what you're asking is not possible; you can't write arbitrary drivers in user-mode.
You could (as your title alludes to), use ptrace(2) to trap on system calls, and basically redirect them to functions in your library. That is not a simple, straightforward solution however.
See also:
How to use ptrace(2) to change behaviour of syscalls?
FUSE (Filesystem in USErspace) may be what you're looking for. It's a mechanism that allows filesystem drivers specifically to be implemented via a user-space process. This is how sshfs, for example, is implemented.
Resources:
http://fuse.sourceforge.net/

Linux and I/O completion ports?

Using winsock, you can configure sockets or seperate I/O operations to "overlap". This means that calls to perform I/O are returned immediately, while the actual operations are completed asynchronously by separate worker threads.
Winsock also provides "completion ports". From what I understand, a completion port acts as a multiplexer of handles (sockets). A handle can be demultiplexed if it isn't in the middle of an I/O operation, i.e. if all its I/O operations are completed.
So, on to my question... does linux support completion ports or even asynchronous I/O for sockets?
If you're looking for something exactly like IOCP, you won't find it, because it doesn't exist.
Windows uses a notify on completion model (hence I/O Completion Ports). You start some operation asynchronously, and receive a notification when that operation has completed.
Linux applications (and most other Unix-alikes) generally use a notify on ready model. You receive a notification that the socket can be read from or written to without blocking. Then, you do the I/O operation, which will not block.
With this model, you don't need asynchronous I/O. The data is immediately copied into / out of the socket buffer.
The programming model for this is kind of tricky, which is why there are abstraction libraries like libevent. It provides a simpler programming model, and abstracts away the implementation differences between the supported operating systems.
There is a notify on ready model in Windows as well (select or WSAWaitForMultipleEvents), which you may have looked at before. It can't scale to large numbers of sockets, so it's not suitable for high-performance network applications.
Don't let that put you off - Windows and Linux are completely different operating systems. Something that doesn't scale well on one system may work very well on the other. This approach actually works very well on Linux, with performance comparable to IOCP on Windows.
IOCP is pronounced "asynchronous I/O" on various UNIX platforms:
POSIX AIO is the standard
Kernel AIO, epoll and io_uring seem to be a Linux-specific implementations
Kqueue is the *BSD and Mac OSX implementation
Message Passing Interface (MPI) is an option for high-performance computing
obligatory Boost reference - Boost.Asio
Use boost::asio. Hands down. It has a mild learning curve, but it's cross-platform, and automatically uses the best available method for the system you're compiling on. There's simply no reason not to.
I know that this isn't quite an answer to your question, but it's the best advice I could give.
So, on to my question... does linux support completion ports or even asynchronous I/O for sockets?
With regard to sockets, in 5.3 and later kernels, Linux has something analogous to completion ports in the shape of io_uring (for files/block devices io_uring support appeared in the 5.1 kernel).
Read the blog entry from Google on libevent, you can implement IOCP semantics on Unix using asynchronous IO but cannot directly implement asynchronous IO semantics using IOCP,
http://google-opensource.blogspot.com/2010/01/libevent-20x-like-libevent-14x-only.html
For an example cross platform asynchronous IO with a BSD socket API look at ZeroMQ as recently published on LWN.net,
http://www.zeromq.org/
LWN article,
http://lwn.net/Articles/370307/
Boost ASIO implements Windows style IOCP (Proactor design pattern) on Linux using epoll (Reactor pattern). See http://think-async.com/Asio/asio-1.5.3/doc/asio/overview/core/async.html

Resources