Manual page inotify(7)

2008年9月17日 01:30

NAME

    INOTIFY 监测文件系统事件

DESCRIPTION

inotify API提供机制来监测文件系统事件。可以用来监测单独的文件或目录。当目录被监测时,inotify会返回目录自己的事件以及目录中文件的事件。

下列系统调用可以被使用:inotify_init, inotify_add_watch, inotify_rm_watch, read, close.

inotify_init 创建一个inotify实例并返回一个与该实例相关连的file descriptor。

inotify_add_watch 操作与inotify实例相关联的"watch list", watch list中的每一项"watch" 中指定了文件或目录的路径。kernel会监视与该路径相关文件有关的一些事件。inotify_add_watch创建一个新的watch item或修改一个已经存在的watch。 每一个watch都有一个独一无二的"watch descriptor", 一个在inotify_add_watch创建watch时返回的integer。

inotify_rm_watch 从watch list中删除一项。

当所有与inotify instance相关的file descriptors都被关闭后,其下所有相关的资源会被kernel释放并重用,所有相关的watches会自动被Free。

可以使用read操作inotify file descriptor来确定事件是否发生,如果事件没有发生,那么认为这个file descriptor是blocking的。read会block直到至少一个事件发生。

每次成功的read都会返回一个包含一个或多个以下结构的buffer:   

struct inotify event{
        int         wd;    /* Watch descriptor */
        uint32_t     mask;    /* 事件掩码 */
        uint32_t    cookie; /* 与事件相关的独一无二的cookie */
        uint32_t     len;    /* name的长度 */
        char        name[]; /* 可选的Null结尾的名字 */
    };

wd 指定了哪一个发生了事件,他是之前通过inotify_add_watch返回的watch descriiptors 之一

mask 有bits构成的事件内容

cookies 与相关事件相联系的独一无二的integer。当前仅用在rename事件中, 使IN_MOVE_FROM 与 IN_MOVE_TO 这一对事件产生的结果与应用程序相关联。

name 当一个被watch的目录中的文件触发事件后,name中包含了该文件相对于被watch目录的路径,该路径以Null结尾,并且该NULL之后读出多余的字节都以NULL填充。

len 是name中的字节数 包含NULL字节;每个inotify_event结构的长度都是sizeof(inotify_event)+len。

提供给read的buffer过小所产生的行为由于kernel的版本不同而不同: 在2.6.21以前的版本,read返回0; 2.6.21版本之后read失败 发生错误EINVAL

inotify 事件

inotify_add_watch中的mask参数与read返回的inotify_event结构中的mask字段中均包含的是inotifyevent的bit mask。下面的bits 用于在调用inotify_add_watch与read的mask中表示相关的事件。

IN_ACCESS    文件被使用(读) *
IN_ATTRIB    metadata被改变(权限,时间戳,扩展属性等等) *
IN_CLOSE_WRITE    以写权限打开的文件被关闭 *
IN_CLOSE_NOWRITE以非写权限打开的文件被关闭 *
IN_CREATE    文件/目录在watched的目录中被创建 *
IN_DELETE    文件/目录在watched的目录中被删除 *
IN_DELETE_SELF    watched的文件/目录被删除
IN_MODIFY    文件被修改 *
IN_MOVE_SELF    watched的文件/目录移动了
IN_MOVE_FROM    文件移出了watched的目录 *
IN_MOVE_TO    文件移入了watched的目录 *
IN_OPEN        文件被打开 *

当监测一个目录时,上面标注(*)的事件可以发生在目录下的文件中,这时返回的inotify_event结构中的name字段就指定了该目录下的文件名。

IN_ALL_EVENT宏包含了上述所有的事件。该宏可用于inotify_add_watch函数的mask参数中.

两个方便的宏:IN_MOVE   相当于 IN_MOVED_FROM|IN_MOVED_TO,IN_CLOSE 相当于 IN_CLOSE_WRITE|IN_CLOSE_NOEWRITE

下面一些额外的bit可以在inotify_add_watch中的mask参数中加入:

IN_DONT_FOLLOW        如果是symbolic link并不解析其中的路径
IN_MASK_ADD        如果watch已存在则在watch的mask中添加事件(代替了replace mask)
IN_ONESHOT        对该路径仅检测一个事件,触发后将其从watch list中删除
IN_ONLYDIR        仅在路径为目录时方加入watch

下面一些额外的bit可以在read中的mask参数中加入:

IN_IGNORED        watch被指定删除(inotify_rm_watch)或自动删除(文件被删除或文件系统被unmounted)
IN_ISDIR        该事件的目标是目录
IN_Q_OVERFLOW        事件队列溢出(该事件的wd = -1)
IN_UNMOUNT        包含watch目标的文件系统被unmount

/proc 接口
    下列的接口可以用来限制inotify消耗kernel memory的大小   

/proc/sys/fs/inotify/max_queued_evnets        

该文件中的值为调用inotify_init时分配给inotify instance中可排队的event的数目的最大值,超出这个值得事件被丢弃,但会触发IN_Q_OVERFLOW事件。   

/proc/sys/fs/inotify/max_user_instances       

其中指定了每一个real user ID可创建的inotify instatnces的数量上限   

/proc/sys/fs/inotify/max_user_watches       

指定了每个inotify instance相关联的watches的上限

注意   

Inotify file descriptors 可以使用select, poll, epoll来监视

如果在inotify file descriptor上连续发生的inotify事件是相同的(相同的wd, mask, cookie,name),那么他们会被合并到一个事件中

通过读inotify file descriptor返回的事件是排序的队列。

FIONREAD ioctl 返回从inotify file descriptor中可读的字节数

Inotify 监测目录并不是递归的:为了监视watch目录下的子目录 必须增加一个watch

BUGs   

2.6.16前的内核版本中, IN_ONESHOT mask标志不工作   

项目问题总结

2008年9月09日 18:49

编码问题

. 初始化问题 声明的结构一定要初始化 作为函数参数的变量一定要初始化 或置为NULL
. 记得free
. 文件名与函数名要起好.
. 线程进程间通信可使用pipe fifo.

设计问题

. 数据结构和模块要尽早定义, 各个模块间数据类型要统一
. 要考虑并发问题
. 每个模块要有各自的init与free函数
. 功能方面与协议尽早沟通.
. 通信过程中最好各个模块使用一个共同的结构.
. 自己编写的模块要有相应的测试代码.
. 多线程增加了代码的复杂度但是使模块间的耦合性降低,也使得逻辑清晰,否则后期的代码将杂乱无章且难看.
. 在使用一个未用过的库前 先把库中的函数都看一遍可以减少编码.
. 错误的程序也会得出正确的结果.

工具问题

. 使用valgrind来检测内存分配问题.
. 加注释 可使用doxygen

Vim 学习笔记

2008年8月25日 22:31

Vim user_05.txt

普通模式

移动

向上滚屏 CTRL-u                向下滚屏 CTRL-d

当前文本位于屏幕顶部 zt    中央 zz        底部 zb

词首移动 w   反向 b    词末移动 e   反向 ge

$ 移到行尾   0 移到行首   ^移到第一行非空字符

移动到指定字符x fx    反向查找 F \
                      > ;重复命令 ,反向重复
移动到指定字符x tx    反向查找 T /

括号匹配 %

确定位置 CTRL-G

移动到指定行 xG     移动到文件首 gg    移动到文件指定部分 x% 按百分比

屏幕上方H 屏幕中间M 屏幕下方L

跳转

跳转 CTRL-]    回跳 CTRL-O    来回跳转 CTRL-O CTRL-I

返回G跳转之前的位置 '

显示跳转位置列表 :jumps

标记当前光标位置 m[a-z]    跳到该标记行首'[a-z]        跳到该标记行首列上`[a-z]   

取得所有标记列表 :marks

编辑

连接两行 J

保存文件并退出 ZZ

撤销操作 u    回退命令 CTRL-R

修改文本 c2wbe<Esc>         cc修改一整行

替换单个字符 r            重复修改 .

p 粘贴        光标前粘贴 P         交换两个字符 xp

拷贝文本 y          删除一个单词 daw

文件间拷贝粘贴 visual模式下 拷贝"+y     粘贴"+p

删除

删除字符 x

删除一整行 dd

删除单词 dw        删除到行尾 d$

设置

显示模式 set showmode

加行号 set number 关闭 set nonumber

查找

反向查找 ?

查找忽略大小写 set ignorecase

查找当前单词 *   反向查找 #   遍历 n     

高亮匹配 set hlsearch       查找过程中显示匹配 set incsearch     到达文件结尾后停止查找 set nowrapscan

进入插入模式 i a

光标下方添加新行 o    光标上方添加新行 O

可视模式     v  

行选择可视模式 V    块选择 CTRL-v   移动到另一端 o 块模式下O   

替换模式 R

Vim 自定义语法颜色显示

文件放在 ~/.vim/after/syntax/下 C语言的文件为c.vim

分屏

:new                                                      
左右分屏          ctrl+w+v    分屏间切换    ctrl+w+w                
扩大窗口          ctrl+w+                 缩小窗口          ctrl+w-
到窗口左面      ctrl+w+h                  到窗口右面      ctrl+w+l
到窗口上面      ctrl+w+k                  到窗口下面      ctrl+w+j

CMake

2008年8月20日 22:58

简明的教程



变量赋值    set(VAR a b c)    VAR为变量名 a b c 为变量的值用空格分隔

变量使用    ${VAR}
例如:        set (Foo a b c)
        command (${Foo}) 相当于 command (a b c)

流程控制语句
1.    if

if(var)
    some_command(...)
endif(var)

2.    foreach and while

set (VAR a b c)
foreach (f ${VAR})
    message(${f})
endforeach(f)

3.    macro and function

//定义宏
macro (hello MESSAGE)
    message($ {MESSAGE})
endmacro (hello)
//调用
hello("hello world")
//定义函数
function (hello MESSAGE)
    message(${MESSAGE})
endfunction(hello)
//function与macro的区别: function create a local scope for variables.
//            macros user the global scope.

正则表达式
^     匹配 行或字符串的开始
$     匹配 行或字符串的结尾
.     匹配 除了新行外的任意单个字符
[]    匹配 括号内的任意字符
[^]    匹配 不在括号内的任意字符
[-]    匹配 在"-"两端范围中的字符
*    匹配 0个或多个之前的表达式
+    匹配 1个或多个之前的表达式
?    匹配 0个或1个之前的表达式
()    保存一个匹配表达式 用于之后的替换

常用命令
ADD_SUBDIRECTORY    添加一个子目录

INCLUDE            从给出的文件中读取CMake listfile代码
    INCLUDE(file1 [OPTIONAL])
    INCLUDE(module [OPTIONAL])
    file中的命令会立即处理 如果使用module代替file1 cmake将会在CMAKE_MODULE_PATH中寻找名为<modulename>.cmake的文件        

INCLUDE_DIRECTORIES    添加include目录到build中
    INCLUDE_DIRECTORIES([AFTER|BEFORE] [SYSTEM] dir1 dir2)

LINK_DIRECTORIES    指定搜索库的目录
    LINK_DIRECTORIES(directory1 directory2 ...)
    指定链接程序搜索库的路径


PROJECT            设置项目名
    PROJECT (projectname [CXX] [C] [JAVA])
    该命令会生成两个变量 projectname_BINARY_DIR与projectname_SOURCE_DIR 后面的选项为项目支持的语言 默认全部支持

SET            给一个CMAKE变量赋值
    SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])



模块(module)
FindPkgConfig    CMake 的pkg-config模块

    <PREFIX> 自定义的前缀

    pkg_check_modules(<PREFIX> [REQUIRED] <MODULE> [<MODULE>]*)
    检测所有给出的modules    

    设置'REQUIRED'参数后 如果MODULE没有找到会发生错误
   
    该命令会设置以下几个变量
        PKG_CONFIG_FOUND    如果pkg-config可以运行在系统中 为TRUE
        PKG_CONFIG_EXECUTABLE    pkg-config程序的路径
        <PREFIX>_FOUND        如果module存在 设置为1   

    下列生成的变量有两组值 一种使用<PREFIX>作为前缀 另一种使用<PREFIX>_STATIC作为前缀 (在调用pkgconfig时使用--static选项)

    <XPREFIX> = <PREFIX>        普通情况下
    <XPREFIX> = <PREFIX>_STATIC    为static链接的情况下

    <XPREFIX>_LIBRARIES        库
    <XPREFIX>_LIBRARY_DIRS        库的路径
    <XPREFIX>_LDFLAGS        所有需要的链接选项
    <XPREFIX>_LDFLAGS_OTHERS    所有其他的链接选项
    <XPREFIX>_INCLUDE_DIRS        '-I' 预处理选项
    <XPREFIX>_CFLAGS        所有需要的cflags(C编译器的选项)
    <XPREFIX>_CFLAGS_OTHERS        其他的编译选项