如何在字符界面下滚动屏幕

2009年9月14日 21:22

以前在使用类Unix系统时,如果没有装桌面系统要在字符界面下工作,会遇到这样一个问题:

如果屏幕输出过多,最早输出的内容会被挤出屏幕看不到了,字符界面又没有滚动条这样的东西,那么该怎么查看那些被挤到“屏幕上面“的内容呢?

有几种方法:

  1. 通过输出重定向将输出定向到文件里,再用编辑器看。
  2. 将输出定向到more或less这样的程序里看。

这也是我之前常使用的,但是直到最近我才发现有第三种方法。。

在键盘的右上角有一个按键叫做Screen lock,在print screen和pause/break按键之间。这个按键的左右就是查看屏幕上的输出。

使用方法:

首先按下Screen lock按钮看到右边键盘灯亮起,既说明开启了滚动屏幕模式,接着可以通过pageup/pagedown来滚动屏幕了。再次按下Screen lock按钮退出滚动屏幕模式。

以前一直没注意这个按钮是干嘛的,原来是做这个的。:-)

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