那点儿历史──C语言历史

C语言的历史非常有趣,它的祖先可以上溯到古老的Algol 60语言──最早的块结构语言。

1963年,剑桥大学将Algol 60语言发展成为CPL(Combined Programming Language)语言。CPL的最大缺点就是它太大了,以至于不能在很多应用程序中使用。到1967年,剑桥大学的Matin Richards在访问MIT时,对CPL语言进行了简化,设计出了BCPL(Basic CPL)语言。

1970年,美国贝尔实验室的Ken Thompson发现BCPL太慢了,而且缺乏运行时的支持,他将BCPL进行了实验性的修改,并为它起了一个有趣的名字──B语言,意思是将CPL语言进行压缩,提炼出它的精华。B是BCPL的一个简化版,而且被设计成专门用来进行系统编程,但它依然不能满足程序员们的要求:它的字符处理机制太丑陋了,而且浮点数运算被实现得并不是很理想,处理指针时开销太大。

在1972年,当PDP-11进入贝尔实验室时,Ken Thompson的同伴,同样在贝尔实验室的Dennis M. Ritchie,在从BCPL中抽取了一些共性放入B语言中,对B进行了改进,并且在里面加入了数据类型,他把这个扩展的语言称为NB(New B)。随后,他又继续对新语言进行大量修改,似乎可以用新的名字来重新命名它了,于是他取了B后面的那个字母作为这种语言的名字,这就是C语言。(曾几何时,人们猜测 C 的后裔会被命名为P──BCPL的第三个字母,而不是D,但如今最显见的C的后裔语言是叫C++。)

1973年,Ritchie完成了C语言核心,并用C重写了整个Unix内核。为了使Unix操作系统推广,1977年Dennis M. Ritchie发表了不依赖于具体机器系统的C语言编译文本《可移植的C语言编译程序》。

1978年,Brian W. Kernighian和Dennis M. Ritchie出版了长久不衰的经典之作──《The C Programming Language》,把C从贝尔实验室推向世界,从而使C语言成为目前世界上流行最广泛的程序设计语言之一。

为四十岁做准备

“十八岁是美丽的,而人生的旅程中最绚丽的一页应该在生命的四十岁时翻开。不要说四十岁有多么遥远,二十年其实是弹指一挥间。虽说四十岁就在眼前,但二十年的时间跨越足以让我们眼花缭乱。虚度今日,等待你的将是无穷的悔恨和遗憾。追求先贤成材路,浩瀚人世间,我们定会发现,四十岁的辉煌来自于十八岁的志向和二十年的血汗。珍视你拥有的青春年华,好好地把握现在,才能真正赢得未来,才能将你如日中天的四十岁勾画得绚丽灿烂。”

记得高中时看过上面这段话,据说还是我们那里某个中学的校训。时过境迁,高中生活已经过去快三年了,高中的同学和朋友一个个都变化不小,想起来就不禁感慨万千 。高中时虽然面临高考的压力,但总能忙中偷闲,和几个哥们经常背着班主任偷偷上网,经常一下课就骑着车子去外面抢着买饭,还能经常在放学路上遇到她……再对比一下现在,一切似乎都只是回忆了,还是那首诗说得好:

“去年今日此门中,人面桃花相映红。人面不知何处去,桃花依旧笑春风。 ”

哎,该走的总是要走的。走吧,走吧,让往事都随风去吧。二十年或许真的很快,希望二十年后自己不会为今天的所做所为后悔。那时回想起现在的自己,或许还只是那句:“年轻人……”

从C/C++到Java(一)

1. Java中的long是64位,char占两个字节,比C多了byte和boolen类型。所以,Java没有sizeof操作符。而且,Java没有“无符号”类型,里面的整数全都是有符号的。

2. Java中的switch语句更严格,它规定switch中的表达式的值的类型必须是int或char,即使是short和long也是不允许的。

3. Java的任何表达式中都不能使用逗号运算符,但是在for循环中,逗号作为一个特殊的语法被支持。

4. Java没有指针,有的只是数组和引用。NULL在Java里被叫做null。需要特别指出的一点是:虽然Java中的函数参数是通过引用传递,但在被调函数中会存有对参数的本地拷贝。

5. Java不需要自己释放内存,因为它带有垃圾回收器。

6. Java不支持多重继承,C++支持。一种替代的方案是Java的interface。

7. 即使是在C++中,string和字符数组也有某种联系,而Java中的String已经基本上脱离了这种关系(仅有的一点儿联系也是你应该避免的)。

8. Java代码是被编译成byte code,而C和C++都是直接被编译成二进制机器码。因此,编写可移植的Java代码比编写可移植的C/C++要容易得多。(感谢孔建军补充这一点)

罗素自传序言—我为什么活着

What I Have Lived For

 

————我为什么活着

 

Three passions, simple but overwhelmingly strong, have governed my life: the longing for love, the search for knowledge, and unbearable pity for the suffering of mankind. These passions, like great winds, have blown me hither and thither, in a wayward course, over a great ocean of anguish, reaching to the very verge of despair.

  三种朴素而又异常强烈的感情一直统治着我的一生:渴望爱,追求知识和对人类苦难的无法容忍的怜悯。这三种感情像飓风一样,把我在痛苦的海洋中吹得忽东忽西,难以捉摸,直把我吹到绝望的边缘。

I have sought love, first, because it brings ecstasy - ecstasy so great that I would often have sacrificed all the rest of life for a few hours of this joy. I have sought it, next, because it relieves loneliness—that terrible loneliness in which one shivering consciousness looks over the rim of the world into the cold unfathomable lifeless abyss. I have sought it finally, because in the union of love I have seen, in a mystic miniature, the prefiguring vision of the heaven that saints and poets have imagined. This is what I sought, and though it might seem too good for human life, this is what—at last—I have found.

  我寻求爱,首先是因为爱给我带来如此之大的欣喜,使我心醉神迷以致我常常愿意牺牲我的余生来换取几个小时的欣喜之情。我寻求爱,其次是因为爱可以解脱孤独--那可怕的孤独就好像一个毛骨悚然的人从世界的边缘探望令人胆战心寒的毫无生气的人们所幻想的天堂神秘雏型。这就是我所寻求的,虽然这可能似乎是人生难以得 到的美好事物,可这就是--终于--我所找到的。

With equal passion I have sought knowledge. I have wished to understand the hearts of men. I have wished to know why the stars shine. And I have tried to apprehend the Pythagorean power by which number holds sway above the flux. A little of this, but not much, I have achieved.

  我以同样的感情探索知识。我想理解人们的心。我想知道为什么星星会发光。我尽力领悟毕达哥拉斯使数字支配变化着的事物的才能。在探索知识方面,我只取得了一点儿成绩,但还不很多。

Love and knowledge, so far as they were possible, led upward toward the heavens. But always pity brought me back to earth. Echoes of cries of pain reverberate in my heart. Children in famine, victims tortured by oppressors, helpless old people a burden to their sons, and the whole world of loneliness, poverty, and pain make a mockery of what human life should be. I long to alleviate this evil, but I cannot, and I too suffer.

  爱和知识,尽其可能把人引向天堂。可是不断的怜悯把我带回到人间。痛苦的呼号声在我心中激荡。饥饿的儿童,在压迫者折磨下的受难者,孤独无 助已成为子女们厌恶的负担的老人们,整个孤独、贫困与痛苦的世界都在嘲弄人生的本来面目。我渴望减轻邪恶,但我力所不及,我也在受苦难。

This has been my life. I have found it worth living, and would gladly live it again if the chance were offered me.

  这就是我的一生。我一直觉得我的一生过得很有价值。如果可能,我愿意再过这样的一生。

在LKML上提的一个问题

发件人 Cong WANG
收件人 linux-kernel@vger.kernel.org
日期 2007-3-11 下午10:15
主题 Style Question
邮送域 gmail.com
Hi, list!

I have a question about coding style in linux kernel. In
Documention/CodingStyle, it is said that “Linux style for comments is
the C89 “//“ style. Don’t use C99-style “// …” comments.”
But I see a lot of ‘//‘ style comments in current kernel code.

Which is wrong? The documentions or the code, or neither? And why?

Another question is about NULL. AFAIK, in user space, using NULL is
better than directly using 0 in C. In kernel, I know it used its own
NULL, which may be defined as ((void*)0), but it’s still different
from raw zero. So can I say using NULL is better than 0 in kernel?

Any reply is welcome. Thanks and have a nice day!

Bernd Petrovitsch 第一个回答到:

On Sun, 2007-03-11 at 22:15 +0800, Cong WANG wrote:
[…]
> Another question is about NULL. AFAIK, in user space, using NULL is
> better than directly using 0 in C. In kernel, I know it used its own
> NULL, which may be defined as ((void*)0),

Userspace has the usually same definition.

> but it’s still different
> from raw zero.

It is different that “0” as such has the type “int”. But this int is
automatically promoted to a “0 pointer”.

> So can I say using NULL is better than 0 in kernel?

Yes, because it is immediately clear that a pointer is (or should be)
there (and not an int).
And the same holds for userspace since this is a pure C question.

Bernd

Jan Engelhardt 回复到:

On Mar 11 2007 22:15, Cong WANG wrote:
>
> I have a question about coding style in linux kernel. In
> Documention/CodingStyle, it is said that “Linux style for comments is
> the C89 “//“ style. Don’t use C99-style “// …” comments.”
> But I see a lot of ‘//‘ style comments in current kernel code.
>
> Which is wrong? The documentions or the code, or neither? And why?

The code. And because it’s not always reviewed but silently pushed.

> Another question is about NULL. AFAIK, in user space, using NULL is
> better than directly using 0 in C. In kernel, I know it used its own
> NULL, which may be defined as ((void*)0), but it’s still different
> from raw zero.

In what way?

>So can I say using NULL is better than 0 in kernel?

On what basis? Do you even know what NULL is defined as in
(C, not C++) userspace? Think about it.

Jan

我看到后回复:

2007/3/12, Jan Engelhardt:
>
> On Mar 11 2007 22:15, Cong WANG wrote:
> >
> > I have a question about coding style in linux kernel. In
> > Documention/CodingStyle, it is said that “Linux style for comments is
> > the C89 “//“ style. Don’t use C99-style “// …” comments.”
> > But I see a lot of ‘//‘ style comments in current kernel code.
> >
> > Which is wrong? The documentions or the code, or neither? And why?
>
> The code. And because it’s not always reviewed but silently pushed.
>
> > Another question is about NULL. AFAIK, in user space, using NULL is
> > better than directly using 0 in C. In kernel, I know it used its own
> > NULL, which may be defined as ((void*)0), but it’s still different
> > from raw zero.
>
> In what way?

The following code is picked from drivers/kvm/kvm_main.c:

static struct kvm_vcpu vcpu_load(struct kvm kvm, int vcpu_slot)
{
struct kvm_vcpu *vcpu = &kvm->vcpus[vcpu_slot];

mutex_lock(&vcpu->mutex);
if (unlikely(!vcpu->vmcs)) {
mutex_unlock(&vcpu->mutex);
return 0;
}
return kvm_arch_ops->vcpu_load(vcpu);
}

Obviously, it used 0 rather than NULL when returning a pointer to
indicate an error. Should we fix such issue?

>
> >So can I say using NULL is better than 0 in kernel?
>
> On what basis? Do you even know what NULL is defined as in
> (C, not C++) userspace? Think about it.
>

I think it’s more clear to indicate we are using a pointer rather than
an integer when we use NULL in kernel. But in userspace, using NULL is
for portbility of the program, although most (just most, NOT all) of
NULL’s defination is ((void*)0).

一些其它的回复如下:

Robert Hancock 写道:

Cong WANG wrote:
> Hi, list!
>
> I have a question about coding style in linux kernel. In
> Documention/CodingStyle, it is said that “Linux style for comments is
> the C89 “//“ style. Don’t use C99-style “// …” comments.”
> But I see a lot of ‘//‘ style comments in current kernel code.
>
> Which is wrong? The documentions or the code, or neither? And why?

The code.. As with a lot of coding style issues, it’s likely just that
nobody saw it and bothered to complain when it went in.

> Another question is about NULL. AFAIK, in user space, using NULL is
> better than directly using 0 in C. In kernel, I know it used its own
> NULL, which may be defined as ((void*)0), but it’s still different
> from raw zero. So can I say using NULL is better than 0 in kernel?

It’s the preferred style, Sparse will complain about using 0 for a null
pointer for example..

Mac的Kyle Moffett 如是说:

On Mar 11, 2007, at 16:41:51, Daniel Hazelton wrote:
> On Sunday 11 March 2007 16:35:50 Jan Engelhardt wrote:
>> On Mar 11 2007 22:15, Cong WANG wrote:
>>> So can I say using NULL is better than 0 in kernel?
>>
>> On what basis? Do you even know what NULL is defined as in (C, not
>> C++) userspace? Think about it.
>
> IIRC, the glibc and GCC headers define NULL as (void*)0 :)

On the other hand when cplusplus is defined they define it to the
null” builtin, which GCC uses to give type conversion errors for
“int foo = NULL” but not “char foo = NULL”. A “((void )0)”
definition gives C++ type errors for both due to the broken C++ void
pointer conversion problems.

Cheers,

Nicholas Miell这样说:

On Mon, 2007-03-12 at 06:40 +0100, Jan Engelhardt wrote:
> On Mar 12 2007 13:37, Cong WANG wrote:
> >
> > The following code is picked from drivers/kvm/kvm_main.c:
> >
> > static struct kvm_vcpu vcpu_load(struct kvm kvm, int vcpu_slot)
> > {
> > struct kvm_vcpu vcpu = &kvm->vcpus[vcpu_slot];
> >
> > mutex_lock(&vcpu->mutex);
> > if (unlikely(!vcpu->vmcs)) {
> > mutex_unlock(&vcpu->mutex);
> > return 0;
> > }
> > return kvm_arch_ops->vcpu_load(vcpu);
> > }
> >
> > Obviously, it used 0 rather than NULL when returning a pointer to
> > indicate an error. Should we fix such issue?
>
> Indeed. If it was for me, something like that should throw a compile error.
>
> >>[…]
> > I think it’s more clear to indicate we are using a pointer rather than
> > an integer when we use NULL in kernel. But in userspace, using NULL is
> > for portbility of the program, although most (
just most, NOT all) of
> > NULL’s defination is ((void
)0).

>
> NULL has the same bit pattern as the number zero. (I’m not saying the bit
> pattern is all zeroes. And I am not even sure if NULL ought to have the same
> pattern as zero.) So C++ could use (void *)0, if it would let itself :p

Not necessarily. You can use 0 at the source level, but the compiler has
to convert it to the actual NULL pointer bit pattern, whatever it may
be.

In C++, NULL is typically defined to 0 (with no void* cast) by most
compilers because 0 (and only 0) can be implicitly converted to to null
pointer of any ponter type without a cast.

GCC introduced the __null extension so that NULL still works correctly
in C++ when passed to a varargs function on 64-bit platforms.

(This just works in C because C makes NULL ((void)0) is thus is the
right size. In C++, the 0 ends up being an int instead of a pointer when
passed to a varargs function, and things tend to blow up when they read
the garbage high bits. Of course, nobody else does this, so you still
have to use (void
)NULL to be portable.)

Randy.Dunlap 给以肯定回答:

On Mon, 12 Mar 2007, Jan Engelhardt wrote:

>
> On Mar 12 2007 13:37, Cong WANG wrote:
> >
> > The following code is picked from drivers/kvm/kvm_main.c:
> >
> > static struct kvm_vcpu vcpu_load(struct kvm kvm, int vcpu_slot)
> > {
> > struct kvm_vcpu *vcpu = &kvm->vcpus[vcpu_slot];
> >
> > mutex_lock(&vcpu->mutex);
> > if (unlikely(!vcpu->vmcs)) {
> > mutex_unlock(&vcpu->mutex);
> > return 0;
> > }
> > return kvm_arch_ops->vcpu_load(vcpu);
> > }
> >
> > Obviously, it used 0 rather than NULL when returning a pointer to
> > indicate an error. Should we fix such issue?
>
> Indeed. If it was for me, something like that should throw a compile error.

At least it does throw a sparse warning, and yes, it should
be fixed.

最后我决定提交补丁:

[PATCH]Replace 0 with NULL when returning a pointer

Use NULL to indicate we are returning a pointer rather than an integer
and to eliminate some sparse warnings.

Signed-off-by: Cong WANG <xiyou.wangcong@gmail.com>


—- drivers/kvm/kvm_main.c.orig 2007-03-11 21:41:23.000000000 +0800
+++ drivers/kvm/kvm_main.c 2007-03-12 14:26:17.000000000 +0800
@@ -205,7 +205,7 @@ static struct kvm_vcpu *vcpu_load(struct
mutex_lock(&vcpu->mutex);
if (unlikely(!vcpu->vmcs)) {
mutex_unlock(&vcpu->mutex);

  • return 0;
  • return NULL;
    }
    return kvm_arch_ops->vcpu_load(vcpu);
    }
    @@ -799,7 +799,7 @@ struct kvm_memory_slot *gfn_to_memslot(s
    && gfn < memslot->base_gfn + memslot->npages)
    return memslot;
    }
  • return 0;
  • return NULL;
    }
    EXPORT_SYMBOL_GPL(gfn_to_memslot);

假期总结&新学期计划

其实这早就应该写的,只是因为网通到现在才把网络接好,所以推到现在才写。

寒假在家事情比较多,书基本上没怎么看,比原定计划差了不少,具体如下:

1. LDD应该读完,结果留了三章没看完,USB,网络和TTY这三章还没看。 不过基本上还算可以;

2. TAOUP是看了几页,主要是把它当小说看了,而且是想起来就看看,想不起来就算,这学期应该把它读完 ;

3. CM就别提了,翻了也就两三页,主要是看书的时候懒得动笔,不适合看这种数学类的(极其拙劣的借口),不知道后面还有没有时间去读它。

4. 寒假中意外的收获是把Python顺带学会了(起码会最基本的了), 主要是《Perl To Python Migration》一书讲解得好,正好适合我这种会Perl而不懂Python的。

既然寒假没怎么好好利用,这学期就得抓紧了,大体计划如下:

1. 熟悉使用Python编程,除Linux Kernel外尽量不再用C;

2. 熟悉Unix上的Network Programming,顺带把TCP/IP协议弄清楚,这是重中之重 ;

3. 加入Linux Kernel开发,感觉并不难,不过确实要花不少时间,此项也列为重点;

  1. 自学编译器原理和编程语言,能学多少是多少;

5. 如果有时间,把Lisp和Smalltalk 看一下,毕竟那才是“优美”的计算机语言。

如此而已。

Linux内核中的几个概念

Sunday, 25. February 2007, 07:19:10

王聪@西邮

软中断(softirq)是内核使用的一种推后执行任务的一种机制,由于一些中断处理必须要在短期内完成,所以内核不得不把一些相对不重要的工作推后执行,软中断就是专门用来执行这种后退的工作。它在某种程度上有点像硬件中断,来得“随时随地”,而且不在进程上下文之中。千万不要把它和“软件中断(software interrupts)”这个概念混了,后者是因为在编程中使用了中断指令(比如:int 0x80)而产生一个硬件上实际存在的中断信号,而前者更本就不和硬件扯关系。

小任务(tasklet)是在软中断的基础上实现的一种后推执行方式。软中断是在编译时就已经确定好的,而小任务则可以在运行时分配和初始化;软中断可以在不同的CPU上同时执行,而同一类型的tasklet只能在调度它们的同一CPU上运行,因此软中断函数必须是可重入的,而小任务的函数则没有这个必要。

工作队列(work queue)是另一种后推方式,但它和小任务有着很大的区别,小任务是在中断上下文中执行的,而工作队列是在进程上下文中执行的,所以工作队列是可以休眠的,也就不一定是原子的。执行工作队列的线程是ksoftirqd/n(n是cpu的编号,在UP是ksoftirqd/0),这是一个内核线程,因此也不能访问用户内存。

下半部(bottom half)是后推执行任务的一个统称,它主要是完成上半部未完成的一些工作。一般来说,在处理中断时,在中断处理例程(上半部)中做的工作越少越好,其余一些相对不那么迫切的工作可以后推给下半部来完成,当然了,下半部可以是小任务,也可以是工作队列。

世界上最遥远的距离(泰戈尔)

Tuesday, 20. February 2007, 07:12:24

By The furthest distance in the world
世界上最遥远的距离
Is not between life and death
不是生与死
But when I stand in front of you
而是 我就站在你面前
Yet you don’t know that I love you
你却不知道我爱你
The furthest distance in the world
世界上最遥远的距离
Is not when I stand in front of you
不是 我就站在你面前
Yet you can’t see my love
你却不知道我爱你
But when undoubtedly knowing the love from both
而是 明明知道彼此相爱
Yet cannot be together
却不能在一起
The furthest distance in the world
世界上最遥远的距离
Is not being apart while being in love
不是 明明知道彼此相爱 却不能在一起
But when painly cannot resist the yearning
而是 明明无法抵挡这股思念
Yet pretending you have never been in my heart
却还得故意装作丝毫没有把你放在心里
The furthest distance in the world
世界上最遥远的距离
Is not but using one’s indifferent heart
不是 明明无法抵挡这股思念 却还得故意装作丝毫没有把你放在心里
To dig an uncrossable river
而是 用自己冷漠的心对爱你的人
For the one who loves you
掘了一条无法跨越的沟渠

开发内核的几条经验

Wednesday, 14. February 2007, 12:20:41

作者:王聪@西邮

1. 永远不要使用sleep_on及其变种,那是不安全的,而且即将被剔出。
2. 老的/proc接口是有害的,如果你不能彻底理解它,千万别使用!尽量不要再往/proc里面放东西了,因为那里现在已经够乱了。
3. wait_event的一个变种──wait_event_interruptible_exclusive──是可以执行独占等待的。LDD中这一点错了,不,过时了。
4. 不要使用lock_kernel(),这个锁太大了,会让系统性能下降。
5. 信号量本身就是一种高级的lock,它能比普通的lock,比如spinlock,实现更多的语义。就像分配了内存后必须释放一样,一个进程对一个信号量进行down操作后,必须在退出前执行up。切记:不要在拥有锁时睡眠!
6. Unix的errno具有丰富的含义,请认真小心地处理它们,在用户空间如此,在内核空间更要如此,因为内核空间的一个错误状态直接影响到现有用户程序的表现。
7. oops是严重的错误,不能信任存在oops的内核。
8.
关于补丁:
a) 稳定内核的补丁只能应用于基版本的内核,比如:2.6.17.*补丁只能应用于2.6.17版本的内核;
b) 基版本内核补丁只能应用于上一个版本的内核,比如:2.6.18补丁只能应用于2.6.17;
c) 增量型补丁只能从一个指定的版本应用于另一个指定版本,比如:补丁patch-2.6.17.10-11.bz2只能应用于2.6.17.10,把它升级为2.6.17.11;
d) 如果你需要升级的版本间隔比较大,比如从2.6.17.1到2.6.17.11,可以先从2.6.17.1退回到2.6.17,然后再一次升级到2.6.17.11;
e) 稳定内核的补丁和基版本内核补丁都在源代码目录中,而增量型补丁在一个单独的目录/pub/linux/kernel/v2.6/incr中。

在这个肮脏的世界,你是我的最爱

Thursday, 1. March 2007, 12:48:24


不是不能等你,也不是不再喜欢你了。只是觉得现在确实是该离开你的时候了,你已经有自己喜欢的人了,有一个能在你身边照顾你的人了,离开你虽然我还是不舍得但是终于放心了。不管你们之间出现了什么矛盾,我都希望你们还能和好如初,只要相爱就一定会在一起的。

关于我们之间的事,我觉得你做得对,换成我我也会这么做,你不用自责。你说过,我们之间有太多的不适合,我爱你只是一种习惯,我想你也是对的。生活也许本来就是这样,什么事都不可能十全十美,不能改变的事只能接受。三年了,我太累了,不想再纠缠于这种问题了。我想开始一种新的生活,开始不再想你。这两年离开你的日子里我也过得很充实,因为只要一想起那些和你在一起的点点滴滴,就能让我心里饱满很久很久。这两年我一直想让自己成为你的骄傲,好让你回到我身边,可我发现我错了,但现在看看又有什么关系呢?这些年来因为你我得到的甚至远比我失去的要多。所以,我还是得谢谢你。这辈子能认识你我就很满足了,也不能再奢求别的了。

关于未来,谁也说不准。中国的教育制度是一种失败,别太在意自己的学校。你可能很快就毕业了吧?希望你能找一个自己喜欢的工作(你那么喜欢孩子,怎么不考虑一下去幼儿园当老师呢?),哪怕它并不起眼,因为做自己喜欢做的事本身就是一种快乐,这是金钱换不来的。如果有人用金钱来衡量你,不要理他们。你是一个好姑娘,应该拥有属于你自己的幸福。

希望你能天天快乐!