Archive for the ‘分享’ Category
一个简单的AHK脚本
#IfWinActive ahk_class Emacs
Capslock::Control
Control::Capslock
#IfWinActive
假如当前的ahk_class是Emacs,那么交换Ctrl和Caps,否则不交换。
Emacs里面的MiniMap
Sublime Text的MiniMap比较有特色,正在想是不是能为Emacs也搞一个类似的东西,没想到已经有了。(不知道MiniMap是啥的,请移步Sublime Text的网站)
http://www.emacswiki.org/emacs/MiniMap
Emacs MiniMap的tricky之处在于,它并没有实现什么新的GUI控件,而是直接新开一个buffer,把font face缩小一下,达到MiniMap的类似效果。想出这法子的哥们可真行。
不过这也意味着MiniMap在字符界面是下不可用的——不过这谁又在乎呢,毕竟Sublime Text连CUI的版本都没有。在Emacs里面用这么小的代价实现相似的功能,一方面是Emacs这货实现是强大,另外一方面是写这东西的哥们实在也挺有想法的。
不过目前看来这个MiniMap功能是有了,但是体验不算特别好。用vertical split开的window在C-x 1之后就不见了,这可是很不爽的。依我的想法来看,能不能想办法让minimap window比较特殊一点,于是自己fork了一个别人已经做了修改的版本hack了一下。目前我主要hack了三个小地方:
1. 为delete-other-windows做了advice,总是保留MiniMap window;
2. 修正了make-overlay的一个错误参数,不改的话为空文件生成的overlay是不对的;
3. 只为图形界面的Emacs创建MiniMap,毕竟用了font face,在字符界面下意义不大。
随便改了一下,感兴趣的就拿走。
https://github.com/liuw/emacs-minimap
MiniMap的实现也不算特别稳定,有时会让Emacs死掉的。但是我没有那个水平,也懒得去debug了——说实话我还是用CUI的Emacs比较多点,看这东西单纯是觉得新奇而已。废话少说了,上图。
使用Git发送patch
以前我一直很土地手写patch邮件,今天Ian Campbell教了新招数,先记下来。Git的send-email可能要单独安装(我的Debian就是)。
首先要安装好MTA,我现在用的是exim,看自己喜好了。然后Git的配置文件要写好。
[user]
name = OOXX
email = XXOO
[sendemail]
smtpserver = SMTPSERVER
chainreplyto = false
signedoffcc = true
Patch要排版怎么办?没关系,用git format-patch。然后使用git send-email就OK了。
% git send-email $(git format-patch HEAD^..) --to XIAOMING --cc XIAOHONG --bcc XIAOFANG
注意由于前面signedoffcc设置的缘故,邮件会自动抄送patch里面所有sign off了的人。
慢着,写个Linux内核补丁,不知道该往哪发,怎么办?内核hacker们早就帮我们想好了。
% cd LINUX_KERNEL_DIR % ./scirpt/get_maintainer.pl PATH_TO_YOUR_PATCH
运行之后会出来一些地址,有list和maintainer,尽管发就好了。
[好文传递]The TTY demystified
http://www.linusakesson.net/programming/tty/index.php
GCC嵌入式ASM快速指南
本文从Inline assembly for x86 in Linux中摘译。
Table of Contents
1 简要GNU汇编语法
1.1 寄存器命名
寄存器名字前面应该加上%前缀。比如要使用eax,那么应该写为%eax。
1.2 来源和目的的顺序
在任何一条指令中,总是先写来源,然后再写目的。这与Intel汇编语法正好相反。
movl %eax, %ebx -- transfers the contents of eax to ebx
1.3 操作数的尺寸
根据操作数的长度是字节、字或者长整形,指令一般需要加上b、w或者l后缀。这不是强制要求的,GCC会根据操作数的尺寸自动加上合适后缀。但是手工加上后缀一方面加强了可读性,另一方面消除了GCC猜错的可能。
movb %al, %bl movw %ax, %bx movl %eax, %ebx
1.4 直接操作数
直接操作数需要加上$前缀。
movl $0xffff, %eax
1.5 直接内存引用
使用()去完成直接内存引用。
movb (%esi), %al -- will transfer the byte in the memory pointed by esi to al
2 内联汇编
GCC提供了一种特殊结构去创建联汇编,格式如下:
asm ( assembler template
: output operands
: input operands
: list of clobbered registers
);
模板由汇编指令构成。input operands是用来作为汇编指令输入操作数的C表达式。output operands依此类推。
asm ("movl %%cr4, %0\n" :"=r"(cr3val))
a %eax b %ebx c %ecx d %edx S %esi D %edi
2.1 内存操作数约束
当操作数位于内存中时,所有操作都会直接在内存位置执行。内存操作数约束的作用是当一个C变量需要被内联汇编操作时,程序员不需要显式地把它放到寄存器中。如:
asm ("sidt %0\n" : :"m"(loc));
2.2 匹配约束
在某些情况下,一个变量可能会同时输入和输出操作数。这样的情况可以使用匹配约束来完成。
asm ("incl %0" :"=a"(var):"0"(var));
在我们的匹配约束例子中,%eax同时作为输入和输出操作数。var先被读入到%eax,操作完成后结果被存回var。“0”指定了和0号输出变量同样约束。即是说,它指定了var的输出应该只被放到%eax。这类约束可以在如下的情况使用:
- 输入是一个变量然后输入到同一个变量;
- 不需要分别使用不同的变量去保存输入和输出。
使用匹配约束可以有效地使用寄存器。
2.3 常见内联汇编用例
下面的例子展示常见的用法。
2.3.1 “asm”和寄存器约束“r”
int main(void)
{
int x = 10, y;
asm ("movl %1, %%eax;"
"movl %%eax, %0;"
:"=r"(y) /* y is output operand */
:"r"(x) /* x is input operand */
:"%eax");/* eax is clobbered register */
return 0;
}
生成的汇编代码如下:
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
movl $10, -4(%ebp)
movl -4(%ebp), %edx /* x=10 is stored in %edx */
,#APP
movl %edx, %eax /* x is moved to eax */
movl %eax, %edx /* y is allocated in edx and updated */
,#NO_APP
movl %edx, -8(%ebp) /* value of y in the stack is updated with the value in edx */
“r”指明GCC可以采用任意的寄存器。在上例中,edx被先后用于存放x和y。
由于eax在clobbered list中,GCC不会使用它去存放数据。
在上例中,edx被先后用于输入和输出,这里有一个前提就是输入数据总是在输出之前就已经失效了。但是实际情况中有很多指令并不总是这样做的,所以我们可以加上“&”修饰符让输入输出使用不同的寄存器。
int main(void)
{
int x = 10, y;
asm ("movl %1, %%eax;"
"movl %%eax, %0;"
:"=r"(y) /* y is output operand, note the "&" modifier */
:"r"(x) /* x is input operand */
:"%eax");/* eax is clobbered register */
return 0;
}
生成下面代码:
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
movl $10, -4(%ebp)
movl -4(%ebp), %ecx /* x=10 is stored in %ecx */
,#APP
movl %ecx, %eax
movl %eax, %edx /* output is in %edx */
,#NO_APP
movl %edx, -8(%ebp)
2.3.2 指定寄存器约束
下面例子中,cpuid的输入由eax指定,输出到eax、ebx、ecx、edx四个寄存器中。
asm ("cpuid"
:"=a"(_eax),
"=b"(_ebx),
"=c"(_ecx),
"=d"(_edx)
:"a"(op));
然后生成如下的代码(这里假设eax等变量存放栈上):
movl -20(%ebp),%eax /* store 'op' in %eax -- input */
,#APP
cpuid
,#NO_APP
movl %eax,-4(%ebp) /* store %eax in _eax -- output */
movl %ebx,-8(%ebp) /* store other registers in
movl %ecx,-12(%ebp) respective output variables */
movl %edx,-16(%ebp)
strcpy可以用下面的方法实现:
asm ("cld\n rep\n movsb"
: /* no input */
:"S"(src), "D"(dst), "c"(count));
2.3.3 匹配约束
拿系统调用的代码做例子:
,#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
"d" ((long)(arg3)),"S" ((long)(arg4))); \
__syscall_return(type,__res); \
}
通过使用匹配约束“0”,系统调用号被放入到eax中。
2.3.4 内存操作数约束
考虑如下的原子减一操作:
__asm__ __volatile__(
"lock; decl %0"
:"=m"(counter)
:"m"(counter));
会生成如下的汇编:
,#APP
lock
decl -24(%ebp)
,#NO_APP
上面的例子中,变量在内存中直接被减一。假如使用“r”的话,操作就没有原子性了。
2.3.5 clobbered约束
考虑如下的memcpy实现:
asm ("movl $count, %%ecx;
up: lodsl;
stosl;
loop up;"
:
:"S"(src), "D"(dst)
:"%ecx", "%eax");
lodsl和stosl隐式地使用eax,ecx被显式地加载到寄存器中。除非我们用clobbered约束告诉GCC这两个寄存器是可用的,它不会再使用它们去存放其他数据。esi和edi没有加入到clobbered列表中,因为它们已经出现在了输入操作数列表中。准则就是,例如一个寄存器在asm中使用了(无论是显式还是隐式),而又没有出现在输入、输出操作数列表中,那么它就必须出现在clobbered列表中。
3 相关资源
HTML generated by org-mode 6.21b in emacs 23
Git Supervisual Cheatsheet
http://panela.blog-city.com/git_supervisual_cheatsheet.htm
http://panela.blog-city.com/update_of_git_supervisual_cheatsheet.htm
Org-mode的Code Blocks功能
在使用Emacs的Org-mode记笔记的时候,难免会遇到要输入代码的情况,使用code block功能来做,方便又美观。
一般的格式是:
#+begin_src language org-switches header-arguments CODE HERE #+end_src
比如说我要输入Ruby代码:
#+begin_src ruby puts 'hello world' #+end_src
还有更酷的。在code block中使用
C-c '
可以调用org-edit-src-code,直接切换到语言对应的mode进行输入,充分享受Emacs对语言的支持。
如果不在code block中调用org-edit-src-code,会进入Artist mode,可以用鼠标画图。
另外,code block还支持代码执行。
详见:http://orgmode.org/worg/org-contrib/babel/intro.php
近期收集的一些有趣的小東東
近來比較少寫blog,實在是比較忙。用繁體寫是因為看簡體的字多了眼花,得換換口味了。
72pines的頁面很奇怪,假如我不用搜狗的全網加速功能去開,出來的頁面就沒有樣式了。可能它有一部份的伺服器被教育網墻掉了(?)。
在王亮先生的Emacs定制和擴展中,找到一個“能獲取root權限的輔助腳本”,解決了我一直頭痛的一個問題。原理挺簡單,使用TRAMP來完全的。以前一直以為TRAMP主要是用于遠程編輯文件的,沒有發現這個功能,沒仔細看Manual的後果。
(defun wl-sudo-find-file (file dir) (find-file (concat "/sudo:localhost:" (expand-file-name file dir))))
當然,其他的內容也很精彩。
第二個,是從Wowubuntu得來的三手信息。爲什麽說是三手呢,因為它也只是轉載的。主要是講Bash shell的一些奇技淫巧。
最牛B的 Linux Shell 命令 系列连载,有點標題黨了,呵呵。
比較有趣的是活用history功能的條目,比如說sudo執行前一條命令是:
$ sudo !!
兩個嘆號“!!”等價于“!-1”,數字換成其他也是可以的,不過誰記得了那麼多啊。
另外一個有趣的功能就是Bash的替換(原來它也有啊,呵呵):
$ !!:s/foo/bar/
很熟悉的語法,只是從來沒有想到過還有這個功能,sigh。
文章提到上面兩個技巧都是出自The Definitive Guide to Bash Command Line History。
還有一些其他的技巧,不僅僅限於Bash本身,不一而足。由於有的要么知道了,要么對我自己用處不大,這里就不多記了。
五笔拆字约定
1. 凡单笔画与字根相连或带点结构都视为杂全型,如“天”、“千”、“丸”、“太”。
2. 区分汉字结构时,按“能散不连”的原则来进行,如“矢”、“卡”、“严”、“走”都视为上下型。
3. 含两字根且相交者属杂合型,如“乐”、“串”、“电”、“本”。
4. 下含“走之”字为杂合型,如“进”、“过”、“这”、“边”。
5. 属于“连”和“交”的汉字一律视为杂合型。
好文传递:Zero Copy I: User-Mode Perspective
“零拷贝”这个词也听到不少了,据说是可以明显提高性能。网上找到好文一篇。
Zero Copy I: User-Mode perspective
在一些程序,比如说HTTP服务器,需要向用户发送文件,有一部分是图片、静态网页之类不需要处理就可以直接发送的文件。土一点的做法无非是:
read(file_fd, buf, len); write(socket_fd, buf, len);
实际上,read(2)这个操作,是首先把文件内容读入到内核缓冲区中去,然后再把文件内容从内核缓冲区拷贝到用户缓冲区;而write(2)这个操作,需要把用户缓冲区的内容拷贝到内核缓冲区。我们不需要对文件内容进行处理的情况下,却多用了一道拷贝工序,直接造成的开销有多了一次的上下文切换,以及浪费了缓冲区的内存。
为什么不把拷贝到用户空间的这一道工序去掉了,内核的两个缓冲区直接拷贝就好了。目前流行的做法是用sendfile(2),在Linux里面的作用是把数据从一个文件描述符直接拷贝到别一个文件描述符。但是sendfile(2)的实现,好像是各个系统都有差异,使用的时候需要注意一下,在使用的时候最好先查一下手册。
但是从内核缓冲区到内核缓冲区的“零拷贝”,还不算真的完全没有拷贝。真正的“零拷贝”需要硬件支持。在具备Gather操作的DMA硬件支持下,内核只需要修改内部文件描述符的指向,然后等待硬件自动执行Gather操作,把数据取走。
