Linux 异步 IO 之 eventfd

经过 3 个月的休(tou)息(lan),是时候写点东西了……

eventfd

较新版本的 Linux 内核(2.6.22 之后)提供了一个新的系统调用 eventfd() 来实现事件通知(参考资料 [1]):

#include <sys/eventfd.h>

int eventfd(unsigned int initval, int flags);

函数返回一个可用于 read()/write()/epoll()/close() 的 fd,fd 包含一个由内核维护的 8 字节的无符号整数,初始值由第一个参数 initval 制定。write() 的 buffer 大小都限定为 8 字节,如果 buffer 大小不等于 8 字节则会返回错误,如果提供给 read() 的大小小于 8 …

阅读全文…

Linux 异步 IO 之 Native AIO

Linux Native AIO

来看看 Linux 提供的 AIO 系统调用(自行封装的头文件 native_aio.h):

#ifndef __NATIVE_AIO_H__
#define __NATIVE_AIO_H__

#define _GNU_SOURCE

#include <unistd.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <linux/aio_abi.h>

static inline int io_setup(unsigned nr_events, aio_context_t* ctx_idp)
{
    return syscall(__NR_io_setup, nr_events, ctx_idp);
}

static inline int io_destroy(aio_context_t 

阅读全文…

Linux 异步 IO 之 POSIX AIO

先来看一个简单的读写文件程序,程序读取源文件,然后把内容打印到屏幕上:

#include <unistd.h>
#include <fcntl.h>

#define BUFSIZE 4096

int main(void)
{
    int fd, nbytes;
    char buf[BUFSIZE];

    fd = open(__FILE__, O_RDONLY);
    while ((nbytes = read(fd, buf, BUFSIZE)) > 0)
        write(1, buf, nbytes);

    close(fd);
    return 0;
}

在这个例子中的 read()/write() 都是同步阻塞 IO,即如果没有数据可读或写入未完成时当前线程会一直等待,直到读写操作完成或出错才会返回。

同步 …

阅读全文…

Linux 异步 IO 之 epoll

epoll 是 Linux 内核在 2.5 引入的一个 I/O 事件通知机制,用来取代旧的 select(2) 和 poll(2)。

select() 的工作模式

从通知机制上说,select() 的方式和 epoll 的方式类似,都是阻塞在某个函数上,如果有指定的 I/O 事件发生的话函数就会返回。这样的通知机制的好处在于,在没有事件发生的时候系统可以去干别的事情。不过 select() 只告诉你有事件发生了,但是没有说清楚是哪些 fd 触发了事件通知,你需要去遍历所有的 fd 来找出哪些真正需要处理。select() 的函数原型如下:

int select(int nfds, fd_set *readfds, fd_set *writefds,
           fd_set *exceptfds, struct timeval *timeout);

fd_set 是一个 …

阅读全文…

使用 inotify 监控目录和文件的状态

概述

很多时候程序需要对文件状态进行监控,例如在命令行中删掉一个文件,图形界面中的文件管理器也要把这个文件去掉(如果文件管理器正在显示被删除文件所在的目录);如果试图用 vim 保存一个文件,而该文件在修改的时候被其它程序修改过,那么 vim 会给出警告说文件已经发生改变。如果需要对文件状态进行实时监控,一个方法是保存文件的状态,然后不停地扫描目录或文件,如果和上一次保存的状态不一致则发出信号,但是这样的做法效率很低。最好的做法是能够向系统注册一个回调函数,当我们需要监控的目录或文件发生改变时调用回调函数,这样程序就能马上得到通知。

根据参考资料 [1],inotify 之前的文件状态监控机制是 dnotify。dnotify 中的“d”指的是目录,只能监控目录事件的变化,即在该目录下的创建/删除文件引起的事件,但是却不能监控文件本身状态的改变(如读写/访问文件),如果需要实现这样的功能需要应用程序自己比较文件状态。

在 2.6.13 的时候引入的 inotify 提供了比 dnotify 更强大的功能,除了目录还可以对文件状态进行监控。并且它不像 dnotify,每监控一个目录/文件都需要打开一个文件描述符,因此不会影响移动介质的 unmount。从接口形式和功能上看,inotify 和 epoll 很像,只是两者监控的事件类型不一样。

09 年出现了 fanotify(参考资料 [2]),据说是 inotify 的下一代,不过目前来看功能还不如 inotify。

对目录的监控

作为 inotify 的第一个示例,程序会在 /tmp/abc 被创建/删除/移动时打印相应的信息:

#include <stdio.h>
#include <string.h>

阅读全文…