行者无疆 始于足下 - 行走,思考,在路上

创新工厂电面小记

其实我一直对这些明星公司抱有一种仰望的态度,像前几天的百度,已经很让我惊喜,给了我很大的信心。昨天的创新工厂电面,虽然自己被虐的比较惨,但是还是进一步明确了自己的方向,了解了自己的差距。

对开复老师,除了仰慕,更多的是一种敬重。老实说我并不觉得开复老师是个天才,我认为他能成功,有一部分原因是在正确的时间正确的地点遇到了正确的人。我从来就不相信“穷人的孩子早当家”,更多时候,良好的家庭背景条件,有眼光的父母亲情教育,宽容大度自由的义务教育和高等教育,是一个人成长成才的助推器。敬重开复,是因为这么多年他为帮助中国青年成长所倾注的心血。当然,少部分人在他背后说三道四,说他虚伪做作,对此,我只能说,这些小人连“虚伪做作”的资本都没有。

好了,废话少说,说说本次面试吧。面试的过程很简单,就是给你一套题,一个小时的时间,然后在根据你答题情况刨根问底。答题的网站是collabedit。大概是由于世界杯的原因,网络比较拥塞,刷了5分钟才刷出题目来。题目总共有22道,考的范围非常广泛,很能反应一个人平时的积累。由于不方便,所以我暂时不能把所有题目原数贴出。大概概述一下题目分布情况吧:

  1. c\c++基础题
  2. 双向链表插入
  3. 二叉树遍历(三种方式)
  4. 栈的基本操作
  5. 概率问题
  6. tcp和udp区别联系
  7. sql基础语法问题
  8. 概率问题
  9. 图论问题(好像是“三角形无关图”,就是求一个8个顶点的无向图中,不含三角形,那么最多的边有多少)
  10. 函数递归问题
  11. 编程序题目:给定一条直线(L: x=5)和一个定点序列a[n],组成一条折线a[0]a[1]...a[n],求这条折线与直线(L: x=5)有多少个交点。
  12. 设计模式(什么是Singleton模式,PHP如何实现)
  13. PHP和MySQL
  14. PHP中的_POST数组
  15. PHP中"==="和"=="两个操作符的差别
  16. 还是PHP
  17. 还是PHP
  18. 还是PHP
  19. JavaScript和iframe
  20. MySql: datetime和timestamp差别
  21. JavaScript和iframe
  22. jQuery: onload()和document.ready()

前面十道题目,除了两道概率问题,答得还算不错;第11道编程题目,我想到的是计算几何中判断线段相交的方法和问题,于是就用内积的方法写了个程序糊弄了上去。结果面试官告诉我说这道题目我只拿到了30%的分数。我一诧异,忙问个中缘由。他说这道题目考的不是线段相交。线段(L: x=5)是给定的,所以不用考虑的那么复杂,根本用不到内积这些东西,我说那就看a[n].x和5相比究竟震动了几次。然后面试官说如果两个交点相同,那么这两个点是算作一个点的。我一想,是啊是啊,是这个样子的。然后他说用怎样的方法可以去掉这些重复的点呢?我说简单啊,算出所有的点后直接排序不就好了。他说时间复杂度太高,让我优化一下。我想了半天也不知道怎么回答,他又提示我说哈希表怎么样?我哈希表用的不熟,转念一想,用哈希表的话,相同的点经过哈希函数映射确实可以“合并”。于是我慌忙补充下时间是线性的云云。

后面的题目我就束手无策了。对javascript和php,我只是听说,很早之前看过一些入门的章节,早忘光了。除了"=="和"==="是查了下手头的一本书简单写了下,其余的题目基本是空白,很是尴尬。面试官表示说你前面的十道题目答的都不错,编程题目不甚理想,灵活度不够,"=="和"==="是不是百度出来的?我说不是不是,也没有别人帮忙,寝室同学都不是计算机学院的。

最后他问我对这套题目有什么缺陷,或者自己有什么优点没有表现出来。我就说自己对linux还算了解,他随机给我出了一道题目:找出一个目录中文件名中包含hello, world的文件。我说用find就行,find . -name "hello, world", 他说不对,我想起来还得加一个recursive的参数。然后我又讲到了自己实验室的项目,他听了下又给我出了道题目:如何在iphone上面写一个帮助用户挑西瓜的程序。我犹豫了下问“iphone有没有办法称出一个物体的重量”——好蠢的问题……然后面试官提醒说“你平时是怎么挑西瓜的”。我说先看成色,再听声音,再看重量。然后我灵机一动说先挑出一部分好的西瓜,听他们的声音,然后将这些声音作成一个样本库,提取初相应的特征。然后去挑西瓜,用iphone录下用户敲西瓜的声音,与样本库里面的样本比对,看看相似度。嗯。大概这样。面试官表示这个答案还行。最后又问了我个排序的问题:给你若干个人,让你按照他们的年龄排序,有什么方法。显然这道题目是有陷阱的。但是我一时想不通,就随口说快排归并。他说不对,问我有没有听过桶排序,我说听说过不了解,他说就是做按照年龄1-100岁做100个桶,然后把扫描这些用户,按照年龄将用户排到桶里就可以了。我一想这么一来,时间复杂度只有[tex]O(n)[/tex]。是,是这么回事,基于比较的排序时间复杂度下限是[tex]O(\lg n)[/tex],突破这个极限的方法就是不采用比较,另寻他法进行排序。这就是“线性排序“。可是我对“线性排序“又不甚了解,导致现在的悲剧。综合而言还是自己的算法功底不够。

临结束时,他问我又没有什么问题要问他。我还是说“想听一下你对我的评价“,他说你的情况比较复杂,需要对我有一个评分,上报HR,可能需要多轮面试。我又问如果最后没有通知是不是就挂了,他说是的。我说好的,谢谢,辛苦了。

就这样结束了……总之,差距尤在,暑假需要实习,在算法,网络,数据库三方面加强训练。嗯。

百度电面

千呼万唤,数模成绩出来了,校赛二等奖,达到了赛前的预期,还算是不错的结果。之后就是准备自己的简历,开始找实习。

在网上闲逛了一天,看了各种各样的教程,重点推荐《简历制作——step by step》,了解基本原则,然后开始动手。简历的排版有多种方式,最基本的是word版,拉拉表格,搞搞字体即可;花哨一点的可以用ps,indesign,只是有些牛刀杀鸡罢了;我不想弄的那么花哨,因此我选择用[tex]\LaTeX[/tex]排版我的简历。正式动手之前,我扫了一下《LaTeX2e中文用户手册》,进一步熟悉了定制[tex]\LaTeX[/tex]的方法,并找到了以下资料作为参考:

我呢,就仿照着pluskid简历的风格,自己制作了一份,pdf和tex源文件可以在这里下载。然后就去88上找相应的信息,稀里糊涂的投了几家,包括百度、阿里、intel等。百度和阿里的效率很高,邮箱发过去简历,不到二十分钟就有了回音,百度更是在当天中午就打来了电话,问我第二天有没有时间,直接电话面试一下。我说好的。于是在6月13号下午一点,我找工作的处女面就这样献给了百度。

首先是客套的自我介绍,原来面试官是浙大02级的学长,怪不得对我这么“照顾”(至少在投简历时我不期望我的资本能够赢得这次面试的机会)。然后就是正经八百的面试。第一道题目是,给你十个瓶子,每个瓶子里装有白色的粉末,其中有一个瓶子中的白粉放入水中30分钟后可以变成蓝色(姑且把这粉末想像成硫酸铜)。现在给你无限制的水,问,在四十分钟内,最少能用几个瓶子,可以将这瓶特殊的粉末鉴别出来。我的直觉是这个问题与小学生的“天平挑苹果“的智力题类似——比如给你3个苹果,两个重量一样,另外一个比较重,用天平一次就能挑出来。我想到的大体思想还是先确定一个大概的范围,比如确定这个“硫酸铜“在前面五个瓶子中,然后在进一步缩小范围。但是此题的难点在于,所给的时间40分钟只够一次实验的时间,多出来的十分钟倒是没什么用,迷惑人用的。进一步想是不是该采用两个集合求交的方法来鉴别呢。此时时间大概过了三分钟,我的大脑依然在飞速的思索。最后我给出的答案是,将十个瓶子分为四组,分别是{1,2,3}、{3,4,5}、{6,7,8}、{8,9,10},每组三个瓶子都取出粉末放到编号为I, II, III, IV的瓶子里面。如果I, II同时变蓝,那么这个粉末就在第3瓶,如果III, IV同时变蓝,那么就是第8瓶,剩下的情况我们可以肯定这瓶粉末肯定在两个瓶子之中。不过结果不算完美,而我也只能得出这样的结果了。其实这道题目正确的答案是数的二进制表示法。我们将十个瓶子的编号{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}进行二进制编码,这样只需要四位二进制数即可,然后找四个瓶子装上水,对于白粉末,如果其二进制编码的某位上为1,我们就在相应的瓶子里放入该瓶的粉末(这话太绕了……),举个例子来说,瓶子3的四位二进制编码为0011,我们就在第I, II个瓶子中放入瓶子3中的粉末。所有的十个瓶子都这样做,最后,I, II, III, IV的颜色序列(蓝表示1,不变色表示0)就可以指示出“硫酸铜“所在瓶子的二进制编码!

第二道题目是一道概率题。概率是我的弱项,高中就学不好,大学更是一点都没有接触。题目大意是给你一个字符串(可能有几亿个字符),给定一个特殊的字符'a',再给定一个可以产生0和1的随机数发生器,然后让你写一个函数,等概率地返回'a'的一个索引(就是'a'在字符串中的位置,比如字符串为aaba,那么a的索引为{0, 1, 3},等概率地返回0、1或者3)。我说这简单啊,首先用[tex]O(n)[/tex]时间做一个扫描,将'a'的索引位置存储在另外一个数组中,假设为b[length_of_all_a],然后用随机数发生器产生一串0、1,转换成十进制,再做x = '0101000...01' mod length_of_all_a的运算,然后返回b[x]就行了。说完了我就知道肯定有问题,这么简单通俗的方法就是一个没有学过计算机的人也能想得出来。果不其然,面试官开始刨根问底了。先是问了我时间和空间复杂度是多少,我说都是[tex]O(n)[/tex],他说复杂度太高,我说要做扫描线性时间复杂度是必须的;然后他说有没有办法减少空间复杂度,毕竟最坏情况是[tex]O(n)[/tex],比如这个超长的字符串全部都是'a',那么存储索引需要的空间就是[tex]O(n)[/tex]的。我一时语塞,要了五分钟考虑时间。最后想出的方法是类似于二分的方法,首先肯定的是在空间复杂度小于[tex]O(n)[/tex]的要求下,我们不可能存储'a'的所有索引了。于是我想的方案就是看随机数发生器,如果是0,我们就去字符串的左半部分查找,否则就去右半部分查找,依次递归,当递归下去的字符串长度小于某个数值的时候,我们就用线性查找的方法,看看这个小串中有没有'a'存在,存在的话,返回索引值,否则向上回溯一层,去另一半查找。总之是很晕的一个山寨方法,而面试官竟然还能听懂,然后他问我怎么样证明这个就是等概率的呢。我说了几个“应该……“,都是凭感觉。再然后他给了我一个串“aaba“,照我的方法,前面个两个'a'被返回的概率有25%,最后一个'a'却有50%,这下我彻底无语了,只能承认自己没辙了。

第三个问题是关于c++的。问我c和c++的static关键字都有什么作用。我就balabalay的说了一通变量的作用域,c++中static class member和static class member functions的东西,可是面试官总是不满意,不停地问“还有吗……“,然后给个提示,我就继续balabala一痛,直到问地我再也无法balabala的时候才放手。

最后好像让我谈了谈自己做的项目,我就把四月份实验室做的哪个项目鼓吹了一通,然后谈了谈acm比赛,我说我只是了解,选拔赛被虐的很惨,对于进入校队基本不抱希望——暑假有时间实习(希望你给我个offer)。临结束的时候又问了一句“你对异步编程“有没有了解,我愣了,说不了解,只听说AJAX是异步Javascript和XML的意思。然后他问我还有没有什么问题,我就傻傻的问“我想知道这次面试中你对我的评价“。评价结果是“思维比较活跃,基础还算不错,但是接触的东西不够广泛“,大概如此。

整个面试过程约一个小时,头脑风暴,增加了自己的信心,也意识到了自己的差距。革命尚未成功,同志仍需努力,暑假,一定要好好把握。

About framebuffer

初次接触framebuffer这 个概念是在去年的9月,那个时候安装archlinux,进入X后觉得console好丑,quark一来,在grub启动的menu.lst上加了一句 vga=792,瞬间console就变成1024*768的分辨率了。先是感到惊喜,再叹quark的神通,三来意识到自己和别人的差距。关于怎样开启framebuffer,grub的配置文件注释里面有很好的说明,这里是我的部分配置menu.lst:

#  FRAMEBUFFER RESOLUTION SETTINGS
#     +-------------------------------------------------+
#          | 640x480    800x600    1024x768   1280x1024
#      ----+--------------------------------------------
#      256 | 0x301=769  0x303=771  0x305=773   0x307=775
#      32K | 0x310=784  0x313=787  0x316=790   0x319=793
#      64K | 0x311=785  0x314=788  0x317=791   0x31A=794
#      16M | 0x312=786  0x315=789  0x318=792   0x31B=795
#     +-------------------------------------------------+
#  for more details and different resolutions see
#  http://wiki.archlinux.org/index.php/GRUB#Framebuffer_Resolution 

# general configuration:
default   0
timeout   3
color light-blue/black light-cyan/blue

# boot sections follow
# each is implicitly numbered from 0 in the order of appearance below
#
# TIP: If you want a 1024x768 framebuffer, add "vga=773" to your kernel line.
#
#-*

# (0) Gentoo Linux 
title  Gentoo Linux
root   (hd0,8)
kernel /vmlinuz-2.6.34-gentoo root=/dev/sda5 rootfstype=ext4 quiet vga=792
initrd /initrd

恰好今天下午 做嵌入式系统的实验,LCD 显示缓冲区体验,要求编程序载入一张图片到LCD显示缓冲区,我回到实验室琢磨琢磨,看到了gentoo开机启动时的那只小企鹅图片,tux,想到开机的时候没有启动X,屏幕上显示出了tux图片,那么可以肯定的是,这张图片一定是通过某种驱动直接“写到显存"里面。而在grub的启动是否采用framebuffer,则和这只tux的”生死“有着直接的联系,因此我敢肯定,framebuffer肯定是这次实验的突破口之一。说干就干,回到实验室查了很多资料,对Framebuffer的相关知识做一次小总结。

FrameBuffer 是出现在 2.2.xx 内核当中的一种驱动程序接口。这种接口将显示设备抽象为帧缓冲区。用户可以将它看成是显示内存的一个映像,将其映射到进程地址空间之后,就可以直接进行读 写操作,而写操作可以立即反应在屏幕上。该驱动程序的设备文件一般是 /dev/fb0、/dev/fb1 等等(具体内容请参见:基于 Linux 和 MiniGUI 的嵌入式系统软件开发指南)。

Framebuffer需要内核的支持,如果没有/dev/fb0类似的文件,恐怕要重新编译内核了。我们可以做两个简单的小实验,看看frambuffer究竟有怎样的魔力:

cat /dev/fb0 > screenshot
# or, dd if=/dev/fb0 of=screenshot
# need super user privilege
clear

仔细观察你的屏幕,然后:

cat screenshot > /dev/fb0
# or, dd if=screenshot of=/dev/fb0
# need super user privilege
clear

是不是有点中病毒的感觉?其实,最简单的理解,/dev/fb0是屏幕显示区域内存的一个抽象,前面先把这部分“内存”保存到screenshot里面,然后再将screenshot里面的”内存“拷贝回去,就实现了屏幕的还原。不过,由于我们使用的GUI和CLI的自动刷新,整个屏幕并不能实现100%的“还原”。

一切皆文件,the great Unix Philosophy,通过读写/dev/fb0,我们可以得到对显示屏100%的控制!进一步的讨论可以参考对FrameBuffer的一夜hack。由此,我的嵌入式实验算是基本达到了第二个要求:写入LCD的缓冲区。载入图片是个复杂问题,毕竟图片的格式五花八门,有损压缩、无损压缩;位图、矢量图等等,就连最简单的bmp位图,想要载入,恐怕也要了解bmp图形文件格式,颇费一番周折。此时我又想起来去年的图形学程序,最后一个project就是载入bmp文件作为纹理贴到一个teapot上面,整个程序下来有600行,不便贴出,给出我当时做的作业,其中载入bmp文件的代码可以作为参考。

至于copy两个文件的c语言程序,我也写了两个,采用的是C语言的标准IO和Linux系统调用IO两种方式:

ANSI IO:

#include <stdio.h>
#include <stdlib.h>

#define BUFSIZE 1024

int copyfile(const char * infile, const char * outfile) 
{
    FILE *fp1, *fp2;
    char buf[BUFSIZE];
    int n;

    if((fp1 = fopen(infile, "r")) == NULL)
    { 
        perror("open file error");
        exit(1);
    }
    
    if((fp2 = fopen(outfile, "w+")) == NULL)
    { 
        perror("open file error");
        exit(1);
    }

    while((n = fread(buf, sizeof(char), BUFSIZE, fp1)) > 0)
    { 
        if((fwrite(buf, sizeof(char), n, fp2)) == -1)
         {
            perror("fail to write");
            exit(1);
        }
    }

    if(n == -1)
    { 
        perror("fail to read");
        exit(1);
    }
    fclose(fp1);
    fclose(fp2);
    return 0;
}

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        printf ("Usage: cp from to\n");
    }
    char * file1 = argv[1];
    char * file2 = argv[2];

    copyfile(file1, file2);
    
    return 0;
}

Linux IO:

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>

#define BUFSIZE 512
#define PERM 0644

int copyfile(const char *name1, const char *name2)
{
    int infile, outfile;

    ssize_t nread;
    char buffer[BUFSIZE];

    if ((infile = open(name1, O_RDONLY)) == -1)
    {
        perror("open file error");
        return (-1);
    }

    if ((outfile = open(name2, O_WRONLY | O_CREAT | O_TRUNC, PERM)) == -1)
    {
        perror("create file error");
        close(infile);
        return (-2);
    }

    while ((nread = read(infile, buffer, BUFSIZE)) > 0 )
    {
        if (write(outfile, buffer, nread) < nread)
        {
            perror("write file error");
            close(infile);
            close(outfile);
            return (-3);
        }
    }

    close(infile);
    close(outfile);

    if (nread == -1)
    {
        return (-4);
    }

    else return (0);
}

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        printf ("Usage: cp from to\n");
    }
    char * file1 = argv[1];
    char * file2 = argv[2];

    copyfile(file1, file2);
    
    return 0;
}

至于两种IO有什么样的区别和联系,我写了一份文档,可以作为入门参考。更进一步的了解已经远远跑题,可以参看jservHackingHelloWorld系列。

OK,本次实验超额完成!120分!^_^


言归正传,事实上,有了framebuffer,Linux的console可以变得无所不能!

先上一张图:

在gentoo下,这种效果需要fbsplash的支持,参照Gentoo Wiki(其实当初装gentoo的时候,自己也折腾过这个,但是一直没有启动起来,不明原因,大概是内核版本的问题,可能同样是内核版本的问题,我的bootchart也无法启动)。还有一个类似的项目叫splashy,不过貌似发展比较缓慢,而且应用也不多。

可能你觉得这就是极限了吧……非也非也!其实有framebuffer,再加上mplayer,我们甚至可以在这样的终端下看视频!!

crazy sand art

mplayer本身是支持多种VIDEO OUTPUT OPTIONS,其中的一种就是framebuffer:

       fbdev (Linux only)
              Uses the kernel framebuffer to play video.
                 <device>
                      Explicitly choose the fbdev device name to use (e.g. /dev/fb0) or the
                      name of the VIDIX subdevice if the device name  starts  with  'vidix'
                      (e.g. 'vidixsis_vid' for the sis driver).

       fbdev2 (Linux only)
              Uses the kernel framebuffer to play video, alternative implementation.
                 <device>
                      Explicitly choose the fbdev device name to use (default: /dev/fb0).

终端截图需要fbgrab的支持。我们在一个终端以super user权限运行:

sudo mplayer -vo fbdev2 videoname

在另外一个终端,同样以超级用户权限运行:

sudo fbgrab filename.png

注意:

  • mplayer -vo选项需要为fbdev2,fbdev不行
  • fbgrab生成的png格式图像需要转换成jpeg格式才能得到满意的效果,否则视频区域一片透明,这可能与图像压缩算法有关(具体我就不知道了)。

差不多了,All about framebuffer。下一次,写一写如何打造高效快捷的终端环境,敬请期待!

所谓焦头烂额

晒下需要过的考试:

  • 计算机组成实验:差一次实验,20号考试
  • 计算机体系实验:差一次实验,26号验收考试
  • 羽毛球:期末考试:
  • J2EE:大程序,在线聊天系统,尚未着手做,刚配好Eclipse,不懂Jsp、Struts……
  • 编译系统设计:尚未着手,写编译器,估计要弃考了……
  • 计算机网络:8个实验报告,7次网上作业(过时了几次了),好像还有个大程序,尚未着手
  • 计算机体系:四篇读书报告,作业,尚未着手
  • 软件工程:搭车完成了大程序答辩,32个ppt,刚看到第5个
  • 算法设计:两次作业一个project,尚未着手做。
  • 嵌入式系统:做了五次实验,还有三周,三个实验,应该不会挂。

所有东西要在一个月之内完成。7月6日考完试。

课外的事情:

  • 写一份简历,准备找实习
  • 还有两场acm新手选拔赛,分别在13号和20号,虽然不抱希望,但是尽量去打打酱油。
  • 六级考试,19号下午去刷刷成绩

想想这半年过的太飘逸了,自顾自,所以导致现在的焦头烂额,也是咎由自取。3月心情不好,家中有事,开学两周基本没去上课。后来系统崩溃了,索性操刀,体验下gentoo,实践了gentoo handbook,水平大增,对linux系统架构有了进一步的了解,了解了什么叫portage, USE, emerge, gentoolkit, 也逐渐体会到gentoo的妙处。中途还帮衬着写了一套社团文档,不过被学校否了,遗憾。到了3月底系统基本配置完毕,却又被导师拉去做windows mobile的项目,整整做了一个月。期间呢,看到了acm集训的选拔标准,心里痒痒,开始着手在zoj上刷题,同时关注88linux版,不小心做了版主,呵。4月底陪朋友,五一去了世博,回来屁股没坐牢,又开始搞数模比赛,整整搞了十天,最后通宵赶出来的论文有36页,期间熟悉了graphviz和Latex进一步用法,初步了解了聚类算法。搞完数模已经是5月15日左右,呆了一两天,补了补一些课程和实验报告,紧接着又开始在zoj集中活力刷题,最后那个星期,周一到周四一直住在实验室。最后还是用了卑鄙无耻的手段,凑够了150道题,得到了ym牛人的一些机会。

暑假,打算找个实习,一个月左右吧。还有个短学期,大概意思就是去给导师打两个星期的工,科研实践。回家学车,估计呆个两星期吧。然后开学回来,找工作吧,在这样跟这些课程死缠烂打,恐怕我要崩溃的。算了算了。该走了。

想想这半年还是看了些书,学了些知识。想想开这个博客也有一年多了。一年前升入大三的时候,已经担心自己要延长毕业了。不过现在,也算是快挺过来了。日光之下,并无新事。一切都会过去,顺其自然即可。重要的是能真正安下心来,坚持下去,做一些事情。人生不是平行的向量,没有可比性。

纠结的j2ee之旅

还没启程,就遇到了诸多意想不到的问题……弄得我焦头烂额,极度郁闷。

web开发本身就是的部署本身就是一件极其纠结复杂的事情,在正是进入web开发前先要搞懂什么叫静态网页、动态网页,什么叫服务器、客户端,什么叫tcp/ip,什么叫html/css,什么叫做动态语言等等;而要进行j2ee的web开发,新概念的爆炸简直是一场急风暴雨,扑面而来,譬如jsp、javabeans、struts、hibernate、spring、ejb、设计模式、MVC等等,令人目不暇接,说实话这写概念到今天我也只是略懂皮毛,因此寻求一款好用的IDE协助开发成了当务之急。等到真正熟悉了整个开发流程和原理,再尝试着转回CLI,寻求一种full-control的感觉。

想进行Java Web开发,第一个前提是有Java,第二个前提是有Web。Gentoo上的Java还是好搞定的,一条命令几乎什么都设置好了,也不用像windows那样去设置PATH环境变量。但是令人比较混乱的是java的选择问题。Gentoo上的jdk至少有5、6种,什么ibm的、apple的、sun的等等,还有什么openjdk——貌似是sun-jdk的开源版本,icedtea(A harness to build the OpenJDK using Free Software build tools and dependencies),GNU Classpath。默认安装的是icedtea6-bin。反正搞到最后,命令行下敲一个java和javac,能用了,因此关于openjdk和sunjdk之间到底是什么关系,我也就没有再深究了。

Java好了,接下来就是开发环境的选择了。记得去年的java程序设计,我单用emacs就搞定了1500行的java校车查询系统,因此emacs+jde+ecb应该也能胜任。但是今年的J2EE Project更侧重web和database,这方面我不熟,因此就想暂时偷偷懒,找个IDE暂时搪塞一下。

关于Java开发的IDE,除了已经“廉颇老矣”的JBuilder,恐怕只剩下EclipseNetbeans了。早先安装过这两个大名鼎鼎的IDE,觉得还是Eclipse更美观一点,因此这次也就首选Eclipse进行安装。安装过程倒也顺利,只是众所周知,Eclipse和Emacs一样是一个平台,需要插件的协助才可以“建功立业”。习惯了linux自动化的包管理系统后,自然也希望Eclipse的插件管理也有类似的功能:自动下载,自动配置,自动判断依赖。可是我几乎在网上找了一天,也没有找到合适的网址,作为Eclipse插件的“源”,自然是及其郁闷,索性放弃,去做别的事情。

后来一次做嵌入式的实验,闲来无聊,就下了windows版的eclipse安装在实验室的电脑上,然后在这个版本上的eclipse找到了比较合适的更新网址(泪流满面,真不容易):

  • EPP Packages Repository http://download.eclipse.org/technology/epp/packages/galileo
  • Galileo http://download.eclipse.org/releases/galileo
  • Mylyn for Eclipse 3.4 and 3.5 http://download.eclipse.org/tools/mylyn/update/e3.4/
  • The Eclipse Project Updates http://download.eclipse.org/eclipse/updates/3.5
  • The Eclipse Web Tools Platform (WTP) Project update site http://download.eclipse.org/webtools/updates

这样总算能安装一些常规插件了(什么?你问我怎么安装?呃,这个问题还是先问问百度先生和google小姐吧。)我安装了Eclipse CDTEclipse WTP,还有一些看似像但不知道能不能用的上的插件。

老师用的是MyEclipse,对于MyEclipse,我的理解就是一个插件的集合,针对Java Web开发做了整合优化。我也想图省事,就去校内的神网搜索,只有MyEclipse 7.0 for linux版本,装之……无法启动……直接sudo rm -rf /where/is/myeclipse/……我又想到最新出的MyEclipse 8.5版会不会好一点,结果是,MyEclipse的官网说”你们中国盗版太严重了“,因此封了所有来自中国的ip,所以也就无法访问了,彻底无语了……

Eclipse安装完毕,简单Hello World也能跑。好啦,开始配置Web和Database。

涉及到的Web服务器主要有两个,ApacheTomcat。这两者是什么关系,有没有相互的依赖性,又是一头雾水。貌似Apache主要解析静态网页,配上php模块可以解析动态php网页,而Tomcat则主要解析ServletJsp。具体依赖性我就不知道了。不过Tomcat是Apache的子项目倒是真的。Apache的配置比较简单,参见Gentoo Wiki,而Tomcat的配置又出了很大的问题。Gentoo Docs上的Tomcat Guide有这么一段:

Standard Tomcat Layout

The root directory of a typical Tomcat binary distribution is laid out as illustrated in the following listing.

Code Listing 2.1: Standard Tomcat Root Directory Layout

/opt/tomcat-x.y/bin
/opt/tomcat-x.y/common
/opt/tomcat-x.y/conf
/opt/tomcat-x.y/logs
/opt/tomcat-x.y/server
/opt/tomcat-x.y/shared
/opt/tomcat-x.y/temp
/opt/tomcat-x.y/webapps
/opt/tomcat-x.y/work
        

Note: Substitute either 5, or 5.5 for x.y

gentoo Tomcat Layout

To comply with FHS and Gentoo standards, Tomcat has been dissected and installed into the following locations.

Code Listing 2.2: Gentoo Tomcat Layout

/usr/share/tomcat-x.y/bin
/usr/share/tomcat-x.y/common
/etc/tomcat-x.y
/var/log/tomcat-x.y/logs
/usr/share/tomcat-x.y/server
/var/lib/tomcat-x.y/shared
/var/tmp/tomcat-x.y
/var/lib/tomcat-x.y/webapps
/var/run/tomcat-x.y

这里面又涉及到一个FHS(Filesystem Hirarchy Standard)的概念。简单的说,tomcat的“正常”安装(在windows平台上)呢,其所有的安装文件都应该在同一个目录下,但是Linux(Gentoo)呢,则有自己的标准(就是FHS),比如临时文件放/tmp和/var,配置文件放/etc里,因此gentoo就把tomcat这个包拆了放到不同的目录里面,这样和自己的哲学比较统一,也确实比较便于管理,比如gentoo环境下开机自动启动apache和tomcat,只需要:

sudo rc-update add apache2 default
sudo rc-update add tomcat-6 default

事实上重启后apache和tomcat服务都已经启动,在浏览器地址栏输入http://localhost/就会出现apache的经典宣传口号“It works!",但是输入http://localhost:8080,浏览器却显示一片空白,再次输入http://localhost:8080/manager/html时,跳出一个对话框,询问manager的用户名和密码(这个密码需要自己配置),正确配置了用户名和密码后重启tomcat输入manager/html,是出现了一个界面,但是功能残缺不全,很多超链接指向html但是实际目录中的文件确实xml格式。而且Eclipse的tomcat插件要求tomcat的安装必须在同一个目录下。我曾想着在/opt/tomcat做几个ln -s的软链接,但终究失败。搜索良久,我找到了这片文章,里面描述的的窘境和我的情况一样。

没办法了,只能去官网下了tarball,自己解压手动安装到/opt/tomcat目录中。然后每次开机手动启动tomcat,这下Eclipse的插件配置也好了……此时的我泪流满面……然后呢,参考ibm developerworks上的文章,兴冲冲地在Eclipse中建立Dynamic Web Project,写了一个"hello, jsp",然后启动tomcat,又出现了tomcat无法启动的问题:

eclipse tomcat

然后我就无语掉了……继续泪流满面……

看来,偷懒的方法不成,还是得回到原始生活时代,开始上网搜一些emacs开发j2ee的东西。用脚趾想也能想得到,用emacs的少,用emacs开发java的少,用emacs开发j2ee的就更少了,因此资料也是出奇的少,相关插件也不完善。拿最简单的jsp来说,我觉得怎么也应该有一个比较顺手的jsp-mode的插件吧,可是结果令人失望……分别尝试了mmm-mode,multi-mode,jsp-mode,nxhtml-mode,可是无一如意,要么是bug无法启动,要么是用了一段时间后就bug,无法正确缩进(nxhtml)等等,于是这条路也走不通了。

于是就剩下最后一个备胎了,netbeans。老实说我不太喜欢netbeans(我觉得界面和字体照eclipse差远了,java swing做出来的东西貌似没几个特别好看的)。emerge一下,提示有几十个包300M的东西要下载,好大的家伙,忍了。然后呢,开始的几十个包安装还是很顺利的。只是到了jnlp这个包,出现了以前没有遇到的问题:

>>> Emerging (1 of 3) dev-java/jnlp-bin-1.2-r1

!!! dev-java/jnlp-bin-1.2-r1 has fetch restriction turned on.
!!! This probably means that this ebuild's files must be downloaded
!!! manually.  See the comments in the ebuild for more information.

 * Please download javaws-1_2-dev.zip and place it in /usr/portage/distfiles
 * https://cds.sun.com/is-bin/INTERSHOP.enfinity/WFS/CDS-CDS_Developer-Site/en_US/-/USD/ViewProductDetail-Start?ProductRef=7026-jaws_dev_pack-1.2-oth-JPR@CDS-CDS_Developer
 * Fetch failed for 'dev-java/jnlp-bin-1.2-r1', Log file:
 *  '/var/tmp/portage/dev-java/jnlp-bin-1.2-r1/temp/build.log'

>>> Failed to emerge dev-java/jnlp-bin-1.2-r1, Log file:

>>>  '/var/tmp/portage/dev-java/jnlp-bin-1.2-r1/temp/build.log'

 * Messages for package dev-java/jnlp-bin-1.2-r1:

 * Fetch failed for 'dev-java/jnlp-bin-1.2-r1', Log file:
 *  '/var/tmp/portage/dev-java/jnlp-bin-1.2-r1/temp/build.log'

google了一下,大概意思是由于license问题,需要到sun的网站上去下载,需要”同意某个许可“,然后给出一个下载链接,就是上面的log中给的那个长串,可是令我极其郁闷的是这个链接怎么也打不开,用wget -c也下载不下来,最后我怀疑是GFW的问题。shit,真是不能忍了,本来不想折腾的。把人逼到绝境。于是我就想起了前不久看到的一个west-chamber计划,好在linuxsir上面还有相关的帖子教程,加了gentoo-china的overlay,可是用eix搜索却怎么也搜不到这个ebuild,奇了怪了,又搜寻了好久,原来是layman升级到1.3后overlay portage的位置改变了,找到了sabayon forums上的帖子,解决了layman的问题,这写总算可以emerge west-chamber了。

编译的过程出了问题,原来是内核配置的问题,又照着linuxsir上的帖子改了.config文件,重新编译了内核,现在还没有重启,不知道能否成功编译west-chamber,翻越GFW。

“待月西厢下,迎风户半开,隔墙花影动,疑是玉人来。”




Host by is-Programmer.com | Power by Chito 1.3.3 beta | © 2007 LinuxGem | Design by Matthew "Agent Spork" McGee