Archive for the ‘Uncategorized’ Category

metaSendsEscape

Monday, March 30th, 2009

Occasionally we can found that the Bash key-binding such as M-f/M-b will not work in XTerm (this happened both in my laptop and desktop), to solve this problem, just press `Control’ and left mouse and check the item `Meta Sends Escape’ from the main options.

To turn it on permanently, add the following line to configure file ‘/etc/X11/app-defaults/XTerm’:

*metaSendsEscape: true

1234567890

Monday, February 9th, 2009

$ date -d @1234567890
Sat Feb 14 07:31:30 CST 2009

Beating the Averages

Sunday, October 12th, 2008

The Averages, 即 “the average programmers’ ‘是也。标题所指文章以前应该看过,再次细读了一番,颇有“余音绕梁”之感。

教科书中常把编程语言划分成低级语言和高级语言,这容易给人造成一种误解:高级语言大致都是等价的。其实不是!并没有一个鸿沟,明确的将一边划为低级语言,另一边是所有高级语言。每一种语言都提供了一个抽象层次,层次越高便越强大。虽然在图灵机的角度来看,它们是等价的,但是在实际生活中,程序员更关心的是语言的表达能力和表达效率。

“奇文共欣赏”,热爱程序设计的朋友们不妨仔细一读。

ruid-euid-suid

Tuesday, April 22nd, 2008

折腾于ruid(real user ID),euid(effective user ID)和suid(saved user ID)之中。从一知半解到似乎理解,手册读起来比较困惑。终于写出一个测试程序taccess.c,开始为root,然后切换到普通用户,最后再变回root。不过有一个地方还是比较困惑:
$ ls -l /tmp/foo.txt
-rw-r—– 1 root root 0 2008-04-22 23:26 /tmp/foo.txt
$ sudo ./taccess /tmp/foo.txt
——————–
uid: 0 euid: 0
gid: 0 egid: 0
/tmp/foo.txt: Success
——————–
uid: 1000 euid: 1000
gid: 1000 egid: 1000
/tmp/foo.txt: Success
——————–
uid: 0 euid: 0
gid: 0 egid: 0
/tmp/foo.txt: Success
$ cat /tmp/foo.txt
cat: /tmp/foo.txt: Permission denied

不明白为何第二次以普通用户访问文件时仍然得到success。

volatile

Monday, March 31st, 2008

[Original: ] http://www.airs.com/blog/archives/154

The volatile qualifier in C/C++ is widely misunderstood. Because it is described so vaguely in language standards, many people interpret it as a do-what-I-mean qualifier.

What the standard says is that accesses to volatile objects must be evaluated strictly according to the abstract machine defined by the language standard; this means that if the C/C++ code reads the volatile object twice, then the machine code must do so as wel. The standard says that volatile objects must be stable at sequence points; this means, approximately, that in between statements all reads and writes of volatile objects must have been completed–the value may not be cached in a register. The standard makes clear that it is possible that the values of volatile objects may change in some unknown way between accesses.

One relatively unimportant misunderstanding is due to the fact that the standard only talks about accesses to volatile objects. It does not talk about accesses via volatile qualified pointers. Some programmers believe that using a pointer-to-volatile should be handled as though it pointed to a volatile object. That is not guaranteed by the standard and is therefore not portable. However, this is relatively unimportant because gcc does in fact treat a pointer-to-volatile as though it pointed to a volatile object.

A way to think about volatile is to observe that it was invented to support memory mapped hardware. Some hardware is controlled by accesses to specific memory addresses. For example, a serial controller often handles input by setting a bit in one memory location and making the new byte available in another memory location. The kernel code must observe that the bit is set, read the byte, and set another bit to tell the serial controller that the byte has been read (I’m skipping the interrupt which is also involved). These accesses should use volatile to make sure that they happen in the exact order written in the program.

The standard also explicitly describes two other uses of volatile. One is for setjmp and is relatively uninteresting. The other is that a variable of type volatile sig_atomic_t may be set in a signal handler and read by code outside the signal handler. In fact, just about all that a portable signal handler may do is set such a variable.

For dealing with memory mapped hardware, volatile is exactly what you want. For most other types of code, including multi-threaded code, volatile does not help.

Using volatile does not mean that the variable is accessed atomically; no locks are used. Using volatile does not mean that other cores in a multi-core system will see the memory accesses; no cache flushes are used. While volatile writes are guaranteed to occur in the program order for the core which is executing them, there is no guarantee that any other core will see the writes in the same order. Using volatile does not imply any sort of memory barrier; the processor can and will rearrange volatile memory accesses (this will not happen for address ranges used for memory mapped hardware, but it will for ordinary memory).

Conversely, if you use the locking primitives which are part of any threading library, then you do not need to use volatile. The locking primitives will include the required memory barriers or cache flushes. They will include whatever special directives are needed to tell the compiler that memory must be stable.

There is one case where volatile may be used for multi-threaded programming with some reliability. You may use a single volatile sig_atomic_t variable to communicate between threads, much as you may use such a variable to communicate between a signal handler and the main program. You should not use more than one such variable to communicate between any pair of threads, as there is no guarantee that the different threads will see the accesses in the same order.

In summary, if you are using volatile for anything other than manipulating memory mapped hardware, or for very limited communication between threads, it is very likely that you are making a mistake. Think carefully about what volatile means and about what it does not mean.