2013年12月21日星期六

万年历程序

#include
#include
#include

int week(int y,int m,int d);//函数声明

void main()
{
    //初始化月份的天数
    int monthday[12]={31,28,31,30,31,30,31,31,30,31,30,31};

    int y,w,i,m=1,d=1;
    printf("请输入一个年份yyyy:\n");
    scanf("%d",&y);

    //如果是闰年,修改第二个月天数
    if ( (y % 4 == 0 && y % 100 != 0)|| y % 400 == 0 ){
        monthday[1]=29;
    }


    for(m=1;m<=12;m++){
        //循环打印每个月
        printf("\n %d年,%d月\n",y,m);
        printf(" 日  一  二  三  四  五  六 \n");

        for (d=1;d<=monthday[m-1];d++){
            //获取对应的星期
            w=week(y,m,d);
            if(d==1){
                //打印每月第一天前面的空格
                for (i=0;i                    printf("%3c ",' ');
                }
            }

            printf("%3d ",d);

            //每星期换行
            if(w==6) printf(" \n");
        }

        printf("\n\n输入任意字符继续\n");
        getch();
    }

    system("pause");
}

int week (int y,int m,int d)
{
    //http://hi.baidu.com/wlzqi/blog/item/65b16b606403df44ebf8f8a2.html
    int w;
    if((m==1)||(m==2)){
        y--;
        m+=12;
    }
    w=(d+2*m+3*(m+1)/5+y+y/4-y/100+y/400+1)%7;
    return w;
}

2013年12月10日星期二

grep 用法

我本不想写这篇文章,首先我觉得这些东西大家肯定都知道,其次就算真不知道还有手册。
直到那天面试的时候我碰到一个哥们,我问他grep你都知道哪些选项?他告诉我,只有-r。我当时就乐了,既然grep是你常用的命令,你凭什么只 知道-r?他回答说,他只想把精力放到内核上,没有时间来学习这些东西。我笑,正是因为你没有时间,所以你才应该提高你的工作效率,而熟悉命令行显然是 Linux上一种提高工作效率的方式。有句老话说得好:“磨刀不误砍柴功。”
有的同学可能觉得我在提倡死记硬背了,事实上我比你更反对中国教育的那种死记硬背。我的观点很简单:既然你用得多,那么有些东西,比如grep的一些选项,自然而然就应该记住了,无须刻意去背。
所以,我在这里以grep为例来展示一下。注意,以下内容没有参考一眼grep的手册。
grep最常用的选项可能是-i,-n和-r了,至少于我如此。-i是忽略大小写,-n可以告诉你找到的东西在文件的哪一行。-r或者-R(看你愿不愿意多按个shift键了),可以去递归一个目录。
-A和-B,你可能就用的比较少了,前者制定显示匹配到的那一行之后的几行,后者指定之前的,比如grep -A 3 -B 4就是说也要显示匹配到的那一行之前的4行和之后的3行,可见A是After,B是Before。用得着刻意去记嘛?显然不用。
-I(大写i)可能用得就更不多了,可惜啊,它非常有用。比如你编译出的内核二进制和你的源代码在同一个目录时,你grep一些字符串的时候会发现一些.o文件中也可以找到,很明显它不是我们想要的,这时候-I就派上用场啦!它告诉grep去忽略二进制文件。
这让我想到了另一个--exclude(我记得似乎没有短选项与之对应),顾名思义,它是用来排除一些文件。比如你编译的内核目录下还有*.cmd这种文件的话,它不是二进制,所以-I排除不掉,这时候你就可以用--exclude "*.cmd"了。
-H,这个用得更少了,你一般不会需要它,因为grep默认就会输出文件名。然而,当grep与find联手的时候就不会了(至于为什么,留给你作 为课后作业),这时候你就要用到-H了。比如,我在内核源代码目录下查找CONFIG_DEBUG_KMEMLEAK定义在哪,我通常这么做:find . -iname 'kconfig*' -exec grep -Hwn DEBUG_KMEMLEAK '{}' \;
我上面用到了另一个选项-w,看见了嘛?它可能是另外一个被严重忽视了的选项,仅次于-I啊!它的意思是告诉grep我所查找的是一个完整的单词, 也就是说,当你找DEBUG_KMEMLEAK的时候它不会给你找出DEBUG_KMEMLEAK_EARLY_LOG_SIZE,你懂的。这可以省去你 手工去加\b了。
噢,我差点儿忘了亲爱的-e,多数情况下你也不需要它,因为grep后面接的就是一个regrex嘛!-e神马时候派上用场呢?我建议你在这里仔细 想想,一个很特殊的情况——我要搜索的字符串以"-"开头时!比如我要搜索"-wangcong"这个字符串,直接grep "-wangcong"显然是不行滴!grep会认为那是"-w -a -n -g -c -o -n -g",无论你怎么加引号!一种解决方法是加反斜线,而另一种方法就是-e "-wangcong"了。顺便说一句,使用多次-e就相当于进行一个“或”操作,所以grep "vmx\|svm"就等价于grep -e vmx -e svm。
-o我估计用的人也不多,它的意思是只输出匹配到的东西,同一行的其它东西不输出。例如,我想搜索printk.c中全部的C语言字符串时,我会这 么做:grep -o '".*"' kernel/printk.c,有点儿类似于strings kernel/printk.o。
-b,知道这个人的灰常少了吧?如果你知道,恭喜你晋级grep高手级别了!我承认我只用过它一次,是在一个脚本中,我想知道某个“字符串”出现在 文件的第几个字节。我印象中这里是有bug的,因为我当时总得不到正确的结果,当然也有可能是我理解不对,没看手册而且没有再次实验,所以这个问题就留给 你了。:-)
-q嘛,大家都知道,脚本中常用。
-c嘛,比如统计CPU个数:grep -c '^processor' /proc/cpuinfo,实在没必要多一个管道去 grep '^processor' /proc/cpuinfo | wc -l。
好了,我就想起来这么多了,欢迎补充。我觉得一个好的Linux程序员应该对他/她敲出的每一行命令的每一个选项都精益求精,不多不少。
我知道有些人对此不屑一顾,嗤之以鼻,我只想告诉这些人一句话:“天下大事必做于细,天下难事必做于易。”你要是认为我这是在教育你,你就错大了,我对教育人,尤其是教育你这种人,没任何兴趣!你倒找给我钱我都不会稀罕去教育你!有他妈的多远给我滚他妈的多远!
附我窜改的《见与不见》:
你知,或者不知它/命令就在那里/不悲不喜
你看,或者不看它/手册就在那里/不来不去
你爱,或者不爱它/程序就在那里/不吵不闹
你用,或者不用它/二进制就在你的机器上/不亢不卑
去了解它们/或者/让它住进你的心里
人机合一/融为一体

shell中if的相关参数

[ -a FILE ]     如果 FILE 存在则为真。
[ -b FILE ]     如果 FILE 存在且是一个块特殊文件则为真。
[ -c FILE ]     如果 FILE 存在且是一个字特殊文件则为真。
[ -d FILE ]     如果 FILE 存在且是一个目录则为真。
[ -e FILE ]     如果 FILE 存在则为真。
[ -f FILE ]     如果 FILE 存在且是一个普通文件则为真。
[ -g FILE ]     如果 FILE 存在且已经设置了SGID则为真。
[ -h FILE ]     如果 FILE 存在且是一个符号连接则为真。
[ -k FILE ]     如果 FILE 存在且已经设置了粘制位则为真。
[ -p FILE ]     如果 FILE 存在且是一个名字管道(F如果O)则为真。
[ -r FILE ]     如果 FILE 存在且是可读的则为真。
[ -s FILE ]     如果 FILE 存在且大小不为0则为真。
[ -t FD ]     如果文件描述符 FD 打开且指向一个终端则为真。
[ -u FILE ]     如果 FILE 存在且设置了SUID (set user ID)则为真。
[ -w FILE ]     如果 FILE 如果 FILE 存在且是可写的则为真。
[ -x FILE ]     如果 FILE 存在且是可执行的则为真。
[ -O FILE ]     如果 FILE 存在且属有效用户ID则为真。
[ -G FILE ]     如果 FILE 存在且属有效用户组则为真。
[ -L FILE ]     如果 FILE 存在且是一个符号连接则为真。
[ -N FILE ]     如果 FILE 存在 and has been mod如果ied since it was last read则为真。
[ -S FILE ]     如果 FILE 存在且是一个套接字则为真。
[ FILE1 -nt FILE2 ]     如果 FILE1 has been changed more recently than FILE2, or 如果 FILE1 exists and FILE2 does not则为真。
[ FILE1 -ot FILE2 ]     如果 FILE1 比 FILE2 要老, 或者 FILE2 存在且 FILE1 不存在则为真。
[ FILE1 -ef FILE2 ]     如果 FILE1 和 FILE2 指向相同的设备和节点号则为真。
[ -o OPTIONNAME ]     如果 shell选项 “OPTIONNAME” 开启则为真。
[ -z STRING ]     “STRING” 的长度为零则为真。
[ -n STRING ] or [ STRING ]     “STRING” 的长度为非零 non-zero则为真。
[ STRING1 == STRING2 ]     如果2个字符串相同。 “=” may be used instead of “==” for strict POSIX compliance则为真。
[ STRING1 != STRING2 ]     如果字符串不相等则为真。
[ STRING1 < STRING2 ]     如果 “STRING1” sorts before “STRING2” lexicographically in the current locale则为真。
[ STRING1 > STRING2 ]     如果 “STRING1” sorts after “STRING2” lexicographically in the current locale则为真。
[ ARG1 OP ARG2 ]     “OP” is one of -eq, -ne, -lt, -le, -gt or -ge. These arithmetic binary operators return true if “ARG1” is equal to, not equal to, less than, less than or equal to, greater than, or greater than or equal to “ARG2”, respectively. “ARG1” and “ARG2” are integers.
源于:http://hi.baidu.com/piaoliuzaiwai/blog/item/2000f3fc9ec960fcfc037f7f.html

使用cscope阅读内核源代码

代码阅读工具简介
对于学习Linux内核的人来说,源代码的阅读尤为重要。因为所有设计思想、内部机制都是以代码的形式实现,所有的资料也都是为了更好的诠释代码。 那么一个好的阅读工具,能够提高阅读的效率和效果。常见的代码阅读工具有,KScope、Source Navigator、Source Insight、lxr、Cscope等。
* KScope[1]是一款KDE桌面环境下的源代码阅读、浏览工具,自带了编辑功能。比较适合C语言编写的大型项目。KScope底层使用Cscope作为源代码的分析引擎。多数发行版都提供了KScope的安装包。
* “Source Navigator”是红帽子公司的,以GNU GPL发布,可从官方网站[2]下载使用。
* “Source Insight”目前只有Windows平台的,官方网站[3]。需要注册才能使用,或者从网上下载注册机生成注册码。在Linux下通过wine模拟虽然可以方便使用,但它毕竟是Windows平台的东西,并不能很自由的使用。
* lxr(linux cross reference)[4]为程序源代码建立索引数据库,利用perl脚本CGI动态生成包含源码的web页面,你可以用任何一种浏览器查阅。缺点是需要服务器支持,还有速度。
* “Cscope”[5]为终端下的代码阅读工具,资源消耗少,对那些忠于命令行的行操作的人,使用起来更加方便、灵活。这也是这篇文章推荐使用的一个重要原因。也有人把Cscope和Emasc绑定阅读源码。当然工具的选取,也取决于个人习惯。
Vim+Ctags+Cscope
cscope的工作需要vim、ctags的配合,它们都是基于命令行的。在Ubuntu下,用户只需执行“sudo apt-get install cscope cscope-indexer ctags vim”即可完成软件安装。下面只是给出了三种工具的常用方法,更多功能可查看man手册,或者官方文档。
Vim
vim被看作是专门为程序员打造的文本编辑器,其丰富的编辑命令都是常用的简单字符,用户很容易上手。vim可对180多种语言的语法高亮,对C语 言自动缩进,真则表达式字符匹配查找,功能强大,并支持多个操作系统平台。关于vim的使用,这里不做讲解。vim中文文档[6]。
Ubuntu系统自带的vim,没有语法加亮功能。上面的安装命令已经更新了vim,在vim 配置文件 ~/.vimrc中 添加一行 “syntax on”,这样在vim中打开的源码就有了语法高亮显示。
vim自带了很多颜色主题,可以直接选取下面一行添加到vim配置文件当中,重新打开vim即可生效。
colorscheme elflord “我使用这个
colorscheme darkblue
colorscheme evening
colorscheme murphy
colorscheme torte
colorscheme desert
Ctags
在源代码根目录下执行 ctags -R 命令用来为程序源代码生成标签文件,其-r选项表示递归操作,同时为子目录也生成标签文件。vim利用生成的标签文件,可以进行相应检索、并在不同的文件C语言元素之间来回切换。
在vim中ctags的简单使用
1) 跳转到指定的函数进入vim后,用 “:tag func_name“ 跳到函数func_name处。使用tag命令时,可以使用TAB键进行匹配查找,继续按TAB键向下切换。
某个函数有多个定义时
:tag
跳到第一个定义处,优先跳转到当前文件
:tnext
跳到第一个
:tfirst
跳到前count个
:[count]tprevious
跳到后count个
:[count]tnext
跳到最后一个
:tlast
你也可以在所有tagname中选择:
:tselect tagname
如果想跳到包含block的标识符:“tag /block” 然后用TAB键来选择。这里’/'就是告诉vim ‘block’是一个语句块标签。
2)用“CTRL + ]“快捷键,跳转到光标所在函数标识符的定义处。
3)使用“CTRL + T”退回上层。 如果想在以write_开头的标识符中选择一下, :tselect /^write_ 这里,’^'表示开头,同理,’$'表示末尾。多个同名的标识符
Cscope
运行cscope命令,出现两个面板,上方是一个查找结果的显示面板,下方是一个查找条件指定面板。使用TAB键在两个面板间切换,也可使用上下左 右方向件和翻页键在同一面板内贴换位置。选中显示面板的某个项,回车即可进入该文件,这是调用vim打开文件,这时就可以结合ctags使用了。当然也可 以直接使用vim打开文件,结合ctags阅读源码。
使用前,必须现使用“cscope-indexer -r”命令递归生成索引信息文件。特殊情况下,还需要用户使用find命令,主动生成索引信息文件,并指定给cscope工具。 cscope提供了如下九种查询方式:
Find this C symbol:
#查找指定的C符号
Find this global definition:
#查找指定的全局定义
Find functions called by this function:
#查找指定函数调用的函数
Find functions calling this function:
#查找调用指定函数的函数
Find this text string:
#查找字符串
Change this text string:
#修改指定字符串
Find this egrep pattern:
#查找匹配字符
Find this file:
#查找指定文件
Find files #including this file:
#指定引用头文件进行查找
在对应某一项中输入查找条件,回车即可进行查询,并将结果显示在显示面板。
应用实例
下面以使用cscope阅读内核源代码为例:
$ wget http://kernel.org/pub/linux/kernel/v2.6/linux-2.6.27.6.tar.bz2
#从Linux内核官网下载内核源代码
$ tar xvfj linux-2.6.27.6.tar.bz2
#解压文件
$ cd linux-2.6.27.6
#进入源代码根目录
$ ctags -R
#递归生成标签文件
$ cscope-indexer -r
#递归生成索引信息文件
$ cscope
#使用cscope阅读源码
对于内核源代码也可以直接使用“make cscope”、“make tags”生成相应的索引信息、标签文件。
标签文件、索引信息文件只需要第一次或者代码发生变动时生成,以后使用直接运行cscope即可。
总结
要达到灵活应用的境界,还必须熟练结合其他工具,如grep、正则表达式等的使用。其中有很多技巧性的东西需要去不断总结、积累。
[1] http://kscope.sourceforge.net/
[2] http://sourcenav.sourceforge.net/
[3] http://www.sourceinsight.com/
[4] http://lxr.linux.no/
[5] http://cscope.sourceforge.net/
[6] http://vcd.gro.clinux.org/

并发编程

http://concur.rspace.googlecode.com/hg/talk/concur.html#hello
http://www.haskell.org/haskellwiki/Parallelism_vs._Concurrency
http://greenteapress.com/semaphores/

https://blog.heroku.com/archives/2013/2/24/concurrency_is_not_parallelism
http://supertech.csail.mit.edu/cilk/