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,即如果没有数据可读或写入未完成时当前线程会一直等待,直到读写操作完成或出错才会返回。

同步 …

阅读全文…

c++11 之变长参数模板

C++ 中可以对函数重载,即同样的函数名字(其实在编译期还是会被生成不同的名字)可以有不同的参数列表,例如 STL 中 string 的构造函数:

string();
string (const string& str);
string (const string& str, size_t pos, size_t len = npos);
string (const char* s);
string (const char* s, size_t n);
...

看上去和 C 中的变长参数有点类似:

void func(int nil, ...);

有点不同的是,C …

阅读全文…

PostgreSQL 笔记

PostgreSQL 是一个采用 BSD 许可证分发的跨平台的对象关系模型数据库,最早可以追溯到 1982 年在伯克利开始的 Ingres 计划。PostgreSQL 出现的时间比 MySQL 要早,之前也听过 PostgreSQL 的大名,不过看到相关的讨论比较少。由于这里的实验需求远未达到两者的极限,所以也没什么评测,网上的评价就不搬运过来了,有兴趣的可以搜一下。这里的实验环境是 Debian 6,PostgreSQL 版本是 9.1。

初始化

不同于 MySQL 在安装的时候会被要求输入 root 的密码,安装 PostgreSQL 的时候什么提示都没有,装完之后也不知道该干嘛……在网上搜了一把,照着参考资料 [1] 操作了一遍,基本算是入门了。

由于没有 root 用户,默认有 root 权限的用户名是 postgres,也有同名的数据库。网上有很多介绍初始化的方法都是新建一个 postgres 的用户,然后切换到该用户登录后再修改密码。但是觉得为了初始化新建一个用户有点小题大作了,于是上网搜了下,发现可以通过修改配置文件达到目的。

首先修改 /etc/postgresql/9.1/main/pg_hba.conf,把其中的

local all postgres 

阅读全文…

B- 树

1972 年 R. Bayer 和 E. McCreight 的论文(参考资料 [1])提出了 B- 树。B- 树是一棵平衡树,与一般的平衡二叉树(AVL,红黑树等)不同的是,B- 树的每个节点最多可以拥有 m(m=2)个元素,(m+1)个子节点,并且所有的叶子节点位于同一层。B- 树的查找和插入的时间复杂度和二叉树一样,都是 O(logn),但因为每个节点保存的元素比较多(一般是几十个到几百个之间),树的高度比一般的二叉树要小很多,访问硬盘次数更少,在数据不能全部加载到内存的时候比一般的二叉树效率要好。

定义

一棵最多有 2n+1 个元素(其中 n= 1)的 B- 树的定义如下(参考资料 [2, 3]):

  • 每个节点最多有 2n+1 个元素;
  • 每个非叶子节点(根节点除外)至少有 n+1 棵子树;
  • 如果根节点不是叶子节点,则至少有 2 棵子树;
  • 一个有 k 棵子树的非叶子节点有

阅读全文…

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 是一个 …

阅读全文…

chroot 使用笔记

看了下最近很火很高大上的 Docker,比较好奇底层的实现机制,发现主要依赖 Linux Container(LXC) 和 cgroup,于是又了解了下 LXC,在看的过程中看到和 chroot 的比较,突然一些零散的片段在我脑海里迅速串起来……

一直在用 Debian 6,由于不爽 GNOME 3 所以没有升级,不过内核和 GCC 倒是在追新。传说 Debian 8 要使用 XFCE 作为默认桌面,小小期待一下。虽然不是什么狂热的追新族,但是在夜深人静的时候也会悄悄把源切到 unstable 然后 upgrade 看看有哪些自己喜欢的工具升级了。不过 unstable 的依赖关系经常处于不完整状态,有时安装一个包 apt-get 解析出来的关系能把整个系统都删掉,所以也有过几次搞坏系统的经历;而且重装了之后一些特定版本的软件又找不回来了,所以在有升级冲动的时候都会先对根分区备份一下(我的系统只有根目录和家目录)放到家目录里,万一搞坏了可以迅速恢复,而且备份之后的系统还可以作为镜像复制到其它机器上(中间就有过一次换电脑的经历,把旧的系统完整复制过来了)。

好吧,顺便记录一下系统备份和恢复的过程。首先用 U 盘或光盘装个 Live 系统(我用的是 SystemRescueCd ),备份的时候用启动盘启动,把硬盘上的根分区挂载到一个目录上然后在该目录下执行 tar(tar 在解压的时候会还原打包时的相对路径);恢复是同样的步骤,只是把打包变成解压。恢复的时候很多情况下 GRUB …

阅读全文…