2007-10-24

some facts about skin color

Witnesses were flabbergasted when the 72-year-old discoverer of the double helix suggested there was a biochemical link between exposure to sunlight and sexual urges. “That’s why you have Latin lovers,” Watson said. ``You’ve never heard of an English lover. Only an English patient.”

— James D Watson

–reference–
San Francisco Chronicle

2007-10-24

理论 vs 实践

The difference between theory and practice is a lot bigger in practice than in theory.

理论与实践的区别在实际上比理论上得出的还要大。

Peter Van Der Linden
《Expert C Programming》

2007-10-23

typedef howto

函数指针的声明可能是C语言中最复杂的声明了。

比如标准C中信号捕捉函数signal的实际声明如下:

void (* signal(int sig, void(*func)(int)))(int);

它的含义是:

signal是一个函数,其参数为整型 int sig以及一个指向函数的指针,这个被指向的函数接受一个整型的参数并返回值void。同时signal函数本身的返回值同他的一个参数一样,也是一个指向接受一个整型参数并返回void的函数指针。

horrible !

但我们在手册中看到的接口声明并非如此,而是非常简洁易读的如下形式:

sighandler_t signal(int signum, sighandler_t handler);

这是因为使用了typedef的缘故

typedef void (*sighandler_t)(int);

这样就可以用简洁的sighandler_t代表一复杂的函数指针了。

由此可见typedef的魔力。

经常用到typedef的地方还有结构体的声明,使用typedef可以少敲不少字。

typedef struct {
    int bar;
}foo,*pfoo; 

foo var;
pfoo pvar;
pvar = &var;

如果结构体中有指向自身的指针(这很常见,不是么?),上面的方法就不好用了 ,但我们另有解决方案:

typedef struct foo foo;

struct foo{
    int bar;
    foo * pbar;
};

foo var;

细心发现,typedef对于未存在的类型也能指定别名。

一个小陷阱:typedef与define的区别。

“typedef和宏文本替换之间存在一个关键性的区别……把typedef看作一中彻底的‘封装类型’ -- 在声明它后不能在向里面添加别的东西” --- C专家编程

#define foo int
unsigned foo i; // this is OK

typedef int bar
unsigned bar j; // illegal!

其次typedef可以保证声明中所有变量都是同一种类型。

例如:

#define foo int * 
typedef  int * bar;

foo i,j; // 等同于 int * i,j; 则i为指针,j为整型

bar m,n; // m,n都是指向整型的指针

结论: 使用define可能会引起潜在的错误,所以,还是使用typedef吧。

适度地使用typedef可以使程序简明清晰,不过,滥用typedef也是不好的,非常不好。我尤其不喜欢用typede给指向结构体指针取别名,谁希望与同一个结构体相关的变量出现好几个在字面上看起来不相关的名字?

–EOF–

2007-10-08

firefox中css高度溢出问题

使用DIV+CSS布局时,经常会遇到兼容性问题。很多情况下Firefox完美解析,而IE表地很垃圾,但似乎也有例外的时候。

当使用height属性指定div的高度时,Firefox会固定高度不变,即使内容的高度超出了规定的大小,div的高度不会变化。带来的结果就是文字外溢到div之外,画面混乱。

而同样的代码在IE下表现地却不错,IE在内容高度超出height指出的预期后,将会自动更改高度以适应内容。

解决方案如下:

Firefox提供了一个min-height属性,可以指定div的最小高度,当内容高度超出min-height的值后,Firefox将像IE一样自动调整大小。

可是IE不支持min-height属性,这样Firefox下工作正常的代码在IE下又失效了。

需要一些小小的css hack

!important作用是提高指定样式规则的应用优先权,有!important后缀的规则会在整个大括号的空间中优先被浏览器采用。

而这个标记是不为IE 6所识别的,所以可以利用这个功能,来实现不同浏览器的代码逻辑分支,以实现兼容的目的:

<div style="min-height:240px;height:auto!important;height:240px;"> 

上面的代码,在Firefox中会优先应用height:auto,而IE 6由于不识别!important,会应用最后面的height:240px。

这个hack有比交大的普适性,一个css内不同字段的分支,都可以用此特性来实现。

–EOF–

reference:
http://www.webmasterworld.com/forum83/6871.htm

2007-10-07

manpages索引更新

从debian sarge 转到 etch后,就发现man东西少了很多,基本的函数,系统调用都没有相应的man手册页。猜想可能是某些和开发相关的包没有装。后来在Synaptic中搜索documentaion,一项一项找,最后发现是manpages-dev没有装。

apt-get install manpages-dev

基本的系统调用、库函数等就都有了。但man -k 和man -f却依然找不到这些函数。猜想可能是存在某些索引之类的东东。可是在网上没有找到在哪里更新索引的指导。man自身的手册页实在太长,看不下去。后来也就将就了。

ubuntu和debian的情况一样,同样默认不安装manpages-dev,无奈,只能忍受。

以前小时候找不到东西经常会很生气,而且越气急败坏越找不到。往往一个小东西搞得一天心情都很差。后来妈妈劝导我,找不到就放一放,过一段时间它会自己出来的。且不论这个理论是否正确,对于调节情绪来说还是相当有用的,况且事实证明最终那些找不到的小东西真会在日后的某一天中被偶然发现。所谓”众里寻她千百度,蓦然回首,她在灯火阑珊处”是也。

而且,我想,那一刻,任何人都会怀有一份惊喜与开心的。

前些日子偶然看到一博客,顺着他的文章一篇篇看下去 — 忽然,ho ho,the answer is Here!

http://blog.verycd.com/yoyopub/showentry=34994

原来manpage的索引由mandb命令管理,在安装了新的manpage文件后,只需

mandb -c
[/basj]

更新一下索引即可。

again,thanks for sharing。

–update–

日前发现manpages-dev包中没有posix相关的内容,包括pthread等的说明,找了一下,这些东西在manpages-posix和manpages-posix-dev包中,装上再重新更新一下索引就可以查阅了。

–EOF–

2007-10-07

becoming jane

“相呴以湿,相濡以沫,不如相忘于江湖。”

看完becoming jane,浮现在脑中的便是这句话。

人世间很多事情往往不能随意,牵扯了太多东西的爱情尤其如此。如果无法耳鬓厮磨,相守终身,何不微笑着说声再见,相忘且相望于江湖。

So, Keep smilling, and, say goodbye.

2007-10-03

Linux下瞬时cpu使用率的统计

top是linux下查看cpu使用率最常见的命令,功能很强大,使用也很方便,是系统管理的好帮手。

在bash脚本中集成top命令获取cpu使用率很简单,但是如果我们想要在C代码中获取当前cpu占用率,又该如何处理呢?

首先要了解一下top的工作原理

1、linux系统通过/proc/stat伪文件系统来输出当前的cpu使用情况,而top正是通过读取此文件中的数据来实现cpu使用情况的统计。
2、cpu占用率并不是一个瞬时概念,而是一个短时间内的统计值,因此无法通过瞬时计算得出,而必须通过一定时间差内的统计来实现。

stat的文件结构

stat文件的前几行为CPU使用信息描述。
具体有多少行取决于系统有多少块CPU,但行中的字段都是相同的。第一行以字符串’CPU’开头,为系统总的CPU使用情况。其余行以’CPU’+CPUID开头,用以分别描述单个CPU。

第一行内容如下:

cpu 15718 197 2574 136003 3881 690 531 0

数字的单位为USER_HZ(1/100ths of a second on most architectures)。
第一个字符串为CPU标识,其后四个数字依次为在用户态消耗的时间片,在低优先级的用户态消耗的时间片,内核态消耗的时间片以及空闲时间片。

2.4内核中,以上即为CPU使用信息的全部内容。但在2.6内核中,这一行还多出了三个额外的数据。分别为 iowait,irq,softirq等操作所耗费的时间片。

了解了以上信息后,我们就可以开始准备编码了~ 不过,最好还是有个参考~

参照busybox的top源代码,我们实现自己的cpu统计程序如下:

#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <errno.h>

#define SMLBUFSIZ 256

typedef unsigned long long ul_t;

typedef struct cpu_t {
    ul_t u, n, s, i, w, x, y, z; // as represented in /proc/stat
    ul_t u_sav, s_sav, n_sav, i_sav, w_sav, x_sav, y_sav, z_sav; // in the order of our display
} cpu_t;

cpu_t *cpus_refresh (cpu_t *cpus)
{
    static FILE *fp = NULL;
    int i;
    int num;
    char buf[SMLBUFSIZ];

    if (!fp) {
        if (!(fp = fopen("/proc/stat", "r")))
            fprintf(stderr,"Failed /proc/stat open: %s", strerror(errno));
    }
    rewind(fp);
    fflush(fp);

    // first value the last slot with the cpu summary line
    if (!fgets(buf, sizeof(buf), fp)) fprintf(stderr,"failed /proc/stat read");

    cpus->x = 0;
    cpus->y = 0;
    cpus->z = 0;
    num = sscanf(buf, "cpu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu",
            &cpus->u,
            &cpus->n,
            &cpus->s,
            &cpus->i,
            &cpus->w,
            &cpus->x,
            &cpus->y,
            &cpus->z
            );
    if (num < 4)
        fprintf(stderr,"failed /proc/stat read");

    return cpus;
}

static void format_output (cpu_t *cpu, const char *pfx)
{
#define TRIMz(x)  ((tz = (long long)(x)) < 0 ? 0 : tz)
    long long u_frme, s_frme, n_frme, i_frme, w_frme, x_frme, y_frme, z_frme, tot_frme, tz;
    float scale;

    u_frme = cpu->u - cpu->u_sav;
    s_frme = cpu->s - cpu->s_sav;
    n_frme = cpu->n - cpu->n_sav;
    i_frme = TRIMz(cpu->i - cpu->i_sav);
    w_frme = cpu->w - cpu->w_sav;
    x_frme = cpu->x - cpu->x_sav;
    y_frme = cpu->y - cpu->y_sav;
    z_frme = cpu->z - cpu->z_sav;
    tot_frme = u_frme + s_frme + n_frme + i_frme + w_frme + x_frme + y_frme + z_frme;
    if (tot_frme < 1) tot_frme = 1;
    scale = 100.0 / (float)tot_frme;

    fprintf(stderr,"%s: %.2f%%us,   %.2f%%sy,   %.2f%%ni,   %.2f%%id,   %.2f%%wa,   %.2f%%hi,   %.2f%%si,   %.2f%%st\n",
                pfx,
                (float)u_frme * scale,
                (float)s_frme * scale,
                (float)n_frme * scale,
                (float)i_frme * scale,
                (float)w_frme * scale,
                (float)x_frme * scale,
                (float)y_frme * scale,
                (float)z_frme * scale);
    
    cpu->u_sav = cpu->u;
    cpu->s_sav = cpu->s;
    cpu->n_sav = cpu->n;
    cpu->i_sav = cpu->i;
    cpu->w_sav = cpu->w;
    cpu->x_sav = cpu->x;
    cpu->y_sav = cpu->y;
    cpu->z_sav = cpu->z;

#undef TRIMz
}

int main(){

    cpu_t * cpu;
    cpu =(cpu_t *)malloc(sizeof(cpu_t));
    memset(cpu,0,sizeof(cpu_t));


    while(1){
        cpus_refresh(cpu);
        format_output(cpu,"Cpu usage:  ");
        sleep(1);
    }

}

需要注意的是,无论用什么方法,我们都无法获取到系统瞬时的CPU使用率,而只能通过近期的使用情况来推测。

在这个程序中,第一次调用cpus_refresh时返回的并不是当前的CPU使用率,而是从系统启动以来至今为止的CPU使用率,这并不能反映当前的CPU使用情况。第二次调用计算差值后得到的是这一秒内CPU的使用率,用它来度量当前瞬时的使用率还是合理的。

–EOF-

2007-09-27

nanosleep精度问题分析

最近有个同学在做流量模拟,发包时需要精确控制发包间隔,即要用到高精度的延时。

首先想到的便是nanosleep系统调用,毕竟从接口上看,它可以达到纳秒级的精度(1*10^-9)。

然而实际上nanosleep的解析度远没有达到预期,把时间间隔设地再小,精度也始终只有一微秒左右。

WHY?

READ THE FUCKING MANUAM

原来,2.6内核中nanosleep实现基于内核中的普通定时器机制,最大解析度也只有1/HZs,所以nanpsleep暂停的最小单位即是1ms,考虑到进程的切换与函数调用消耗的时间,实际的最小单位可能会在10ms左右甚至更长。

如果是这样,那为何内核还要提供这样一个名不副实的函数呢?
原来在2.4内核中,当把进程调度策略设置成实时级别的,诸如SCHED_FIFO或SCHED_RR,则对于较小的延迟时间,内核将采用忙等的方式进行计时处理。由此提供的解析精度可以达到2ms以下。

尝试了一下,实际解析度的确升高了,效果不错。

#include   <stdio.h>
#include   <time.h>
#include   <sys/time.h>
#include   <sys/types.h>
#include   <unistd.h>
#include   <sched.h>

#define BILLION  1000000L

void do_sleep(int looptimes,int sleeptimes){
    
    int i,j;
    struct timespec tv={0,1};
    struct timeval start, stop;
    long accum;

    for(i=0;i<looptimes;i++){
        gettimeofday(&start,NULL);

        for(j=0; j<sleeptimes; j++){
            nanosleep(&tv,NULL);
        }

        gettimeofday(&stop,NULL);
        accum = ( stop.tv_sec - start.tv_sec )*BILLION + ( stop.tv_usec - start.tv_usec );

        fprintf(stderr,"%ld\t", accum/sleeptimes );
    }
    
    fprintf(stderr,"\n");
}

int main( int argc, char** argv )
{
    struct sched_param sp;
        
    sp.sched_priority=0;
    sched_setscheduler(0,SCHED_FIFO,&sp);

    fprintf(stderr,"Schedule priority: %d\n",sp.sched_priority);
        
    do_sleep(10,100);

    sp.sched_priority=99;
    sched_setscheduler(0,SCHED_FIFO,&sp);
    
    fprintf(stderr,"Schedule priority: %d\n",sp.sched_priority);
    
    do_sleep(10,100);
    
    return 0;
}

实验环境:
kernel version: Linux version 2.4.20-8smp (bhcompile@stripples.devel.redhat.com) (gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5)) #1 SMP Thu Mar 13 16:43:01 EST 2003

–EOF–

2007-09-10

Laws in China

关于彭宇,我也想说两句。

早在04年,南京也曾发生过一件轰动一时的事情。即所谓的“鸭吧案”。

顾名思义,即是男人在给男人提供性服务。无论此案的个中曲折,最后的审判结果为鸭吧老板被判刑8年。我虽不了解法律,但至少知道在法律成文的国家,“法律无明文规定不为罪”的原则还是有的,只是不知在此案中法院根据什么定罪以及量刑。

新华网关于这件事的报道中有一段如下:

“事实上,检察机关在接到警方的提请批捕后,对其情节的定性有过一些争议。我国《刑法》第358条规定的“组织他人卖淫活动”并对组织同性卖淫行为没有明确的界定,按照“法律无明文规定不为罪”的法律原则,李宁等人的行为应当“无罪释放”。于是检察院起初作出了不批捕的决定,当时李宁等人的拘留时间已满30天,警方在向检察院申请复议的同时,将李宁等人释放。可检察院复议的结果仍然维持原有意见。鉴于案件的特殊性,检察院、警方将此案向上级部门汇报,江苏省政法部门召开了案件研讨会。会议决定立即由江苏省高院向最高院请示,最高院接到请示后,随即向全国人大常委会作出汇报,最终人大常委会作出口头答复:组织男青年向同性卖淫,比照组织卖淫罪定罪量刑。”

但这里似乎忽略了一个问题,那就是法律的解释权属于谁,法律需要解释的是后又如何操作的问题。

关于法律的解释权,宪法规定如下:

“法律解释权属于全国人民代表大会常务委员会。

法律有以下情况之一的,由全国人民代表大会常务委员会解释:

(一)法律的规定需要进一步明确具体含义的;

(二)法律制定后出现新的情况,需要明确适用法律依据的。

国务院、中央军事委员会、最高人民法院、最高人民检察院和全国人民代表大会各专门委员会以及省、自治区、直辖市的人民代表大会常务委员会可以向全国人民代表大会常务委员会提出法律解释要求。

常务委员会工作机构研究拟订法律解释草案,由委员长会议决定列入常务委员会会议议程。

法律解释草案经常务委员会会议审议,由法律委员会根据常务委员会组成人员的审议意见进行审议、修改,提出法律解释草案表决稿。

法律解释草案表决稿由常务委员会全体组成人员的过半数通过,由常务委员会发布公告予以公布。

全国人民代表大会常务委员会的法律解释同法律具有同等效力。”

可以看到,如果法律需要新的解释的话,是需要一个严谨的流程的。虽然按照常识,此案的被告理当受刑,但法院及检察机关仅仅凭借人大常委的一个口头答复即对公民进行判决,岂不有失法律的严谨及公正?

三年后,同样是在南京。法官像福尔摩斯一般作出了一番“精彩”的推理。判决书通篇充斥着“一般不会”,“不可能可能”,“从常理分析”,“能性比较大”,“更符合情理的做法”,“与情理相悖”等猜测性的字眼,最终得出了彭宇有罪的结论。在这份判决书面前,法律的客观性丧失殆尽,审判法官随意发挥的即兴表演。按照法官的逻辑,在我们的和谐社会中,一个正常人是不会也不应该向路边跌倒的老人伸出援手的,因为这不合“常理”且”与情理相悖” 。可悲我中华五千年文明古国,道德已经沦丧到如此地步。

且不论这份荒谬的判决书,在案件的举证中,法院居然没有采纳被告的人证,反而相信了原告提供的一份无法确定真伪的“电子版笔录”,更加让人怀疑法院的公正与独立性。

彭伟已经提起上诉,希望法院可以给他一个公道,拯救一下我们对法制日益丧失的信心。

2007-09-06

解决ubuntu播放受限制的媒体格式

由于版权原因,Unbutu 7.04中取消了对于mp3等媒体格式的支持,也就是xine对于mp3等格式的支持。
由于绝大部分的播放器都是调用的xine引擎,所以包括kaffeine,amarok等都无法正常使用了,即使像往常一样安装了mplayer的win32codecs也不行。

版权真是件头痛的事,TNND。

不过凡事总有解决的方法,尤其在互联网上~ ubuntu官网已经给出了解决方案(我不主动给你装,但是用户自己装和我没关系~)。

第一步:

点击 Applications → Add/Remove. 在右上方选则All available applications. 然后再左边选择Other ,在出现的菜单中选择 Ubuntu restricted extras 包. 单击 OK.

第二步:

sudo apt-get install gstreamer0.10-pitfdll gstreamer0.10-ffmpeg gstreamer0.10-plugins-bad gstreamer0.10-plugins-bad-multiverse gstreamer0.10-plugins-ugly gstreamer0.10-plugins-ugly-multiverse gxine libxine-main1 libxine-extracodecs ogle ogle-gui

第三步:

sudo apt-get install w32codecs

这样就可以顺利播放大部分视频格式了。