<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    海闊天空

    I'm on my way!
    隨筆 - 17, 文章 - 69, 評論 - 21, 引用 - 0
    數據加載中……

    2009年7月27日

    經典的Linux Socket 編程 示例代碼 (下)


    摘自:http://fanqiang.chinaunix.net/a4/b7/20010810/1200001101.html


    在例程main()函數快要結束時,我們看到,在服務器接受了客戶機的連接請求后,將為其創建子進程,并在子進程中執行代理服務程序do_proxy()。
    -----------------------------------------------------------------/****************************************************************
    function:    do_proxy
    description:  does the actual work of virtually connecting a client to the telnet service on the          isolated host.
    arguments:   usersockfd socket to which the client is connected. return value: none.
    calls:     none.
    globals:     reads hostaddr.
    ****************************************************************/
    void do_proxy (usersockfd)
    int usersockfd;
    {
    int isosockfd;
    fd_set rdfdset;
    int connstat;
    int iolen;
    char buf[2048];
    /* open a socket to connect to the isolated host */
    if ((isosockfd = socket(AF_INET,SOCK_STREAM,0)) < 0)
    errorout("failed to create socket to host");
    /* attempt a connection */
    connstat = connect(isosockfd,(struct sockaddr *) &hostaddr, sizeof(hostaddr));
    switch (connstat) {
    case 0:
    break;
    case ETIMEDOUT:
    case ECONNREFUSED:
    case ENETUNREACH:
    strcpy(buf,sys_myerrlist[errno]);
    strcat(buf,"\r\n");
    write(usersockfd,buf,strlen(buf));
    close(usersockfd);
    exit(1);
    /* die peacefully if we can't establish a connection */
    break;
    default:
    errorout("failed to connect to host");
    }
    /* now we're connected, serve fall into the data echo loop */
    while (1) {
    /* Select for readability on either of our two sockets */
    FD_ZERO(&rdfdset);
    FD_SET(usersockfd,&rdfdset);
    FD_SET(isosockfd,&rdfdset);
    if (select(FD_SETSIZE,&rdfdset,NULL,NULL,NULL) < 0)
    errorout("select failed");
    /* is the client sending data? */
    if (FD_ISSET(usersockfd,&rdfdset)) {
    if ((iolen = read(usersockfd,buf,sizeof(buf))) <= 0)
    break; /* zero length means the client disconnected */
    rite(isosockfd,buf,iolen);
    /* copy to host -- blocking semantics */
    }
    /* is the host sending data? */
    if (FD_ISSET(isosockfd,&rdfdset)) {
    f ((iolen = read(isosockfd,buf,sizeof(buf))) <= 0)
    break; /* zero length means the host disconnected */
    rite(usersockfd,buf,iolen);
    /* copy to client -- blocking semantics */
    }
    }
    /* we're done with the sockets */
    close(isosockfd);
    lose(usersockfd);
    }
    -----------------------------------------------------------------
    在 我們這段代理服務器例程中,真正連接用戶主機和遠端主機的一段操作,就是由這個do_proxy()函數來完成的。回想一下我們一開始對這段 proxy程序用法的介紹。先將我們的proxy與遠端主機綁定,然后用戶通過proxy的綁定端口與遠端主機建立連接。而在main()函數中,我們的 proxy由一段服務器程序與用戶主機建立了連接,而在這個do_proxy()函數中,proxy將與遠端主機的相應服務端口(由用戶在命令行參數中指 定)建立連接,并負責傳遞用戶主機和遠端主機之間交換的數據。
    由于要和遠端主機建立連接,所以我們看到do_proxy()函數的前半部分實際上相當于一段標準的客戶機程序。首先創建一個新的套接字描述符 isosockfd,然后調用函數connect()與遠端主機之間建立連接。函數connect()的定義為:
    -----------------------------------------------------------------
    #include <sys/types.h>
    #include <sys/socket.h>
    int connect(int sockfd, struct sockaddr *servaddr, int addrlen);
    -----------------------------------------------------------------
    參數sockfd是調用函數socket()返回的套接字描述符,參數servaddr指向遠程服務器的套接字地址結構,參數addrlen指定這個 套接字地址結構的長度。函數connect()執行成功時返回"0",如果執行失敗則返回"-1",并將全局變量errno設置為相應的錯誤類型。在例程 中的switch()函數調用中對以下三種出錯類型進行了處理: ETIMEDOUT、ECONNREFUSED和ENETUNREACH。這三個出錯類型的意思分別為:ETIMEDOUT代表超時,產生這種情況的原因 有很多,最常見的是服務器忙,無法應答客戶機的連接請求;ECONNREFUSED代表連接拒絕,即服務器端沒有準備好的傾聽套接字,或是沒有對傾聽套接 字的狀態進行監聽;ENETUNREACH表示網絡不可達。
    在本例中,connect()函數的第二個參數servaddr是全局變量hostaddr,其中存儲著函數parse_args()轉換好的命令行 參數。如果連接建立失敗,在例程中就調用我們自定義的函數errorout()輸出信息"failed to connect to host"。errorout()函數的定義為:
    -----------------------------------------------------------------
    /****************************************************************
    function:  errorout
    description: displays an error message on the console and kills the current process.
    arguments:  msg -- message to be displayed.
    return value: none -- does not return.
    calls:    none.
    globals:   none.
    ****************************************************************/
    void errorout (msg)
    char *msg;
    {
    FILE *console;
    console = fopen("/dev/console","a");
    fprintf(console,"proxyd: %s\r\n",msg);
    fclose(console);
    exit(1);
    }
    -----------------------------------------------------------------
    do_proxy()函數的后半部分是通過proxy建立用戶主機與遠端主機之間的連接。我們既有proxy與用戶主機連接的套接字 (do_proxy()函數的參數usersockfd),又有proxy與遠端主機連接的套接字isosockfd,那么最簡單直接的通信建立方式就是 從一個套接字讀,然后直接寫到另一個套接字去。如:
    -----------------------------------------------------------------
    int n;
    char buf[2048];
    while((n=read(usersockfd, buf, sizeof(buf))>0)
    if(write(isosockfd, buf, n)!=n)
    err_sys("write wrror\n");
    -----------------------------------------------------------------
    這種形式的阻塞I/O在單向數據傳遞的時候是非常有效的,但是在我們的proxy操作中是要求用戶主機和遠端主機雙向通信的,這樣就要求我們對兩個套 接字描述符既能夠讀由能夠寫。如果還是采用這種方式的阻塞I/O的話,很有可能長時間阻塞在一個描述符上。因此例程在處理這個問題的時候調用了 select()函數,這個函數允許我們執行I/O多路轉接。其具體含義就是select()函數可以構造一個表,在這個表中包含了我們所有要用到的文件 描述符。然后我們可以調用一個函數,這個函數可以檢測這些文件描述符的狀態,當某個(我們指定的)文件描述符準備好進行I/O操作時,此函數就返回,告知 進程哪個文件描述符已經可以執行I/O操作了。這樣就避免了長時間的阻塞。
    還有一個函數poll()可以實現I/O多路轉接,由于在例程中調用的是select(),我們就只對select()進行一下比較詳細的介紹。select()系列函數的詳細描述為:
    -----------------------------------------------------------------
    #include <sys/time.h>
    #include <sys/types.h>
    #include <unistd.h>
    int select(int n, fd_set *readfds, fd_set *writefds, fd_est *exceptfds, struct timeval *timeout);
    FD_CLR(int fd, fd_set *set);
    FD_ISSET(int fd, fd_set *set);
    FD_SET(int fd, fd_set *set);
    FD_ZERO(fd_set *set);
    -----------------------------------------------------------------
    select()函數將創建一個我們所關心的文件描述符表,它的參數將在內核中為這些文件描述符設置我們所關心的條件,例如是否是可讀、是否可寫以及 是否異常,而且在參數中還可以設置我們希望等待的最大時間。在select()成功執行時,它將返回目前已經準備好的描述符數量,同時內核可以告訴我們各 個描述符的狀態信息。如果超時,則返回"0",如果出錯,則函數返回"-1",并同時設置errno為相應的值。
    select()的最后一個參數timeout將設置等待時間。其中結構timeval是在文件<bits/time.h>中定義的。
    -----------------------------------------------------------------
    struct timeval
    {
    __time_t tv_sec; /* Seconds */
    __time_t tv_usec; /* Microseconds */
    };
    -----------------------------------------------------------------
    參數timeout的設置有三種情況。象例程中這樣timeout==NULL時,這表示用戶希望永遠等待,直到我們指定的文件描述符中的一個已準備 好,或者是捕捉到一個信號。如果是由于捕捉到信號而中斷了這個無限期的等待過程的話,select()將返回"-1",同時設置errno的值為 EINTR。
    如果timeout->tv_sec==0&&timeout->tv_usec==0,那么這表示完全不等待。 Select()測試了所有指定文件描述符后立即返回。這是得到多個描述符狀態而不阻塞select()函數的輪詢方法。
    如果timeout->tv_sec!=0||timeout->tv_usec!=0,那么這兩個參數的值即為我們希望函數等待的時 間。其中tv_sec設置時間單位為秒,tv_usec設置時間單位為微秒。如果在超時的時候,在我們指定的所有文件描述符里面仍然沒有任何一個準備好的 話,則select()將返回"0"。
    中間三個參數的數據類型是fd_set,它的意思是文件描述符集,而readfds, writefds和exceptfds則分別是指向文件描述符集的指針,他們分別描述了我們所關心的可讀、可寫以及狀態異常的各個文件描述符。之所以我們 稱select()可以創建一個文件描述符"表",那個所謂的表就是由這三個參數指向的數據結構組成的。其具體結構如圖1所示。其中在每個set_fd數 據類型中都為我們關心的所有文件描述符保留了一位。所以在監測文件描述符狀態的時候,就在這些set_fd數據結構中查詢相關的位。
    第一個參數n用來說明到底需要遍歷多少個描述符位。n的值一般是這樣設置的,從我們關心的所有文件描述符中選出最大值再加1。例如我們設置的所有文件 描述符中最大的為6,那么將n設置為7,則系統在檢測描述符狀態的時候,就只用遍歷前7位(fd0~fd6)的狀態。不過如果不想這樣麻煩的話,我們可以 象例程中那樣將n的值直接設置為FD_SETSIZE。這是系統中設定的最大文件描述符個數,不同的系統這個值也不相同,一般是256或是1024。這樣 在檢測描述符狀態的時候,函數將遍歷所有的描述符位。
    在調用select()函數實現多路I/O轉接時,首先我們要聲明一個新的文件描述符集,就象例程中這樣:
    fd_set rdfdset;
    然后調用FD_ZERO()清空此文件描述符集的所有位,以免下面檢測描述符位的時候返回錯誤結果:
    FD_ZERO(&rdfdset);
    然后調用FD_SET()在文件描述符集中設置我們關心的位。在本例中,我們關心的就是分別與用戶主機和遠端主機連接的兩個套接字描述符,所以執行這樣的語句:
    FD_SET(usersockfd,&rdfdset);
    FD_SET(isosockfd,&rdfdset);
    然后調用select()返回描述符狀態,此時描述符狀態被存儲進描述符集,也就是set_fd數據結構中。在圖1中我們看到所有的描述符位狀態都是 "0",在select()返回后,例如fd0可讀,則在readfds描述符集中fd0對應的位上將狀態標志設置為"1",如果fd1可寫,則 writefds描述符集中fd1對應的位上將狀態標志設置為"1",狀態異常的情況也也與此相同。在本例中,我們只關心兩個套接字描述符是否可寫,因此 執行這樣的select()函數:
    select(FD_SETSIZE,&rdfdset,NULL,NULL,NULL)
    那么在select()返回后怎樣檢測set_fd數據結構中描述符位的狀態呢?這就要調用函數FD_ISSET(),如果對應文件描述符的狀態為"已準備好"(即描述符位為"1"),則FD_ISSET()返回"1",否則返回"0"。
    -----------------------------------------------------------------
    if (FD_ISSET(usersockfd,&rdfdset)) {
    if ((iolen = read(usersockfd,buf,sizeof(buf))) <= 0)
    break; /* zero length means the host disconnected */
    write(isosockfd,buf,iolen);
    -----------------------------------------------------------------
    這一段代碼就實現從套接字usersockfd(用戶主機)到套接字isosockfd(遠端主機)的無阻塞傳輸。而下一段代碼實現反方向的無阻塞傳輸:
    -----------------------------------------------------------------
    if (FD_ISSET(isosockfd,&rdfdset)) {
    if ((iolen = read(isosockfd,buf,sizeof(buf))) <= 0)
    break; /* zero length means the host disconnected */
    write(usersockfd,buf,iolen);
    -----------------------------------------------------------------
    這樣就通過proxy實現了用戶主機與遠端主機之間的通信。
    對這段proxy代碼我只是寫了一些自己的理解,大多數是一些函數的用法,這些都是linux網絡編程中一些最基礎的知識,如果有不對的地方,還請各位大蝦批評指正。





    posted @ 2009-11-17 21:14 石頭@ 閱讀(754) | 評論 (0)編輯 收藏

    經典的Linux Socket 編程 示例代碼 (上)

    http://fanqiang.chinaunix.net/a4/b7/20010810/1200001101.html


    Linux是一個可靠性非常高的操作系統,但是所有用過Linux的朋友都會感 覺到, Linux和Windows這樣的"傻瓜"操作系統(這里絲毫沒有貶低Windows的意思,相反這應該是Windows的優點)相比,后者無疑在易操作 性上更勝一籌。但是為什么又有那么多的愛好者鐘情于Linux呢,當然自由是最吸引人的一點,另外Linux強大的功能也是一個非常重要的原因,尤其是 Linux強大的網絡功能更是引人注目。放眼今天的WAP業務、銀行網絡業務和曾經紅透半邊天的電子商務,都越來越倚重基于Linux的解決方案。因此 Linux網絡編程是非常重要的,而且當我們一接觸到Linux網絡編程,我們就會發現這是一件非常有意思的事情,因為以前一些關于網絡通信概念似是而非 的地方,在這一段段代碼面前馬上就豁然開朗了。在剛開始學習編程的時候總是讓人感覺有點理不清頭緒,不過只要多讀幾段代碼,很快我們就能體會到其中的樂趣 了。下面我就從一段Proxy源代碼開始,談談如何進行Linux網絡編程。

       首先聲明,這段源代碼不是我編寫的,讓我們感謝這位名叫Carl Harris的大蝦,是他編寫了這段代碼并將其散播到網上供大家學習討論。這段代碼雖然只是描述了最簡單的proxy操作,但它的確是經典,它不僅清晰地 描述了客戶機/服務器系統的概念,而且幾乎包括了Linux網絡編程的方方面面,非常適合Linux網絡編程的初學者學習。
    這段Proxy程序的用法是這樣的,我們可以使用這個proxy登錄其它主機的服務端口。假如編譯后生成了名為Proxy的可執行文件,那么命令及其參數的描述為:
    ./Proxy <proxy_port> <remote_host> <service_port>
    其中參數proxy_port是指由我們指定的代理服務器端口。參數remote_host是指我們希望連接的遠程主機的主機名,IP地址也同樣有 效。這個主機名在網絡上應該是唯一的,如果您不確定的話,可以在遠程主機上使用uname -n命令查看一下。參數service_port是遠程主機可提供的服務名,也可直接鍵入服務對應的端口號。這個命令的相應操作是將代理服務器的 proxy_port端口綁定到remote_host的service_port端口。然后我們就可以通過代理服務器的proxy_port端口訪問 remote_host了。例如一臺計算機,網絡主機名是legends,IP地址為10.10.8.221,如果在我的計算機上執行:
    [root@lee /root]#./proxy 8000 legends telnet
    那么我們就可以通過下面這條命令訪問legends的telnet端口。
    -----------------------------------------------------------------
    [root@lee /root]#telnet legends 8000
    Trying 10.10.8.221...
    Connected to legends(10.10.8.221).
    Escape character is '^]'

    Red Hat Linux release 6.2(Zoot)
    Kernel 2.2.14-5.0 on an i686
    Login:
    -----------------------------------------------------------------
    上面的綁定操作也可以使用下面的命令:
    [root@lee /root]#./proxy 8000 10.10.8.221 23
    23是telnet服務的標準端口號,其它服務的對應端口號我們可以在/etc/services中查看。

    下面我就從這段代碼出發談談我對Linux網絡編程的一些粗淺的認識,不對的地方還請各位大蝦多多批評指正。

    ◆main()函數
    -----------------------------------------------------------------
    #include <stdio.h>
    #include <ctype.h>
    #include <errno.h>
    #include <signal.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <sys/file.h>
    #include <sys/ioctl.h>
    #include <sys/wait.h>
    #include <sys/types.h>
    #include <netdb.h>
    #define TCP_PROTO   "tcp"
    int proxy_port;    /* port to listen for proxy connections on */
    struct sockaddr_in hostaddr;   /* host addr assembled from gethostbyname() */
    extern int errno;   /* defined by libc.a */
    extern char *sys_myerrlist[];
    void parse_args (int argc, char **argv);
    void daemonize (int servfd);
    void do_proxy (int usersockfd);
    void reap_status (void);
    void errorout (char *msg);
    /*This is my modification.
    I'll tell you why we must do this later*/
    typedef void Signal(int);
    /****************************************************************
    function:    main
    description:   Main level driver. After daemonizing the process, a socket is opened to listen for         connections on the proxy port, connections are accepted and children are spawned to         handle each new connection.
    arguments:    argc,argv you know what those are.
    return value:  none.
    calls:      parse_args, do_proxy.
    globals:     reads proxy_port.
    ****************************************************************/
    main (argc,argv)
    int argc;
    char **argv;
    {
    int clilen;
    int childpid;
    int sockfd, newsockfd;
    struct sockaddr_in servaddr, cliaddr;
    parse_args(argc,argv);
    /* prepare an address struct to listen for connections */
    bzero((char *) &servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = proxy_port;
    /* get a socket... */
    if ((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0) {
    fputs("failed to create server socket\r\n",stderr);
    exit(1);
    }
    /* ...and bind our address and port to it */
    if   (bind(sockfd,(struct sockaddr_in *) &servaddr,sizeof(servaddr)) < 0) {
    fputs("faild to bind server socket to specified port\r\n",stderr);
    exit(1);
    }
    /* get ready to accept with at most 5 clients waiting to connect */
    listen(sockfd,5);
    /* turn ourselves into a daemon */
    daemonize(sockfd);
    /* fall into a loop to accept new connections and spawn children */
    while (1) {
    /* accept the next connection */
    clilen = sizeof(cliaddr);
    newsockfd = accept(sockfd, (struct sockaddr_in *) &cliaddr, &clilen);
    if (newsockfd < 0 && errno == EINTR)
    continue;
    /* a signal might interrupt our accept() call */
    else if (newsockfd < 0)
    /* something quite amiss -- kill the server */
    errorout("failed to accept connection");
    /* fork a child to handle this connection */
    if ((childpid = fork()) == 0) {
    close(sockfd);
    do_proxy(newsockfd);
    exit(0);
    }
    /* if fork() failed, the connection is silently dropped -- oops! */
    lose(newsockfd);
    }
    }
    -----------------------------------------------------------------
    上面就是Proxy源代碼的主程序部分,也許您在網上也曾經看到過這段代碼,不過細心的您會發現在上面這段代碼中我修改了兩個地方,都是在預編譯部分。一個地方是在定義外部字符型指針數組時,我將原代碼中的
    extern char *sys_errlist[];
    修改為
    extern char *sys_myerrlist[];原因是在我的Linux環境下頭文件"stdio.h"已經對sys_errlist[]進行了如下定義:
    extern __const char *__const sys_errlist[];
    也許Carl Harris在94年編寫這段代碼時系統還沒有定義sys_errlist[],不過現在我們不修改一下的話,編譯時系統就會告訴我們sys_errlist發生了定義沖突。
    另外我添加了一個函數類型定義:
    typedef void Sigfunc(int);
    具體原因我將在后面向大家解釋。

    套接字和套接字地址結構定義

    這段主程序是一段典型的服務器程序。網絡通訊最重要的就是套接字的使用,在程序的一開始就對套接字描述符sockfd和newsockfd進行了定義。 接下來定義客戶機/服務器的套接字地址結構cliaddr和servaddr,存儲客戶機/服務器的有關通信信息。然后調用parse_args (argc,argv)函數處理命令參數。關于這個parse_args()函數我們待會兒再做介紹。

    創建通信套接字

      下面就是建立一個服務器的詳細過程。服務器程序的第一個操作是創建一個套接字。這是通過調用函數socket()來實現的。socket()函數的具體描述為:
    -----------------------------------------------------------------
    #include <sys/types.h>
    #include <sys/socket.h>
    int socket(int domain, int type, int protocol);
    -----------------------------------------------------------------
    參數domain指定套接字使用的協議族,AF_INET表示使用TCP/IP協議族,AF_UNIX表示使用Unix協議族,AF_ISO表示套接 字使用ISO協議族。type指定套接字類型,一般的面向連接通信類型(如TCP)設置為SOCK_STREAM,當套接字為數據報類型時,type應設 置為SOCK_DGRAM,如果是可以直接訪問IP協議的原始套接字則type應設置為SOCK_RAW。參數protocol一般設置為"0",表示使 用默認協議。當socket()函數成功執行時,返回一個標志這個套接字的描述符,如果出錯則返回"-1",并設置errno為相應的錯誤類型。

    設置服務器套接字地址結構

    在通常情況下,首先要將描述服務器信息的套接字地址結構清零,然后在地址結構中填入相應的內容,準備接受客戶機送來的連接建立請求。這個清零操作可以用 多種字節處理函數來實現,例如bzero()、bcopy()、memset()、memcpy()等,以字母"b"開始的兩個函數是和BSD系統兼容 的,而后面兩個是ANSI C提供的函數。這段代碼中使用的bzero()其描述為:
    void bzero(void *s, int n);
    函數的具體操作是將參數s指定的內存的前n個字節清零。memset()同樣也很常用,其描述為:
    void *memset(void *s, int c, size_t n);
    具體操作是將參數s指定的內存區域的前n個字節設置為參數c的內容。
    下一步就是在已經清零的服務器套接字地址結構中填入相應的內容。Linux系統的套接字是一個通用的網絡編程接口,它應該支持多種網絡通信協議,每一 種協議都使用專門為自己定義的套接字地址結構(例如TCP/IP網絡的套接字地址結構就是struct sockaddr_in)。不過為了保持套接字函數調用參數的一致性,Linux系統還定義了一種通用的套接字地址結構:
    -----------------------------------------------------------------
    <linux/socket.h>
    struct sockaddr
    {
    unsigned short sa_family; /* address type */
    char sa_data[14]; /* protocol address */
    }
    -----------------------------------------------------------------
    其中sa_family意指套接字使用的協議族地址類型,對于我們的TCP/IP網絡,其值應該是AF_INET,sa_data中存儲具體的協議地 址,不同的協議族有不同的地址格式。這個通用的套接字地址結構一般不用做定義具體的實例,但是常用做套接字地址結構的強制類型轉換,如我們經常可以看到這 樣的用法:
    bind(sockfd,(struct sockaddr *) &servaddr,sizeof(servaddr))
    用于TCP/IP協議族的套接字地址結構是sockaddr_in,其定義為:
    -----------------------------------------------------------------
    <linux/in.h>
    struct in_addr
    {
    __u32 s_addr;
    };
    struct sochaddr_in
    {
    short int sin_family;
    unsigned short int sin_port;
    struct in_addr sin_addr;
    /*This part has not been taken into use yet*/
    nsigned char_ _ pad[_ _ SOCK_SIZE__- sizeof(short int) -sizeof(unsigned short int) -       sizeof(struct in_addr)];
    };
    #define sin_zero_ - pad
    -----------------------------------------------------------------
    其中sin_zero成員并未使用,它是為了和通用套接字地址struct sockaddr兼容而特意引入的。在編程時,一般都通過bzero()或是memset()將其置零。其他成員的設置一般是這樣的:
    servaddr.sin_family = AF_INET;
    表示套接字使用TCP/IP協議族。
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    設置服務器套接字的IP地址為特殊值INADDR_ANY,這表示服務器愿意接收來自任何網絡設備接口的客戶機連接。htonl()函數的意思是將主機順序的字節轉換成網絡順序的字節。
    servaddr.sin_port = htons(PORT);
    設置通信端口號,PORT應該是我們已經定義好的。在本例中servaddr.sin_port = proxy_port;這是表示端口號是函數的返回值proxy_port。
    另外需要說明的一點是,在本例中,我們并沒有看到在預編譯部分中包含有<linux/socket.h>和< linux/in.h>這兩個頭文件,那是因為這兩個頭文件已經分別被包含在<sys/types.h>和< sys/types.h>中了,而且后面這兩個頭文件是與平臺無關的,所以在網絡通信中一般都使用這兩個頭文件。

    服務器公開地址

      如果服務器要接受客戶機的連接請求,那么它必須先要在整個網絡上公開自己的地址。在設置了服務器的套接字地址結構之后,可以通過調用函數bind()綁定服務器的地址和套接字來完成公開地址的操作。函數bind()的詳細描述為:
    -----------------------------------------------------------------
    #include <sys/types.h>
    #include <sys/socket.h>
    int bind(int sockfd, struct sockaddr *addr, int addrlen);
    -----------------------------------------------------------------
    參數sockfd是我們通過調用socket()創建的套接字描述符。參數addr是本機地址,參數addrlen是套接字地址結構的長度。函數執行成功時返回"0",否則返回"-1",并設置errno變量為EADDRINUAER。
    如果是服務器調用bind()函數,如果設置了套接字的IP地址為某個本地IP地址,那么這表示服務器只接受來自于這個IP地址的特定主機發出的連接 請求。不過一般情況下都是將IP地址設置為INADDR_ANY,以便接受所有網絡設備接口送來的連接請求。
    客戶機一般是不會調用bind()函數的,因為客戶機在連接時不用指定自己的套接字地址端口號,系統會自動為客戶機選擇一個未用端口號,并且用本地 IP地址自動填充客戶機套接字地址結構中的相應項。但是在某些特定的情況下客戶機需要使用特定的端口號,例如Linux中的rlogin命令就要求使用保 留端口號,而系統是不能為客戶機自動分配保留端口號的,這就需要調用bind()來綁定一個保留端口號了。不過在一些特殊的環境下,這樣綁定特定端口號也 會帶來一些負面影響,如在HTTP服務器進入TIME_WAIT狀態后,客戶機如果要求再次與服務器建立連接,則服務器會拒絕這一連接請求。如果客戶機最 后進入TIME_WAIT狀態,則馬上再次執行bind()函數時會返回出錯信息"-1",原因是系統會認為同時有兩次連接綁定同一個端口。

    轉換Listening套接字

    接下來,服務器需要將我們剛才與IP地址和端口號完成綁定的套接字轉換成傾聽listening套接字。只有服務器程序才需要執行這一步操作。我們通過調用函數listen()實現這一操作。listen()的詳細描述為:
    -----------------------------------------------------------------
    #include <sys/socket.h>
    int listen(int sockfd, int backlog);
    -----------------------------------------------------------------
    參數sockfd指定我們要求轉換的套接字描述符,參數backlog設置請求隊列的最大長度。函數listen()主要完成以下操作。
    首先是將套接字轉換成傾聽套接字。因為函數socket()創建的套接字都是主動套接字,所以客戶機可以通過調用函數connect()來使用這樣的 套接字主動和服務器建立連接。而服務器的情況恰恰相反,服務器需要通過套接字接收客戶機的連接請求,這就需要一個"被動"套接字。listen()就可將 一個尚未連接的主動套接字轉換成為這樣的"被動"套接字,也就是傾聽套接字。在執行了listen()函數之后,服務器的TCP就由CLOSED變成 LISTEN狀態了。
    另外listen()可以設置連接請求隊列的最大長度。雖然參數backlog的用法非常簡單,只是一個簡單的整數。但搞清楚請求隊列的含義對理解TCP 協議的通信過程建立非常重要。TCP協議為每個傾聽套接字實際上維護兩個隊列,一個是未完成連接隊列,這個隊列中的成員都是未完成3次握手的連接;另一個 是完成連接隊列,這個隊列中的成員都是雖然已經完成了3次握手,但是還未被服務器調用accept()接收的連接。參數backlog實際上指定的是這個 傾聽套接字完成連接隊列的最大長度。在本例中我們是這樣用的:listen(sockfd,5);表示完成連接隊列的最大長度為5。

    接收連接

    接下來我們在主程序中看到通過名為daemonize()的自定義函數創建一個守護進程,關于這個daemonize()以及守護進程的相關概念,我 們等一會兒再做詳細介紹。然后服務器程序進入一個無條件循環,用于監聽接收客戶機的連接請求。在此過程中如果有客戶機調用connect()請求連接,那 么函數accept()可以從傾聽套接字的完成連接隊列中接受一個連接請求。如果完成連接隊列為空,這個進程就睡眠。accept()的詳細描述為:
    -----------------------------------------------------------------
    #include <sys/socket.h>
    int accept(int sockfd, struct sockaddr *addr, int *addrlen);
    -----------------------------------------------------------------
    參數sockfd是我們轉換成功的傾聽套接字描述符;參數addr是一個指向套接字地址結構的指針,參數addrlen為一個整型指針。當函數成功執 行時,返回3個結果,函數返回一個新的套接字描述符,服務器可以通過這個新的套接字描述符和客戶機進行通信。參數addr所指向的套接字地址結構中將存放 客戶機的相關信息,addrlen指針將描述前述套接字地址結構的長度。在通常情況下服務器對這些信息不是很感興趣,因此我們經常可以看到一些源代碼中將 accept()函數的后兩個參數都設置為NULL。不過在這段proxy源代碼中需要用到有關的客戶機信息,因此我們看到通過執行
    newsockfd = accept(sockfd, (struct sockaddr_in *) &cliaddr, &clilen);
    將客戶機的詳細信息存放在地址結構cliaddr中。而proxy就通過套接字newsockfd與客戶機進行通信。值得注意的是這個返回的套接字描 述符與我們轉換的傾聽套接字是不同的。在一段服務器程序中,可以始終只用一個傾聽套接字來接收多個客戶機的連接請求;而如果我們要和客戶機建立一個實際的 連接的話,對每一個請求我們都需要調用accept()返回一個新的套接字。當服務器處理完畢客戶機的請求后,一定要將相應的套接字關閉;如果整個服務器 程序將要結束,那么一定要將傾聽套接字關閉。
    如果accept()函數執行失敗,則返回"-1",如果accept()函數阻塞等待客戶機調用connect()建立連接,進程在此時恰好捕捉到 信號,那么函數在返回"-1"的同時將變量errno的值設置為EINTR。這和accept()函數執行失敗是有區別的。因此我們在代碼中可以看到這樣 的語句:
    -----------------------------------------------------------------
    if (newsockfd < 0 && errno == EINTR)
    continue;
    /* a signal might interrupt our accept() call */
    else if (newsockfd < 0)
    /* something quite amiss -- kill the server */
    errorout("failed to accept connection");
    -----------------------------------------------------------------
    可以看出程序在處理這兩種情況時操作是完全不同的,同樣是accept()返回"-1",如果有errno == EINTR,那么系統將再次調用accept()接受連接請求,否則服務器進程將直接結束。

    posted @ 2009-11-17 21:13 石頭@ 閱讀(2379) | 評論 (0)編輯 收藏

    Unix發展史

    先前的一個理想
    UNIX系統自 1969 年 Ken ThompsonKen Thompson 與 Dennis RitchieDennis Ritchie 在美國貝爾電話實驗室(Bell Telephone Laboratories )發展出雛形至今,已歷經近 30 來年。而 "UNIX" 這個字典上查不到其原意的怪字,其實是戲謔 MULTICS(MULTiplexed Information and Computing System)操作系統的大而無當所產生的諧音字。
    在 1957 年 10 月,前蘇聯發射了第一枚人造衛星,此舉讓當時的美國總統艾森豪威爾決定投下巨額的經費用以支持及發展科學,美國高等研究計劃署 (ARPA,Advanced Research Projects Agency )便是在這個時空下設立了,該單位負責推動系統發展等相關計劃,成為當時美國電子計算器發展的重要推手。
    1960年代是大型計算機的發展年代,當時的麻省理工學院因最先實現了兼容分時系統(CTSS, Compatible Time-Sharing System),在電子計算器領域享有相當崇高的地位。
    1963年,麻省理工的里克萊德(J. C. R. Licklider,1915~1990 )
    推動了 MAC計劃,MAC 以 IBM的大型計算機做為主體,連接了將近 160臺終端機,這些終端機就四散在學區以及教職員的家中,可以讓 30 位使用者同時共享計算機資源。這項計劃到了 1965 年便不堪負荷,于是麻省理工便決定開發更大型的分時計算機系統。新的計劃便是—— MULTICS. 一個計算機
    史上最為龐大的分時計算機系統,企圖連接 1000 部終端機,支持 300位使用者同時上線的分時計算機系統。她面臨的是,操作系統的分時觀念還在各學術與研究機構探索成形中,計算機硬件亦需重新設計的雙重挑戰。
    當時,麻省理工原本找 IBM來配合這項計劃,但 IBM正忙著應付自己的問題而無意配合MULTICS 計劃。此時,通用電子公司(General Electric Company)
    也就是奇異公司正好在發展自己的大型主機,見機不可失,便極力邀請麻省理工參予她們的 GE 645 大型主機的規格制定。有了奇異熱心主動的計算機硬件配合,麻省理工找上的不能販售計算機卻人才濟濟的貝爾電話實驗室來負責承包軟件工程。于是 乎,MULTICS 的計劃便在 1965 年由麻省理工學院、奇異公司及貝爾電話實驗室這三個成員開始共同發展。
    1969年,MULTICS 計劃在歷經四年的奮戰后,仍舊未達到原先規劃設計的理想,貝爾電話實驗室決定退出計劃。功能未達原始設計理想的 MULTICS還是安裝在奇異公司的 GE 645 大型計算機上供麻省理工使用。奇異公司在該計劃草草結束后不到一年便完全淡出大型計算機市場。日后,MULTICS 計劃被嘲解為Many Unnecessarily Large Table In Core Simultaneously.
    農夫我個人認為, MULTICS計劃誕生在大型計算機將開始鼎沸的 1965 年,夭折于大型計算機最為輝煌的 1969 年。她如果適時在 1960 年代末期成功的話,絕對可以助長當時已經普遍被計算機權威人士視為理想的「計算機公用事業」,至少可以讓大型計算機的發展與資源集中的應用模式就不至于會 在 1970 年代初期就迅速萎縮。因為 MULTICS計劃如果成功,至少能讓當時的大型計算機的應用規模大上 10 倍左右。然而,MULTICS 計劃失敗了。她嚴重地打擊了當時依賴大型計算機主機的計算機公用事業業者在發展上的信心。更由于沒有相似的計劃后繼進行,使得集中式的大型計算機主機沒有 明顯的使用效能提升,而加速催化計算器工業的轉變,以尋找新的道路。另一方面,MULTICS 計劃失敗的經驗亦讓當時參與該計劃的軟件工程師們得到相當寶貴的經驗與正面的影響。
    幾年后,就在 AT&T ,MULTICS 計劃這個不同凡響的失敗換來的一個不同凡響的成功。
    一個戲謔她的名字誕生了…… UNIX.
    Ken_Thompso


    400) {this.resized=true; this.width=400; this.alt='Click here to open new window';}" onmouseover="if(this.resized) this.style.cursor='hand';" onclick="window.open('/upimg/20070420/11M10351425013001.jpg');" border="0">
    Dennis_Ritchie


    400) {this.resized=true; this.width=400; this.alt='Click here to open new window';}" onmouseover="if(this.resized) this.style.cursor='hand';" onclick="window.open('/upimg/20070420/11M103514N021A4.jpg');" border="0">

    一個游戲的開始
    1969年貝爾實驗室的計算器科學研究中心(Computing Science Research Center )
    成員退出 MULTICS計劃的同時,貝爾實驗室本身其實也沒有一套完善便利的交談式計算器服務環境。在其中不少工程師們也正為了改善程序設計環境努力著, Ken Thompson 、Dennis Ritchie和其同事們在當時草擬一個新的檔案系統架構,這個檔案系統也就是早期的 UNIX 操作系統的檔案系統的前身。當時的 Ken Thompson 忙著使用 Fortran語言將原本在 Multics系統中開發的game叫 "Space Travel" (太空旅游)轉移到 GECOS System 上開發。 當時 GECOS System大型計算機的CPU Time相當昂貴(一秒要 75 塊美金),同時控制 "spaceship"(宇宙飛船) 的效果不甚理想,于是 Ken Thompson 不得不尋找替代的開發環境。Thompson看上了一臺很少被人使用的 Digital Equipment Corporation PDP-7 迷你計算機,當時 PDP-7使用的是 Graphic-II 顯示器,具有不錯的圖形處理能力。 Brian kernighan 于是 Ken Thompson 便與 Dennis Ritchie 連手將程序設計轉移到 PDP-7型計算機上。
    Ken Thompson在移轉工作環境的同時為了得到較好的發展環境,便與Dennis Ritchie共同動手設計一套包含 File System、Process Subsystem 及一小組 Utility的操作系統,當時這套系統僅能支持 2個使用者使用。由于貝爾實驗室對于 MULTICS計劃失敗的陰霾還未消散, Brian Kernighan這位仁兄開玩笑地戲稱這套新的操作系統為 UNiplexed Information and Computing System,縮寫為 UNICS,之后大家取諧音便叫她為 "UNIX" ,沒想到這個開玩笑的名字會被人叫到今天。
    初期的自由發展
    事實上該套 "UNIX" 系統在當時僅是私下的被使用,也并沒有得到多大的重視,一直到1971年的一個正式的計劃,UNIX才正式被搬上臺面。
    PDP-11/201970 年,當時貝爾實驗室的專利部門(Patent department )缺乏一套文書處理系統,為了設計開發的需要,于是買了一臺 PDP-11 計算機。當時 PDP-11 計算機的交機過程并不順利,處理器先到,硬盤則多等了好幾個月。
    當 PDP-11 一切準備妥當后,他們便將 UNIX 移植到擁有 512K bytes 硬盤的PDP-11/20 型計算機上,并在此系統之下開發了一套文書處理工具。而這套工具便是后來 nroff / troff的前身。那時的 UNIX 提供 16K bytes給系統、8K bytes給使用程序,檔案最大的極限是 64K bytes. 而此套含有文書處理工具的系統,也正式獲得貝爾實驗室的專利部門采用,系統名稱并被編為 "First Edition". 在 UNIX 移植成功后 Thompson 用 B語言為它添加了 Fortran Compiler,但因為 B語言屬于一種解譯語言(interpretive language ),執行成效并不是很好,于是 Ritchie又將它—— Compiler 發展成可產生機器碼、允許定義數據形態及結構,Ritchie 稱它為 C語言。1973年并以 C語言改寫全部UNIX原始程序,UNIX于是首度出現正式版本——V5(第五版)。
    此時的 UNIX 慢慢地在貝爾實驗室內部蔓延開來,裝機數也變成了 25 部之多。
    由于當時的貝爾實驗室實際上是掌控在美國電信電話公司(AT&T)及其子公司西方電器公司的手上,實驗室主要是負責研究改進西方電器公司制造的和 美國電信電話公司在貝爾系統中使用的電信設備。同時根據軍方合同,從事與國防有關的研究與改進的工作。而 AT&T 本身由于有反托拉斯法的限制并不能從事于任何有關計算機方面的銷售,所以 AT&T 的主管階層們對于當時 UNIX 的發展并沒有太多的支持,因而當時貝爾實驗室內部對于 UNIX 的發展并不是相當在意也無意于將之推廣。不過為了應付實驗室內各部門日益增加的 UNIX 使用者與相關技術支持需求,還是成立了 UNIX ystem Group (簡稱 USG)。但該組織也僅只是提供技術上的支持,并未賦予繼續發展的任務。所以當時的 UNIX 發展,全靠AT&T的工程師們的努力。這段期間 UNIX 的發展完全沒有組織及系統性可言,而玩家盡是一些工程師們,于是乎種下了 UNIX 日后較難以被一般人所接受的命運。


    400) {this.resized=true; this.width=400; this.alt='Click here to open new window';}" onmouseover="if(this.resized) this.style.cursor='hand';" onclick="window.open('/upimg/20070420/11M10351522035M3.jpg');" border="0">



    400) {this.resized=true; this.width=400; this.alt='Click here to open new window';}" onmouseover="if(this.resized) this.style.cursor='hand';" onclick="window.open('/upimg/20070420/11M10351522035M3.jpg');" border="0">

    走出貝爾實驗室
    1974年 Thompson 與 Ritchie共同在 Communications of the ACM發表了一篇 UNIX 論文 "UNIX Time-Sharing System" 得到相當大的回響。 1975 年 UNIX 發表第六版(V6)﹐其提供的強大功能更勝過當時昂貴大計算機的操作系統,其最大特點是以高級語言寫成,僅需要做少部份程序的修改便可移植到不同的計算機 平臺上。 UNIX V6版本并附有完整的程序原始碼在 1976 年正式從貝爾實驗室內部傳播到各大學及研究機構,UC Berkeley 也就是依據這個版本開始研究并加以發展,并在 1977 年發表 1 BSD(1st Berkeley Software Distribution)版本的 UNIX OS,其后續的發展更為 UNIX OS貢獻良多且影響深遠,此點稍后再為你說明。
    同年 UNIX 因它提供良好程序發展環境、網絡傳輸服務與及時服務(Real-Time Services),而廣得各電話公司采用。Interactive System Corporation更因 Value Added Reseller (VAR )運用 UNIX 來強化辦公室自動化環境,成為第一家應用UNIX操作系統的公司。此年UNIX亦被修改并第一次裝到 Interdata 8/32 型計算機上。這也是 UNIX 操作系統首次安裝在非 PDP型的計算機上。自此 UNIX 系統開始被移植改裝到各型微處理機及新計算機上
    一個穩定的基石
    1978年 UNIX 發表對今日影響最重大的 UNIX 第七版(UNIX Time-Sharing System,Seventh Edition )也就是 V7.此版本包含 Fortran 77 compiler、Shell (只有Bourne Shell)、文件處理工具(nroff/troff 、roff、 MS mocro等)、UNIX-to-UNIX-file-Copy(用來支持兩臺 UNIX 機器間的檔案傳輸)、數據處理工具(AWK 、SED 等強悍的工具)、除錯工具(ADB )、程序發展工具(MAKE)、Lexical analyzer generator(LEX 、YACC等)、簡單的繪圖工具、并支持 C語言及 LINT verifier,主要執行于 PDP-11 及Interdata 8/32型計算機上。在當時那個年代來說其系統的架構與功能已經是相當的完備的了。Bourne Shell的原作者稱她為 "improvement over all preceding and following Unices" ,在今日也有人稱這個版本是 "last true Unix".由此可見 V7 在 UNIX 發展里程上的扮演了相當重要的盤石角色。
    在當時 DEC公司推出了一款 32-bit supermini 主機—— VAX,搭配的 VAX的操作系統叫做 VMS. 這款迷你級計算機的硬件無可挑剔〈直到今日她的穩定度仍是被諸多老一輩的系統管理者所贊許的〉,但 DEC對 VMS操作系統的支持性卻讓貝爾實驗室的工程師們寧愿使用UNIX OS . 而這項工作則是由 John Reiser和Tom London所共同完成。他們以 V7 為基礎轉移 UNIX OS到 VAX計算機上使用。
    這個版本被稱為 UNIX V32.同時為了轉移的方便性,他們把 32-bit 的 VAX當成是大一點的 PDP-11 (因為 DEC 的 PDF-11 型計算機是 16-bit ),同時為了執行的效率,V32 放棄使用 VAX硬件提供的一項 paging 功能(DEC 的 VMS OS 有支持 paging 功能,也由于 V32舍棄這項功能,所以 V32沒有虛擬內存的功能)。
    即使是如此,V32 支持的地址已高達 4Gb. 就這樣沒有支持paging功能的 V32開始被廣泛的安裝在 VAX的機器上運作。
    DEC 則是在 1984 年左右推出來自己的 UNIX OS,叫做 ULTRIX.


    400) {this.resized=true; this.width=400; this.alt='Click here to open new window';}" onmouseover="if(this.resized) this.style.cursor='hand';" onclick="window.open('/upimg/20070420/11M1035156104cD.jpg');" border="0">
    一個重要的延續及發展—— BSD UNIX
    時間回到 1973 年 11 月, Ken Thompson 和 Dennis Ritchie 在印第安納Purdue大學的一場操作系統原理的座談會。會場上、坐著一位柏克萊大學(U.C. Berkeley )教授,名字叫 Bob Fabry. 當天的 K&R所發表的 UNIX 立刻引發 Bob Fabry的極度興趣。當時的柏克萊還是處在使用大型計算機主機、批次執行程序的階段,并沒有像 UNIX 這樣的交談式作業環境。會后,他便決定將UNIX帶回柏克萊。
    于是柏克萊的計算器科學、數學與統計三個系所合買的一臺 PDP-11/45,準備用來迎接UNIX.1974 年 1月,Bell Labs寄來了一卷 V4 的磁帶,學生 Keith Standiford 便開始進行安裝 V4 的工作。安裝時 Standiford 碰到了問題,便轉向 Bell Labs求援。人在新澤西州的 Thompson 便透過柏克萊這端速度只有300-baud的調制解調器在在線進行偵錯。
    在 UNIX 的發展史上,這是 Bell Labs與柏克萊的第一次接觸。
    完成除錯后,V4便順利地在柏克萊這臺新買的 PDP-11/45計算機上工作了。
    當時這臺是三個系所合買的,計算器科學好不容易裝上了 UNIX ,卻碰到數學與統計系所要使用 DEC's RSTS system,所以在一陣協調后,UNIX與 DEC's RSTS system以 8:16小時的比例分配,供三個系所輪流使用。一段時日后,具交談式功能的 UNIX 在效能上的表現得到絕多數學生們喜愛,紛紛將自己的計劃轉向UNIX的時段。而一天占了 16 個小時的批處理時段卻乏人問津。
    當時 Eugene Wong與 Michael Stonebraker教授,看上了 UNIX 提供的便利性,便打算將他們的 INGRES 數據庫計劃重原先批處理的計算機環境轉移到UNIX系統上面。在 1974 年,他們為這執行計劃添購了一臺新的 PDP-11/40 計算機,上面安裝了 V5.這個計劃也就是柏克萊的第一個將作業環境轉移到UNIX的案子。
    UNIX作業環境的需求,在柏克萊迅速地成長。為了應付需求,Michael Stonebraker 與Bob Fabry 教授決定再申請購買兩臺 PDP-11/45. 1975年初,DEC 推出 PDP-11/70,價格差不多等于兩臺 PDP-11/45,但功能強過 PDP-11/45 所以他們便決定改購買一臺 PDP-11/70.
    這臺機器引來了 Ken Thompson 、碰上 Bill Joy 以及日后產生了 1BSD.她就宛如是一塊 UNIX 史上的地標,沿襲自 Bell Labs,豎立在柏克萊,承先啟后并開創新局。農夫個人認為,她應該被供在博物館。
    當這臺機器在 1975 年終運達柏克萊時;同一時間,Thompson受邀回母校(柏克萊)當客座教授,科目就是 NIX.Thompson 在校期間與 Jeff Schriebman和 Bob Kridle 一起動手將新版的 V6 安裝在 PDP-11/70.
    Bill Joy1975年,一位密執安州大學的畢業生來到了柏克萊,他的名字就是Bill Joy. 當時 Joy和同學 Chuck Haley (tar 就是他寫的)喜歡一起泡在計算機房里面,Thompson也時常插上一腳。他們成功地改善了 Pascal 的解譯與偵錯的能力,同時還提升了解譯與執行的速度。另外換裝上 ADM-3的屏幕后,他們覺得ed文字編輯指令并不合用;于是根據另外一個相似的 em 指令,發展了自己的覺得滿意的文字編輯工具,也就是指令 ex.
    1976年夏天,Thompson結束了他的休假回到 Bell Labs. 此時的 Joy和Haley 已經開始著手探索 UNIX kernal,甚至還做了一些修改。1977年初,Joy 制作了一卷磁帶,上頭寫著"Berkeley Software Distribution." ,這就是 1BSD. 其中包含新的 Pascal compiler與 ex 編輯器。
    次年,來了幾臺新屏幕—— ADM-3a ,這種屏幕支持光標地址顯示,Joy 在這種屏幕上完成了有人愛不釋手;有人恨之入骨的文字編輯器—— vi.接著不久,Joy 便發現一個問題,老舊的屏幕裝備,還是會被用在其它的計算機上。為了支持上的方便,Joy 針對此現象設計了一個接口,用來管理、支持不同的屏幕裝備。
    這個接口就是現在的 termcap.1978 年中,包含了功能加強的 Pascal 與 vi 及termcap 的 "Second Berkeley Software Distribution ," 也就是 2BSD ,迅速的取代了原先版本。
    1979年,至少有 75 部 PDP-11 的機器上安裝 2BSD 在運作著。自此在 DEC PDP-11 系列上執行的 BSD版本便一直以 2.xBSD 作為識別。
    由于 PDP-11 計算機實在相當長壽,持續到今日農夫我仍然在網絡上發現過關于PDP 計算機的網站。似乎到今日它們仍舊在某些地方默默地工作著。
    2.xBSD最近的一次改版是在 1987 年,使用 4.3 BSD為主架構改寫,版本定為 2.10 BSD.
    在 BSD UNIX 中登場的重要功能當中,有一個直到今日仍然叫人又愛又恨的指令– vi.我接觸過不少學習 UNIX OS的人,大部分的人對 vi 的使用與掌握都不算順手,其中恨死這個指令的也大有人在,前些日子農夫我還看到某個網站公開討論起 vi 是否阻礙了 UNIX 的發展?實在夸張了一點!
    Bill Joy多次公開地說,他要是知道 vi 會如此受" 歡迎" 的話,他寧愿當初沒有寫 vi 這只程序。不過 Bill Joy 也說過,當時他原本還想加入一項 Multiple Windows in vi 的功能,不過當他在寫這部分程序的時候,磁帶機壞了,所以Bill只好在沒有備份的情況下繼續工作,想不到" 屋漏偏逢連夜雨" ,程序寫到一半,他使用的硬盤也跟著掛了。在無可挽救又沒有備份磁帶的情況下,Bill宣告放棄為 vi 增加 Multiple Windows 這項功能。事后 Bill 為前一版的 vi 寫好使用說明后就繼續作其它的事。所以 vi 就長成今天那付德性。農夫我認為這或許是福不是禍!搞不好當初要是連 Multiple Windows 這項功能一起發表的話,上頭的圖可能就是遺照了。
    當時有位 Richard Fateman教授,原先使用一臺 PDP-10 上進行著他的Macsyma 研究計劃。但他需要更大的內存地址來執行程序,所以在 1978 年初,他看上了當時迪吉多新發表的 VAX-11/780.好不容易,他聯合了其它的部門才湊足購買 VAX的經費。剛開始時,機器原本安裝的是 VMS操作系統。不過別的成員要執行 UNIX 操作系統,于是 Fateman安裝上了 V32. 但問題來了,V32 并不支持虛擬內存,Fateman 便找上了 Domenico Ferrari 教授,希望他與他的研究小組能為 UNIX 加上這項功能。當時一位學生叫 Ozalp Babaoglu ,他想到了一些解決的方法似乎可行,但因為牽涉到 VAX硬件與 UNIX kernal的問題,于是他找上了 Joy幫忙。
    就在只有一臺 VAX的狀況下,他們努力奮戰著。1979年 1月,在 VAX上支持虛擬內存的UNIX版本終于誕生,V32 從此走入歷史。緊接著 Peter Kessler與 Marshall Kirk McKusick 為他加上了Pascal;Joy 則動手將 2BSD 上的 ex、vi、C shell 等工具轉移了過來。這個版本就是 3BSD.一個首次支持虛擬內存、demand paging 和 page eplacement 的 UNIX OS.


    400) {this.resized=true; this.width=400; this.alt='Click here to open new window';}" onmouseover="if(this.resized) this.style.cursor='hand';" onclick="window.open('/upimg/20070420/11M1035161F53004.jpg');" border="0">


    400) {this.resized=true; this.width=400; this.alt='Click here to open new window';}" onmouseover="if(this.resized) this.style.cursor='hand';" onclick="window.open('/upimg/20070420/11M1035164Z63303.jpg');" border="0">
    UNIX與 DARPA交會
    1970年代末,美國國防部先進研究計劃機構(Defense Advanced Research Projects Agency ——簡稱 DARPA)正在為 AI (Artificial Intelligence ),VLSI及計算器視覺等研究(vision research )找尋一個可共通作業的計算機環境。硬件方面的首選是迪吉多的 VAX主機。配合的操作系統是 VMS. 這樣的組合因擁有相當接近 DARPA 需求的功能被列入優先的考量,但在 DARPA與 DEC商談對于 VMS的支持事宜之后,DARPA 并沒有得到滿意的答案。這迫使他們考慮朝向UNIX發展。但當時 UNIX OS(指的就是32V )搭配 VAX,最大的缺憾就是沒有支持虛擬內存;但此時已經有人克服了。
    當時,Bob Fabry 教授寫了一份建議書給 DARPA,建議他們以柏克萊支持虛擬內存的 3BSD 為基礎,發展成為計劃所需。這份企劃書引起了 DARPA的高度興趣。隨后 3BSD 也實際獲得了 DARPA相關計劃成員們的良好風評,也因此最后柏克萊大學打敗了卡奈基梅隆大學與 BBN(Bolt Baranek & Newman , Inc. ),讓 Bob Fabry成功地獲得了 DARPA的資助合約。這份合約開始于 1980 年 4月,為期 18 月。此后的 DARPA便以 UNIX OS為標準操作系統。 Bob Fabry 教授在取得 DARPA合約后,依約成立了一個支持機構,也就是 Computer Systems Research Group簡稱 CSRG.Bob Fabry找上了 Bill Joy 來負責軟件開發。Joy 迅速地以先前的 3BSD 為基礎,整合新的功能。如 Job Contro l (作者是 Jim Kulp )、auto reboot 、1K block file system. 同時也整合入Pascal compiler 、Franz Lisp system、enhanced mail handling system.這就是在 1980 年所發表的 4BSD.沒多久她便被安裝在將近 500臺VAX 上。
    DARPA 采用了這個版本作為當時 DARPA的標準 UNIX 操作系統。
    樹大招風,當時,有位在 Stanford Research Institute的仁兄叫 David Kashtan,寫了一份關于 VMS與 BSD UNIX在 VAX上的執行效率評估。該份報告指出 BSD UNIX 在效率上不如 VMS來的好。Joy 知道這件事之后,花了不到一個星期的時間,重新調整 UNIX kernal. 然后也寫了一份報告,證明他們的BSD 在 VAX上要比 VMS優越多多。 1981年 6月,這個 Joy調整過的系統,加上了 Robert Elz 寫的 auto configuration ,以 4.1BSD 的版本發表了。
    當時的 DARPA對柏克萊 4.1BSD 的表現相當滿意,于是續簽了兩年的新約,金額更是先前合約的 5倍。其中有一半的金額用在資助柏克萊繼續發展 BSD UNIX . 錢多的相對代價就是要求高。當時,DARPA 對 UNIX 的期望開出了明確的目標;更迅速、更有效率的檔案系統、支持程序可執行地址達 multi-gigabyte 、提供彈性的解譯溝通能力、具整合支持網絡能力。
    在此同時,為了達到計劃的目標,DARPA 成立的一個指導委員會;主要的成員有柏克萊的 Bob Fabry, Bill Joy ,Sam Leffler 、BBN 公司的 Alan Nemeth and Rob Gurwitz、貝爾實驗室的 Dennis Ritchie 、史丹佛大學的 Keith Lantz、卡內基。梅倫大學 Rick Rashid、麻省理工學院 Bert Halstead、信息科學協會 Dan Lynch、DARPA 的 Duane Adams and Bob Baker以及加州。洛杉磯大學的 Jerry Popek.
    不久,Joy 便開始整合早先 BBN的 Rob Gurwitz所發表的 TCP/IP protocols ,不過他對 BBN這些程序的執行效率并不滿意,于是 Joy與 Sam Leffler重新寫的一版自己的程序。
    另外,并加入了一些支持網絡的工具 rcp,rsh , rlogin ,rwho. 他們稱她為 4.1aBSD,這個版本并沒有正式發表,在1982年 4月開始供內部使用。雖是如此,在 4.2BSD 未正式發表之前,她還是繁殖的到處都是。6 月, 4.1aBSD kernal加上了新完成的檔案系統,版本更新為 4.1bBSD.
    rcp , rsh, rlogin , rwho 這群指令。因安全機制上的理由,逐漸被另一群新的指令群所取代,新的指令群叫 SSH(Secure Shell)。SHH 相關網址(http://www.ssh.org)。
    1982年的春季末,已厭倦了在柏克萊環境的 Bill Joy ,答應受邀加入當年剛創辦的 Sun Microsystems , Inc. ,成為 SUN的第四號創辦人。那年的整個夏季他就在兩地奔走。之后他對修改中的彈性解譯溝通機制及改寫 UNIX kernal到一個段落之后,由 Leffler接手了他的工作。由于合約期限的因素,Leffler 在1983年 4月發表了 4.1cBSD,提供給參予 DARPA各項相關計劃的成員試用。6 月,DARPA 的指導委員會第二次會議招開,驗收與檢討最新版的 BSD 成果。繼續整合 UNIX 系統的 Leffler,在 1983 年 8月,發表了 4.2BSD.她達到了DARPA 的預定的需求;足以應付 CAD/CAM影像處理與 AI 研究的高速的檔案系統及擴展強化的虛擬內存功能;提供能分散處理的解譯溝通機制;支持56-Kbit 的 ARPA Internet網絡連結,以及 10-Mbit/s Ethernet 的局域網絡;還有經過重組架構已模塊化的 kernal code ,提供更有效率的計算機平臺移植。
    SUN 以生產 RISC 架構的工作站計算機為主,使用的正是以 BSD為基礎所的UNIX OS.在當時以不遜色于大型計算機的多人多任務、具網絡溝通功能的UNIX OS 、加上價格低廉的硬件(相對于 mini 級計算機而言),廣獲得工程界的青睞,而mini級大計算機的命運自此注定開始逐漸式微。計算機軟件的應用因為有了網絡于是也開始朝向 Client-Server的架構發展。
    1982年,SUN 有了自己的操作系統—— SunOS 1.0——承襲自 4.1BSD.一直到 1990 年11月,發表 SunOS 4.1.1 版同時冠上 Solaris 1.0時,SUN 才算開始向 System V 版本靠攏。
    SunOS 4.1.1 可算是以 BSD為主體再附加上 System V 工具的 UNIX 混血兒。但這其實是個商業考量的過渡性做法(后文會加以說明)。
    而 SunOS 4.1.x版的字眼也僅延續到 1994 年的 SunOS 4.1.4為止,她后繼的版本是 Solaris 1.3. 真正延續到今日的 Solaris版本,則是始于 1992 年 7月的Solaris 2.0 (SUN OS 5.0)。
    在商業有所成就的 SUN Microsystems 對 UNIX OS的發展倒也做了些重大貢獻;如 1984 年發表的 NFS(Network File System )與其后在 1986 年發表的PC- NFS.
    商業化的不平坦歷程—— UNIX 版本的戰爭
    UNIX商業化實質上即意味著將產生各種獨立化的 UNIX 版本,這點大概是最顯而易見的事實。如果以商品要具備獨特性與獨占性的利益來做考量的話,其實一點也不意外。因此 UNIX 開始衍生的相當多的版本。這種現象,對使用者以開發應用程序的廠商而言,已經造成了某成程度上困惑。然而,一種無所適從的無力感其實才剛開始。
    1984年 1月 1日, AT&T 這個擁有 1495 億美元資產、1 ,009 ,000 位員工的龐大巨獸,終于被格林法官(Harold H. Greene)以反扥拉斯法(antitrust ) 強制拆解成七家 RBOCs(Regional Bell Operating Companies ) . AT&T 也因而在一夕間解體成為區域性網絡公司,從此失去了長途電話的壟斷性地位。這種時空的轉變讓 AT&T 對 UNIX 的態度有了 180度的轉變(其實,農夫我指的是收費的態度)。
    先前已經提過 70 年代初期的 AT&T ,已經在長途電話市場上占有絕對壟斷的優勢,因而被美國政府的限制不得涉足與從事計算機與其它行業,也正因而造就了UNIX發展初期的自由開放。直到 1979 年,AT&T才宣布要將 UNIX 商業化的計劃。1981年 11 月,AT&T屬下的USG 發表了 System III.次年又更新為System IV.稍后于 1983 年,AT&T 將 CRG, USG合并成立了 UNIX System Development Lab. 一般簡稱為 USL,從其名稱就不難清楚她將要扮演的角色。該年 System V 上市了。此時 AT&T 發覺每次版本更新都得花不少宣傳費,實在不劃算,所以決定在 System V 以后,名字就不再做變動了。1984年,System V Release 2發表,簡稱為 SVR2.在這個版本中,才終于看到來自 BSD 版本的 Virtual memory 功能,農夫我不得不驚嘆 AT&T 的穩健作風。SVR3則是到了 1986 年才發表,隨后 1987 年又發表了 SVR3.2.
    1987年,在工作站市場上已占有一席之地的 SUN,找上了 AT&T ,打算將System V與 BSD這兩大版本歸為一統。 1988年初,雙方更簽訂了合作合約,AT&T取得 SUN的一席董事,同時亦有權買下 SUN百分之二十的股份。這項合作計劃,原本有機會整合當時版本紛亂的 UNIX OS. 但那是理想。實際上這個計劃反而讓 UNIX 族群里的其它成員恐慌萬分,特別是 IBM、DEC 、HP這幾個產業龍頭。為了抵制這項行動,他們組織了一個反對聯盟。因此「開放軟件基金會」也就是 Open Software Foundation 簡稱 OSF在 1988 年正式誕生;成員除了前面的三巨頭外,尚有多達三十幾家計算機硬件制造廠商與系統咨詢顧問公司,也相繼以行動投入到此反對的行列中。然而 AT&T 與 SUN也不示弱地組織了 UNIX International ,也就是UNIX國際公司,成員數量雖然不比 OSF陣營來的多,但如果她是 Intel、 Toshiba 、Unisys、Motorola、Fujitsu ,這幾個大塊頭,那也是很夠看頭的。
    企業自身的利益在現實世界里始終是以個體的考量為優先,所以這兩大陣營始終沒能再達成任何共識,就連當時所制定的 UNIX 統一標準規格,嚴格來說也從不曾被實現過。這種企業利益上的沖突與矛盾其實也存在于同一個陣營中不同的成員之間。兩大陣營對峙,可以說是 UNIX 有史以來最重大的產業沖突事件。
    由于商業利益的政治考量大過技術問題的考量,也因此奠定了 UNIX 將繼續分裂下去的命運。 AT&T 在 1989 年發表了 SVR4 ,SUN 在日后也將她的 SunOS 4.1. 1 開始冠上 Solaris的字眼,以行動靠攏 SVR4.OSF 則是在 1990 年發表了OSF/1.UNIX版本的問題因而更加混亂了。但有趣且可笑的是,開放系統——Open System ,這個雙方都標榜的理念與觀念卻因此在計算機產業界引起了回響,這點倒是原先所始料未及的。
    不久 AT&T 撤銷了對 SUN的投資,同一個陣營的成員彼此也因而勞燕分飛。
    USL 在 1991 年正式轉變了一家獨立的商業公司。但 UNIX 在商業市場上的價值卻出現了變化……
    讓 UNIX 自由—— Networking Release 2
    自從 UNIX 走出貝爾實驗室后,研究機構與學術界就扮演了繼承與發展的雙重角色。在1979到 1984 年這段期間,UNIX的擁有者 AT&T ,對于學術界的授權政策尚可用「大方」來形容;同時也對學術界做某種程度的資助與合作。當時的學術界,得助于 AT&T 的大方授權與分享程序原始碼,研習 UNIX 這個分時操作系統開始在學術界蔚為一股風氣,甚至可以說是一種潮流或一種流行。其中,像柏克萊 BSD對 UNIX 的貢獻,就是一個公開的事實。但早期的 BSD使用者,是必需向 AT&T 支付授權金的。這點,從產業界資助學術界的角度來看是一點也不值得驚訝的。因為資金的援助為了就是取得其成果。所以當時基于 AT&T 原始碼所發展的成果,均歸屬 AT&T 所有。也因而 AT&T 掌控了 UNIX 的所有權。到了1984年以后,AT&T開始更積極地保護 UNIX 的原始碼;AT&T甚至還要求各大學的使用人員簽訂保密條約,想藉此防堵 UNIX 的原始碼從學術單位流出,以影響到商業利益。
    在 DARPA資助柏克萊從事 BSD OS 發展的過程中,誕生了 TCP/IP 這項廣泛影響現今計算機與因特網的通訊協議。由于 DARPA對于資助開發的軟件項目有明文規定接受資助者必須無條件地釋出程序的原始碼,所以 TCP/IP 的原始碼與程序的版權并不屬于 AT&T 所有。這點在現今看來其意義是不凡的。也正因為有此一條件,柏克萊的 CSRG (Computer System Research Group)因應 BSD Vendors需求,在 1989 年 6月發表了 Networking Release 1 ,她包含了TCP/IP source code以及一些工具,提供給當時正開始起步發展的個人計算機制造業者使用。Networking Release 1 授權收費僅 1000 美元,而且不需要 T&T的商業授權,取而代之的是柏克萊大學的開放式授權。
    農夫我看柏克萊授權方式,幾乎可以說是一種良心式授權方式,在實質的運用上她完全沒有限制。她允許原始碼或執行檔在任何情況下修改并且允許將修改后的程序 從事商業行為而無須任何回饋,當然也沒有絕對要求開發者必須要釋出原始碼。如果你改都不改地加以販售,她也沒有意見。但有一點不可違反的限制,就是必須在 衍生物的版權聲明上提到柏克萊的貢獻。這種做法在日后,也沒有多少改變,而這樣的授權方式也成為了柏克萊的授權精神。
    Keith Bostic由于 Networking Release 1 所得到的響應實在遠超過 CSRG 成員的預估。
    這個不算差的成果,讓柏克萊的 CSRG 覺得有必要釋出更多屬于 BSD的程序原始碼。于是激發 CSRG 的成員 Keith Bostic開始組織志愿工作者從事一項就算不能夠驚天也足以動地的程序寫作計劃。計劃的主要目的在當時還真讓人感到有點" 烏扥邦".農夫我個人喜歡戲稱她為「解放 UNIX 計劃」。
    Marshall Kirk McKusick這項計劃大體上分成兩個部分,操作系統工具(Utility )
    與核心(kernal)。而且參與人員必須在完全沒有參考 AT&T UNIX source code的情況下進行撰寫程序的工作。因為只有在這種條件下,寫出來的程序代碼,才能擺脫 AT&T 的著作權束縛。當然這也絕對不是一件容易的事。Keith Bostic四處奔走,組織了超過四百名熱心的軟件工程師,經過了長達十八個月的奮戰之后,操作系統主要的工具與鏈接庫才算改寫完成。Marshall Kirk McKusick負責改寫當時的核心程序。但系統核心的部分,由于長期以來柏克萊與 AT&T 一直就彼此分享 UNIX 原始碼,所以各自所加上去的程序代碼早已混雜難分了。為了徹底的厘清雙方各自撰寫的部分,他們下決心進行逐行比對。首先花了好幾個月的時間,將核心程序每 一行每一個檔案都建立轉換比對的數據庫。然后接著進行移除來自 AT&T 32V 的程序代碼并改寫她們。即使是如此,仍舊有 6只程序讓他們束手無策,因而無法將核心程序徹底完整地改寫。最后,他們還是決定將他們所做的所有成果發表。授權的方式沿用 Networking Release 1 的授權方式,授權的磁帶依舊是 1000 美金。這個版本就是 Networking Release 2 ,也有人稱她為 4.3BSD NET/2.發表的時間在 1991 年 6月。雖然這是個不完整的操作系統。
    但,在今日看來,卻有著劃時代的意義—— UNIX OS自由了。
    誰是" 老大哥" ——侵權訴訟
    AT&T的 USL在 1991 年正式轉變了一家公司。當然,這意味著她將更重視UNIX在商業上的利益。當時的 UNIX OS早以稱霸高階的計算機市場;從 Cray 超級計算機、IBM 的大型計算機主機、迷你級計算機到工作站,均是 UNIX 的天下(這一點,直到現在21世紀,仍舊沒有多大的改變)。即使在 80 年代中期后開始迅速發展的個人計算機,雖然當時被戲稱為是玩具計算機,但也仍舊有像XENIX[注1], Interactive UNIX[注2]等幾種向 AT&T 繳過稅的商業化版本。
    UNIX簡直就是 AT&T 的一棵搖錢樹。
    但這一切在 Networking Release 2 (以后簡寫為 Net/2)出現之后,起了變化!
    首先,一位 i386 處理器的玩家名叫 Bill Jolitz,在拿到 Net/2之后,很快地就將 Net/2 kernal 缺少的程序補齊了。BSD kernal這時可算是大功告成了。
    當時 Bill Jolitz將他們放在因特網與其它人共享他的原始碼,并且得到了不少正面的響應。由于這個版本是使用在 i386 微處理器的個人計算機上,所以就命名為386BSD,在 1992 年 2月正式發表。這該算是 BSD首度功能完整且版權獨立的版本。Bill Jolitz 是當時唯一的 kernal 維護者。在他離開這個計劃之后,繼起的 BSD玩家們延續了這個版本,日后衍生了 FreeBSD,然后又從其中分支出裂NetBSD版本。
    另一個將 Net/2完整化的是一家叫 Berkeley Software Design ,Incorporated的公司,簡稱 BSDI[注3]. 由于 Net/2的版權聲明中,宣稱其源文件的合法性,并且允許使用者,從事衍生物的商業行為,所以 BSDI 將他們修改后的系統命名為 BSD/386. 他們并將成果打包,刊登廣告以 995美金的售價販售 BSD/386,而且含原始碼,而且還提供免費服務電話的咨詢,電號號碼是"1-800-ITS-Unix". 時間大約是在 1992 年 1月。當時,USL 的 System V 含 source code的價格大約是 BSD/386價格的一百倍左右。這可驚動了老大哥 AT&T.并且正式地書面嚴重警告 BSDI 違反的注冊商標法(電話號碼里有Unix的字眼),并公開宣稱 AT&T 擁有 UNIX 的注冊商標。BSDI再次刊登廣告公開反擊 AT&T ,聲明她的商業行為完全合法。果不期然,BSDI的博命演出讓雙方手牽手走上法庭。
    AT&T的 USL控告 BSDI 剽竊他的 UNIX 原始碼,要求法官還他公道。在聽證會上,BSDI祭出早已準備好的法寶;自己在無任何 AT&T source code 的條件下寫出的合法檔案,以及來自于 BSD授權的 Net/2 source code. 前面的證據足以讓 BSDI 立于不敗之地,后者讓 BSDI 置身在暴風圈外。BSDI的辨證獲得了法官的采信。但 At&T 豈會就此罷手,他們將焦點轉移到 Net/2的 BSD授權上面,并且重新提出控訴,被告的對象變成了 BSDI 與柏克萊大學;同時 AT&T 還申請法庭禁止 BSDI 一切的 BSD/386銷售行為。就這樣,柏克萊大學也對號入座了。
    農夫我認為,畢竟 AT&T 是營利企業,她得維護她的商業利益,這點是天經地義的事。
    雖然柏克萊大學與 AT&T 在 UNIX 發展上有著非比尋常的關系,但商業利益是現實的。企業資助學術界的研究計劃,多半是基于商業上的考量;我相信,學術界的少數高層在尋求奧援時不會不明白這 一點,即使這有可能讓大部分的學術人士無法接受或不愿接受。不管如何,這一記醒棍倒再次挑起了這一點事實。
    成為被告的柏克萊大學,只好無奈地面對這場無情的商業訴訟。但他們也同樣不甘示弱地對 AT&T 的 Systerm V 著作權提出質疑,因為在 AT&T 的 UNIX 授權聲明中完全沒有提及柏克萊的貢獻。所以柏克萊反控 AT&T 違反 BSD 的授權條款。柏克萊的反擊讓戰況越演越烈,訴訟案一路從 AT&T 的老家新澤西州的聯邦法庭打到柏克萊大學的所在地加州法院,但依舊沒有結果。
    到了 1993 年,官司還在進行中,但 AT&T 卻已經打包 USL準備以一億美元的價格找尋買主了。最后 AT&T 將 USL 以八千萬美元代價的賣給了 Novell.而新買主也當仁不讓地加入了這場混戰。但卻也因此,戰況露出了一線平息的曙光。
    訴訟案在 1994 年 1月宣告終結,以庭外和解收場。實際的協議內容僅有當事人知情。
    如果從勝負的角度來看這場訴訟,或許柏克萊與 BSDI 是勝利的一方。但如果從UNIX發展的腳步來看這場訴訟,就可能根本沒有任何一方是勝利者了。
    事件平息后的 1994 年 6月,柏克萊的 CSRG 風光地發表了 BSD 4.4 Lite.在這個版本中,有 70 個檔案引用的一份新修改的版權聲明,闡述的 AT&T 與 BSD雙方的貢獻,并明確地給予檔案自由散播的權利。但不知為何,應該有能力完整發表的 BSD 4.4 Lite 還是缺少了三的檔案。當時,農夫我也很高興地買了一本BSD4.4-Lite CD-ROM Companion ,含一張光盤,現在拿在手上,看來總覺得有點呆。
    掌握 UNIX source code 以及 UNIX 商標的 Novell ,將 UNIX 商標交給X/open管理,自己則發展了一套命名為 UNIXWave 的操作系統。推出后市場的反應并不熱絡。不久,Novell與 SCO接頭,在 SCO保證繼續支持UNIXWare 的條件下,UNIX在 1995 年二次易主,新主人是SCO[注4].
    備注:*1 Intel在 1978 年發表 4.77 MHz 的 8086 微處理器。1980年,Microsfot 便以 V7 為基礎,發表了在微處理器(microprocessor-based computers)上執行的版本也就是 XENIX. 到了 1982 年,一家成立于 1979 年的軟件公司 Santa Cruz Operation ,成為微軟的合作開發廠商。之后她這家公司便一直致力于這個領域里延續到今日,縮寫就是今日的 SCO.
    *2 Interactive IS/1 (以 V6 為主體)。這個版本后來演化為比較讓人熟知的名字—— Interactive UNIX. 后來因為 Sun Microsystems 致力發展 Solaris for X86,被財力雄厚的 Sun Microsystems 合并了,如今已經不見蹤跡了。
    *3就在我反復修改這段文稿的時候,BSDI這家公司已經被 Wind River 合并了,改名為iXsystems.2001/05/03
    *4 2001 年 5月 4日,Caldera International , Inc. 正式并購了 SCO的服務器軟件部及SCO 專業服務部這兩個部門,新的控股公司名為 Caldera, Inc


    400) {this.resized=true; this.width=400; this.alt='Click here to open new window';}" onmouseover="if(this.resized) this.style.cursor='hand';" onclick="window.open('/upimg/20070420/11M10351DZN248.jpg');" border="0">


    400) {this.resized=true; this.width=400; this.alt='Click here to open new window';}" onmouseover="if(this.resized) this.style.cursor='hand';" onclick="window.open('/upimg/20070420/11M10351HPY959.jpg');" border="0">
    GNU 計劃——開啟了新大道
    在 1983 年 9月 27 日,麻省理工學院人工智能實驗室(MIT Artificial Intelligence Lab )的 Richard M. Stallman(以下簡稱為 RMS),在net.unix-wizards以及net.usoft 的 newsgroups 貼上了一份標題為 "new UNIX implementation" 的訊息。這就是如今廣為人知的 GNU計劃的開始。在那則被視為「GNU 宣言」草稿的訊息中,RMS 闡述個人的理念與計劃的目的——完成一個命名為 GNU的 "Free UNIX"操作系統,希望藉此尋喚理念想同者共襄盛舉。
    「如果我喜歡一個程序的話,那我就應該分享給其它喜歡這個程序的人」,這是RMS 的座右銘。此點也似乎正是促使其決心運作 GNU計劃的原動力。當時的RMS 是想寫出一套免費的操作系統。能夠讓每個人如空氣般地自由的取得與使用。
    選擇“UNIX兼容”為設計的主要原因是;RMS 表明,UNIX并非他個人理想中的操作系統;他僅閱讀一些相關數據,但未曾使用過(MIT 使用操作系統是"ITS——Incompatible Timesharing System");但他認為 UNIX 操作系統具有優良的本質特性。他相信如果 GUN與 UNIX 兼容將更容易令人接受。所以 RMS承襲 MIT用遞歸縮寫字命名的傳統為 GNU釋譯界定 Gnu is Not Unix.
    1984年 1月,RMS 為了展開他的理想而決心離開已經待了十幾年的 MIT AI Lab.。當他向他老板 Patrick Winston 辭職時,Winston 試圖挽留地說:「你還是要辭職?」。RMS 不為所動的回答:「是」。Winston 顯然得到預料中的答案,于是接著說出了思緒里關懷:「你想要保留你的鑰匙嗎?」。于是 RMS就從此開始專心地" 失業" 在他的老東家。一個人窩在他原來的舊辦公室中,規劃著如何開始他的 GNU計劃。但想開發一套新的 UNIX 兼容的操作系統,即使是財力、人力資源雄厚的頂級計算機公司,也絕對不是一件說想做就能夠做到的事。
    當擬妥他的「GNU 宣言」之后,他正式向全世界呼喚、表明其將所為。種子落地了。
    GNU 計劃的第一只程序要算是孤軍奮戰的 RMS在 1984 年 9月開始撰寫的Emacs 編輯器。
    1985年初,Emacs 已進入可用的階段。于是 RMS將她放在pre.ai.mit.edu這臺機器的 FTP server 上,免費地讓 amonymous的到訪者自由下載使用。不久后,Emacs 強捍的功能引發了一些玩家們的注意,由于附上了 source code,玩家們能自己動手為它添加新的功能或除錯,很快地,Emacs 獲得了相當熱烈的回響。隨著名聲漸播,開始有人相繼地加入 GNU計劃的程序寫作陣營。" 此道不孤" 讓 RMS倍感振奮與喜悅。
    當時的因特網并未十分普及。所以有不少人雖然對 Emacs程序有興趣,卻沒辦法經由 FTP的管道取得,因而有人透過其它管道向 RMS詢問能如何取得時,這可讓當時處在失業狀態的RMS 看到能夠支持他繼續奮戰下去的資金來源——販售" 自由軟件".
    一個人、一個獨立的個人,要想在現實中實行自己的理念,最先得接受" 現實".唯有接收它是事實,實行理念的道路,才獲得比較穩固的起點與開始。 ——網絡農夫如是說。
    想著、寫著,腦中突然掠過一絲感受(所以順便記錄在這個地方)。不管如何,RMS 真的開始以一卷磁帶 150 塊美金的代價,服務有需要的人。也因為基于這個開始與基礎,RMS 當年便創立了自由軟件基金會—— Free Software Foundation(以后簡稱為FSF )。這對GNU 計劃而言,意味著它已跨越個人化理念的構思階段,并進入了有群體組織化的運作階段。
    同時,RMS 也制定出了屬于GNU 計劃的軟件版權。RMS 使用 "copyleft" 用來形容她,其實就是與著作版權(copyright ) " 對立" 之意。這也就是 GPL—— General Purpose License(通用公共授權)。
    GNU 計劃的種子,就這樣生根發芽了。
    從販賣 GNU自由軟件擴展到其它的相關軟件與參考手冊,提供軟件技術支持,并接受計算機器材與資金的捐助(捐助者依法享有一定額度的減稅),為企業代訓軟件人 才。FSF 努力地開辟財源卻仍舊是運作資金捉襟見肘。RMS 本人并不支薪。而FSF 聘請軟件工程師的待遇,也僅是軟件業界薪資水平的一半。但這絕不表示GNU 計劃的軟件水準是半桶水。GCC 編譯器是 GNU計劃在 1987 年 3月開始發表的免費編譯器,當時的版本是 0.9測試版。如今最新的版本則是 3.0. 這個編譯器可以說是今日自由軟件寫作的基石。GCC 所解譯的機器碼,其可靠度絕對不遜于商業化的編譯器產品,甚至可以說是優越過商業編譯器。
    90年代初,GNU 計劃暨已完成了質量與數量均十分可觀的系統工具。這些工具被廣泛的使用在當時各種工作站的 UNIX 系統上。雖然已有如此的成果,但仍稱不上是完整的操作系統。他們缺少一支屬于自己的" 核心程序(kernal)".
    UNIX在 4.2BSD 之后,越寫越大 kernal 開始帶來一些不便與問題。因而當時便開始有另一個寫作理念逐漸在發展——微核心(microkernal )理念。
    1985年,卡內基大學(Carnegie Mellon University簡稱 CMU)暨以 4.3BSD 為發展基礎,將之一拆為二,分成 micro kernal 與 single server兩個部分。
    該計劃的名稱為"Mach". 這個計劃成了微核心發展的技術先河。GNU 原本有意直接采用"Mach"計劃的成果。但無奈,這一等,從80年代中等到了90年代初,在幾經商量之后,他們打算采用微核心的寫法,成立自己的計劃, 名稱叫"Hurd". 這項計劃,如今仍在奮戰中,雖然 microkernal的做法讓他們吃了不少苦頭;但可喜的是,0.2 , 0.3 測試版本已經發表。
    直到 21 世紀的今日,RMS 依舊努力不懈地耕耘著他的夢土。盡管他本人認為還尚未完全地實現他的「GNU 宣言」;但他執著于理念的行動,已凝聚了相當數量的自由軟件寫作族群們,在這些人與群體的努力下,一條新的大道其實已經被開拓出來了,她通往一個新的世 界。大道旁,枝葉已然繁茂的樹蔭下,可口果實一如禮物般地為所有的人成熟。人們稱她—— Linux.
    新世代的焦點—— Linux
    1990年代中期,因特網因出現 World Wide Web , HTML 這種新型態的應用,而開始迅速的延燒全世界。一夕間,架設因特網主機的需求激增。這時有一套可以免費取得,并且能讓 x86計算機升格成 UNIX 級主機的免費操作系統,開始了吸引全世界目光。在傳媒與計算機工程師們的競相走告下成為了這個新世代的焦點,這個新的名字就是 Linux.
    Linus Benedict Torvalds 當然,這套媒體吹捧的當紅炸子雞,可非一人之功,一夕即成的。Linux 是一套版權徹徹底底與 AT&T 無關的 UNIX-like OS.原始核心程序的創作者是芬蘭籍的 Linus Benedict Torvalds(現今他仍舊是核心程序的維護者)。操作系統里大部分的系統工具,來自于 RMS行之多年的 GNU計劃成果,以及其它的自由軟件寫作計劃產生的軟件,如 X Windows、KDE 、Gnome 等窗口接口。由于構成操作系統的主要部分均奉行 GPL 版權,所以市面上有相當多樣的安裝套件,目前較廣為人知的有 RedHat 、Slackware 、SuSE、Debian GNU/Linux ……。也因此,這套操作系統,可說是包含了無數字自由軟件寫作者的共同心血。
    如此的一套操作系統其實也就是 RMS多年來想要達成的宿愿—— "Free UNIX". 所以,RMS 本人總認為該將名稱改做"GNU/Linux".因此,也有人用 GNU/Linux來稱呼這個操作系統。
    Torvalds打從十歲出頭當他外公的" 鍵盤手" 開始,到了中學就已成了不折不扣的計算機迷。1990年,當他就讀赫爾辛基大學(University of Helsinki) 信息系二年級,選修一門「C 語言與 UNIX 操作系統」的課程,因而瘋狂地迷戀上了UNIX操作系統。那年正好赫爾辛基大學正好添購的一臺 VAX,安裝 Ultrix 操作系統。連接了 16 臺終端機供授課師生使用。有所限制的計算機資源,對一位計算機迷來說是極痛苦忍受的。
    Torvalds開始作夢想" 搞" 一套可以在自己計算機上跑的 UNIX.
    1991年 1月,Torvalds利用 "學生貸款" 加上去年的 "耶誕紅包" ,以分期付款方式買了一臺 386 DX33 個人計算機(他的第三臺計算機)。他選擇安裝的操作系統則是在學術界頗負盛名的 Minix[ 注5]. 在幾番奮戰下,就緒運作的 Minix OS 功能性卻多方面無法滿足Torvalds的需求,因而激發了他重頭來的欲念。于是 Torvalds 在他的 386 DX33 上逐步探索并撰寫出他自己的核心程序。他網絡上釋放的第一個版本是 1991 年 9月 17 日的 0.01 版。雖然她是個簡陋的開始,但由于 Torvalds 本人持續維護與網友回饋貢獻,原本一個人所撰寫的核心程序竟在不知不覺中逐漸轉化成 "虛擬團隊" 的運作模式。
    然而,一般計算機使用者,需要的是可安裝運作的操作系統(農夫我習慣以" 安裝套件" 稱之),而非單一的操作系統核心。當時英國的曼徹斯特電算中心(Manchester Computer Center,簡稱 MCC)便根據 0.12 版核心程序制作了一套名為 MCC Imterin的安裝套件。隨后各地的安裝套件有如雨后春筍般地出現;如美國德州 Dave Safford 的 TAMU (Texas A&M University)版、Martin Junius 的 MJ 版、Peter McDonald的 SLS(Softlanding Linux Sustem)版等非商業安裝套件的出現。在安裝需求日增的情況下,Linux 安裝套件創造出了一塊新的需求市場。這一線商機,讓非商業安裝套件的也開始出現在商業市場上。Slackware 大概可算是最早出現的商業安裝套件了。到如今,商業與非商業的安裝套件則已多得數不清了。
    隨著使用人數激增,核心程序的版本與功能也開始加速演化,但仍不失于穩健。
    1994年 3月 13 日,核心程序 1.0正式發表。其安裝套件在功能上的整合已急起直追當時商業版的 UNIX OS. 此時的 Linux OS 已擁有數十萬名使用者。當時赫爾辛基大學還以此為由舉辦了一場名為"Linux首度正式發表會". 就在芬蘭電視臺與眾多傳媒的鄭重其事的報導下,Torvalds成了芬蘭人的自豪,Linux OS宛如剛誕生的" 超新星" ,閃閃發亮地展現在眾人眼前。
    早期的 Linux核心程序曾被 Andrew Tanenbaum 指出,過度緊密地與 x86處理器結合,所以他認為 Linux核心程序將無法移植到別的處理器上。這點顯然與UNIX OS 的可移植性大不相同。當時的情況的確是如此,這或多或少與Torvalds本人受限于擁有的硬件資源有關。
    但當 Linux的使用族群拓展開來之后,便開始有人主動地將她移植到不同的平臺上。像 Dave Miller即以不下于Torvalds狂熱與學習精神將 Linux成功地移植到 SUN的 SPARC工作站上。
    此外如 Amiga、Atari 、PowerPc 、MIPS R4000也陸續見到 Linux的身影。
    這些移植嚴格地從技術的角度來看,僅能說是" 個案".但這已激發 Torvalds 的興趣。
    真正撼動 Linux核心的移植是對 Alpha處理器。
    1994年 5月,在 DEC使用者協會上,Digital 的工程師 John Hall(外號Maddog) 碰上了 Torvalds ,雙方一見如故。Maddog力勸 Torvalds 將Linux 移植到 Alpha芯片上,并主動提供了一臺 Alpha 計算機供 Torvalds 研究使用。當年可說是全世界最快的 64-bits Alpha芯片是 DEC引以為豪的一項成就,其架構與功能均優越過同一時期的 Intel 32-bits處理器。這種技術性的挑戰吸引了 Torvalds 的投入。這項移植,但這對原先以 x86微處理器為寫作基礎的 Linux核心程序而言,實在不是一件小工程。在 Torvalds 與 DEC相關人員的將近一年奮戰后,Linux 核心程序脫胎換骨,成功地移植到 Alpha處理器上(與 x86處理器使用同一套程序代碼)。1995年 3月,被戲謔是 Linux'95 的1.2 版核心程序正式發表,支持Intel x86 、DEC Alpha 、SUN SPARC 、MIPS等處理器。
    1996年 6月,核心程序版本由 1.3直接躍升為 2.0版。Torvalds本人正式欽定了一只" 企鵝" 作為 Linux的標志。同時也開始支持對稱式多重處理器(Symmetric Multi-Processing,簡稱 SMP)架構的計算機;而支持的處理器則又多了 Motorola 68k 和 PowerPc. 在自由軟件團體們的努力與計算機產業業界的支持投入之下,Linux 具備的功能逼近商業版 UNIX OS. 當然,Linux 要達到" 成熟" 與" 穩定" ,實際上還有好長的一段路要走。
    時至今日,散播在全球各地的 Linux虛擬發展團體,仍舊持續地發展中。能維持到什么時候?這在將來的歷史自有答案。但至少在現今,一個 RMS奮斗的目標——可自由分享程序代碼的操作系統,已可貴地呈現在我們的眼前。
    備注:*5 Minix是 Andrew Tanenbaum 教授為教學目的而撰寫的操作系統。
    在教育界可算是一套學習 UNIX 基礎的好范本。


    400) {this.resized=true; this.width=400; this.alt='Click here to open new window';}" onmouseover="if(this.resized) this.style.cursor='hand';" onclick="window.open('/upimg/20070420/11M10351K6092622.jpg');" border="0">


    400) {this.resized=true; this.width=400; this.alt='Click here to open new window';}" onmouseover="if(this.resized) this.style.cursor='hand';" onclick="window.open('/upimg/20070420/11M10351N20109221.jpg');" border="0">

    新文明世紀自由共享
    到此,這一段關于 UNIX 發展的文字,已從過去的歷史當中走回到了今日…
    … 21 世紀的今日。本文也接近尾聲了。請諸位原諒農夫將以極為自身的歷史感受,來作為本文的結語。
    閱讀與探究歷史,是農夫個人在年輕時即有的一點小癖好。通常我無法忍受對自己喜好事物的緣由一無所知。所以我會想辦法去探究她由誰所創、因何而生與發展的沿革。也正因為如此,我才會為 UNIX 這個當初我沒能在英文字典上找的怪字,寫了這么一篇文字。
    然而在 UNIX 的發展過程當中,我驚訝地發現了一項有別于我探索 20 世紀歷史的東西。
    我相信諸君應該清楚,20世紀是人類文明史上最為血腥殘暴的一段歲月。在其間,多數民族的上個世代所遭逢的苦難,都是空前的。哲學家柏林(Isaiah Berlin )回顧 20 世紀的感受,說了以下這樣的一段話。
    「我的一生——我一定得這么說一句——經歷了二十世紀,卻不曾遭逢個人苦難。
    然而在我的記憶之中,它卻是西方史上最可怕的一個世紀。」
    的確,每當我閱讀 20 世紀的相關史料,我就更能加倍地感受到這份莫名的幸運。我生長在臺灣,這塊回顧其歷史僅能以" 悲土" 稱之的島上,她的苦難直至今日亦尚未完全結束。
    盡管多數年輕的一代已然淡忘,來自何方,歸往何處。
    身為一個中國人,站立在這塊似乎仍將被同胞武力相向的孤島上……我已不清楚歷史傷口會因得到同胞的愛而痊愈,還是再次因人類殘暴掠奪的天性而迸裂……
    抱歉,離題了。
    我想說的是,在 20 世紀未的因特網時代中,我感受到了令人喜悅地,根源于心、跨越既有疆界藩籬的自由共享文明。這相較于 20 世紀初將" 戰爭" 視作為文明象征的人類而言,實屬無價可貴的進展。即使這文明仍僅是剛播下的種子。
    但我相信,她將如貝聿銘所言:
    「你永無法明確知道你已播種的東西何時可以收割;或許只有一次收成,或許可重復收成。你也許遺忘曾播種了些什么,一種經驗,一種感受,與某人的關系,抑或一種哲學及一項傳統。然后,忽然間就開花了,被全然不同的環境所喚醒。這種盛開可以沖破藩籬及整個時代。」
    多希望親眼看到,幾個世代后的某日,人類彼此掠奪的行為如天花一般地在人類社會中絕跡;而,共享已成為人類整體奉行的道德公理。如果這樣的一個社會是我們今日所企求的;那么,這個方向與希望,就值得你我花一生的精力去努力。
    當然,這僅只是一個個人的希望,我也清楚這世間并非如此美好。但,如果因假設一件事物不可能做到,而決定不去做;那是假設得到勝利,而非真實的事實。
    或許過去的歷史,曾經證實正義、公理、平等與理想的勝利,不過是短暫的曇花一現;那又如何。只要我們不放棄希望,希望就有機會成為真實。今日,所有的美好均因此得來,明日也是。
    這幾年來,我已看到不少因特網上諸君們的努力。我也相信這嶄新文明的種子,有朝一日將展現出令人贊嘆、愉悅的美景。未來存在我們尚未發現的國度。
    我相信,我們能發現未曾走過的通道,打開不曾打開的門,進入玫瑰園中……那會是一個嶄新的文明。


    摘自:http://www.oklinux.cn/html/other/unix/20070421/21330.html

    posted @ 2009-11-15 15:56 石頭@ 閱讀(2141) | 評論 (0)編輯 收藏

    測試你的C語言掌握程度

    字符串 
    學習時間:1.5W(“W”周,下同)
    知識點checklist
    strlen()函數的返回值是什么類型的?
    字符串strlen()的值,是否和他占據的內存空間相同?
    你是否知道strcpy函數存在的潛在風險?如何避免?
    如果一個字符串沒有字符串結束符,而調用str開頭的庫函數,會發生什么?
    Strcpy(),strcat(),strcmp(),strncpy(),strncat(),strncmp()內部到底是如何運行的?這些函數到底對源字符串和目標字符串做了些什么?你是否觀察過它們運行時兩個字符串內存的變化?
    上面這些函數使用時,各有哪些需要注意的地方?
    你會幾種字符串查找操作?
    c語言中有字符串這個數據類型嗎?
    對字符串進行操作的時候,是否為字符串結尾符預留存儲位置?不然的話容易造成非常訪問內存。

    數組
    學習時間:2W
    知識點checklist
    你肯定知道,定義“int a[10];”,a[10]這個元素是無效的。
    你知道幾種數組初始化的方法?
    數組和指針有千絲萬縷的聯系而又不同,你是否對他們在不同情況下的使用進行過詳細的總結?
    “int calendar[10][20];”,這是一個什么樣的數組?它擁有10數組類型的元素,還是20個?
    “int a[10];”,數組名a在本質上是一個什么?你是否打印過a的值?
    你知道幾種獲取數組某元素的方法?
    指針和數組相同嗎?什么時候相同?什么時候不同?
    用指針和下標訪問數組元素,那種方式更快?

    結構體
    學習時間:1W
    知識點checklist
    你知道什么是位域結構體嗎?如何定義它?如何使用它?
    你知道字節對齊對結構體占用內存空間大小的影響嗎?如何計算結構體占用內存的大小?


    學習時間:1W
    知識點checklist
    你知道宏的本質是什么嗎?函數?語句?類型定義?或者其他?
    你知道語言設計者為什么設計宏嗎?這些原因目前是否仍然成立?
    你會設計帶有參數的宏嗎?
    你知道使用宏的參數的的時候的注意事項嗎?
    你會設計帶有可變參數的宏嗎?
    你知道使用宏有什么劣勢嗎?
    你有沒有更好的替代方案?


    枚舉
    學習時間:0.5W
    知識點checklist
    是否可以指定枚舉中各項的值?
    如果不指定值,枚舉的第一個值是多少?
    枚舉的值是否可以是負數?
    定義枚舉的時候,你是否專門定義了枚舉的最小值和最大值?


    Switch
    學習時間:0.5W
    知識點checklist
    switch(c)中的c的數據類型有哪些?
    你是否在所有的switch中都加了default語句?
    是否在所有的case中都加了break語句(一般情況的做法)?如果你不加break,將會發生什么?


    Static
    學習時間:1W
    知識點checklist
    static的三個主要作用是什么?
    static的修飾的局部變量是保存在什么地方的?全局變量哪?
    static修飾的全局變量和函數,在其他的文件中是否可以訪問?如何訪問?
    你知道static是c語言中實現封裝和隱藏的利器嗎?你是否經常使用?
    定義在不同源文件中的static全局變量,編譯器是否允許他們的變量名稱相同?他們在內存中的地址是否相同?函數那?


    const
    學習時間:1W
    知識點checklist
    你是否經常使用const來表明不能夠被更改的變量?
    你是否經常使用const常量來代替宏?
    下面四種情況,你知道是各表示什么意思嗎?
    int  i_value= 10;
    const  int* pvalue = &i_value
    int  const *pvalue = &i_valueint*  const  pvalue= &i_value
    const  int* const  pvalue = &i_value
    你知道const常量如何初始化嗎?


    Sizeof
    學習時間:1W
    知識點checklist
    對于字符數組,strlen和sizeof的值是否相同?
    Sizeof本質上是函數還是宏?
    Sizeof的返回值是什么類型?


    指針
    學習時間:3W
    知識點checklist
    “int *p;”&p,p,*p他們的值分別表示什么含義?
    你定義的指針初始化了沒?
    你理解指針的指針的概念嗎?你會使用嗎?
    “int *pi_value; pi_value = 0x100000;” pi_value + 1的值是是多少?
    你會定義函數指針嗎?
    你會使用函數指針調用函數嗎?
    關于指針和數組,請參見知識點數組。


    動態分配內存
    學習時間:1W
    知識點checklist
    動態分配的內存是保存在什么地方的?
    什么情況下使用動態分配內存?
    動態申請內存一定要釋放,否則會內存泄露。你是否使用過內存檢測工具?


    函數
    學習時間:1W
    知識點checklist
    如何查看函數在內存中的地址?
    如何給一個函數指針賦值?
    你是否會定義可變入參函數
    你是否可以區分函數的形參與實參?
    如何定義函數名,以準確的表達函數的用途?
    你是否使用const來修飾函數入參和返回值,以表的特定的含義?
    遞歸如何使用?

    變量
    學習時間:1W
    知識點checklist
    全局變量,局部變量,常量分別保存在內存中的什么地方?
    不同類型的變量,你是否知道其作用域?
    全局變量和局部變量是否可以重名?你是否在這樣做?
    局部變量在函數退出后是否有效,為什么?
    全局變量為什么不允許定義在頭文件中?有何危害?

    鏈接(linux)
    學習時間:1W
    知識點checklist
    鏈接位于編譯過程的那個階段?
    動態鏈接庫和靜態鏈接庫使用時有何區別?
    如何對動態鏈接庫進行動態加載(不用重啟程序而加載鏈接庫)?
    動態鏈接有何優點?
    動態鏈接庫中是否定義了非static的全局變量?你是否知道這是一個非常危險的動作?
    動態庫中的全局變量(非static)和函數(非static)是否可以和上層全局變量和函數重名?重名后會發生什么事情?


    運行時的數據結構(linux)
    學習時間:1W
    知識點checklist
    你知道什么是段的概念嗎?
    可執行程序可以分為幾個段?每個段保存的是什么內容?
    如何查看可執行程序各個段的大小?
    當函數被調用時發生了什么?
    你有沒有試過程序的棧空間最大有多大?程序超過此大小會發生什么?
    你使用的系統的棧是向下生長的,還是向上生長的?

    Include
    學習時間:0.5W
    知識點checklist
    1、如何避免對同一頭文件的多次include?


    聲明
    學習時間:1W
    知識點checklist
    什么是聲明,什么是定義?
    你是否會運用c語言聲明的優先級規則?


    關于復雜度:
    軟件的首要技術使命是管理復雜度。
    優秀程序員的一個特質是將復雜的事情簡單化,而非將簡單的問題復雜化。所以,他們一般會選擇簡單的解決方案。
    極盡機巧,復雜的解決方案,除了將新手搞得暈頭轉向之外,別無他用。
    閱讀優秀程序員的代碼,是一種享受,你很少遇到思維的阻力,你可以盡情的享受簡單之美。
    所以,對難以理解的語言特性,要慎用、少用,最好不用,而以簡單的解決方案替代之。但是,在做這些之前,你必須對這些知識點理解深刻。

    如果你發現有什么錯誤,請和我聯系。
    如果這些知識點你90%以上都不知道,或者理解不深刻——我希望你可以加入DS計劃,共同學習。
    如果這些知識點你90%以上都知道,并且理解深刻——我希望你也可以加入DS計劃,成為知識點專家,對新手進行指導。
    如果你知道的比上面列出的還要多,或者還有你認為非常重要的,建議你也分享出來,對上面列舉的內容進行優化。

    原文地址:http://blog.csdn.net/chgaowei/archive/2009/10/27/4731498.aspx
    DS計劃加入方式:
    1、 方式1 :加入 QQ 群: 93684322 。
    2、 方式2 :加入 CSDN 群組: DS計劃 。 

    一位網友的建議

    對《C方向項目詳細計劃》的一點建議
    作者:陳新
    原文: http://hi.csdn.net/space-1568678-do-thread-id-990.html
    首先自己介紹一下,我已經工作多年,目前半管理半開發,主要使用PHP和C語言,對于C語言有過一定研究,有一些經驗。
    我很少上CSDN,雖然已經注冊了很長時間,今天心血來潮進來看看,就發現了常高偉的的帖子《深入學習C語言知識點checklist——測試你掌握C的程度》,仔細看了一遍,覺得還不錯,這年頭還執著于技術細節的人很少了,可見作者還是下了不少功夫的。
    接著就看到了“讀S計劃”,覺得有點意思,看完之后就有了寫這個建議的沖動,希望對大家有所幫助。

    關于c語言知識點本身,還是挺全面的,如果一個人大部分問題都能詳細解答,說明這個人對C語言的了解還是很不錯的。
    不過我還是有幾點建議:
    1、知識點組織得不是很好,顯得有些凌亂,有些相關知識點被分割到了多個地方,有些不夠全面,從學習的角度來將,不是非常好。
    例如開始就從字符串操作講起,我覺得不是很好。原因是字符串操作只是庫函數,對于c語言的字符串,我們開始只要知道是0結束就夠了,函數后面在慢慢學習。了解字符串函數最好的辦法,就是自己實現這些函數,然后跟源代碼進行比較,找出差距。
    例如宏和Include,不應該分開,而應該作為預處理統一學習。預處理主要包括宏替換、文件包含和條件編譯三部分,另外的一些慢慢再了解就可以了。
    此外,我覺得應該把static、const這些限定詞和變量結合在一起學習,順便把其它限定詞auto、extern、register、 volatile、restrict、inline等整合在一起,從變量的類型(存儲格式)、生命周期、作用域、可視性、存儲分配等各種角度出發進行說明。
    2、有些提問不是很恰當。
    例如sizeof本質上是函數還是宏?因為sizeof既不是函數,也不是宏,這么提問容易讓人產生誤解。要想弄明白sizeof具體是什么,至少要明白編譯的整個過程,弄明白編譯時和運行時的概念。
    例如數組提到的定義int a[10]; a[10] 這個元素是無效的。這種說法并不完全正確,a[10]并非無效,如果真弄明白了具體含義,完全是可以這么使用的(當然一般不推薦)。
    3、學習時間的安排
    像Switch、枚舉之類的,如果有人講解,一天就足夠了。而數組應該和指針放在一起,由于指針是c語言的難點之一,恐怕3周的時間都不一定足夠。
    4、應該把c語言的學習當作當作一個系統,分成多個階段。
    個人覺得分為三個階段比較合適:
    第一階段是c語言本身,主要是類型、操作符、表達式、語法結構、函數、指針、數組、結構等,想完全弄清楚這些其實很不容易。入門可以參照譚浩強的那本教科書,不過這本書只適合了解一下,不深入,而且里面有些地方和例子都不是很好。還是推薦K&R的《The C Programming Language》,最好是英文原版的。這階段可以同時學習《數據結構》,嘗試實現一些鏈表、樹的操作。
    第二階段是結合著實際情況,加深對函數以及相關知識的認識,試著編寫一些小軟件,實現一些小功能。可以和《APUE》一起學習,里面講到的例子都可以自己寫一下。
    第三階段是深入學習編譯原理、操作系統等知識,了解代碼是如何從文本文件一步一步變成可執行文件的,知道棧、堆分別是什么,清楚程序的存儲空間布局,庫函數和系統調用的區別等。這階段可以在某個方面深入下去,編寫一個比較大的軟件,例如一個簡單的網絡程序、數據庫系統或者編譯器等。
    因此知識點中的鏈接、運行時的數據結構、結構體中的內存對齊等和其它知識點放在一起并不是很好,畢竟大部分其它大部分題目都是c語言本身的知識,而這些知識點不少都是要看具體實現的,甚至有些并沒有標準答案。

    另外,還有一些題外話:
    1、現在已經比較少使用c語言開發軟件了,c語言對開發者的要求比較高,c語言不是一天兩天就能掌握的,因此首先要弄清楚自己是否真的對技術感興趣,對技術有種刨根問底的沖動,而且愿意為此花功夫。如果僅僅是想搞搞應用,要快速實現某個功能,而不追求效率,不在乎具體實現方式,最好還是去學習更高級的語言。
    2、 c和c++不是一個語言,所謂c++是c語言的超集也是不正確的,如果當初c++的名稱是d語言之類的,可能就不會有這么多麻煩了。最主要兩者的指導思想是不一樣的,c語言默認其使用者什么都懂,所以將一切的控制都交給開發者自己去完成,語言本身不作太多限制,給開發者最大的自由度。這么做的好處和壞處都是非常明顯的,沒有誰比誰好的問題,只有是否適用的問題。
    3、語言本身只是一個工具,將我們了解的計算機知識發揮、展示出來的工具,但基礎知識遠遠比語言本身更重要。如果認為學好了一門語言,就是所謂的高手了,那是不切合實際的。當然語言本身也需要我們花費很大精力,畢竟掌握好一個工具,更能讓我們的工作事半功倍。


    摘自:http://topic.csdn.net/u/20091027/22/0573CFB5-F1BF-4CF2-8E60-13D907301A8E.html

    posted @ 2009-10-31 13:10 石頭@ 閱讀(569) | 評論 (0)編輯 收藏

    看看吧! 朋友。


    成功經驗寶典100則
    1、王宗立說:每天早上游泳(輸入正面潛意識)是他成為億萬富豪的關鍵。在游泳過程中,輸入正面潛意識,使其每天都保持巔峰狀態。
    2、最重要的是要養成習慣,立即行動。感動之后是行動。一點總比沒有好,晚做總比不做好。
    3、 要養成運動的習慣,要養成早起的習慣。運動能激發無限的魅力,會使一個人感覺起來非常自信。所以我要自己保持持續的運動狀態。讓自己一早起來就很巔峰的狀 態。很多情況是越文明,生活越糜爛。而你看王永慶,臺灣的經營之神,雖然年齡高達86歲,但還是每天5點半起床,跑5000公尺,多年來一直堅持。朝氣 ——POWER.能量就是魅力,氣宇非凡。早起,不要為自己找理由,什么我沒休息夠,我昨天好累啊,等等。
    4、僅僅知道還不夠,關鍵是要不斷地訓練。訓既是教育,練既是練習。
    5、學校不教兩件事情,一是不教談戀愛,怎樣找個好老婆怎樣嫁個好老公。二是學校不教怎樣**,學校給人的教育是追求金錢意味著罪惡,人為財死,鳥為食亡,財富是萬惡之源。
    6、成功者與失敗者的差別在于時間管理,運用時間的方法。
    7、你可以主宰你自己的命運!!!下定決心爭取過自己想要的生活。清楚自己的生活目的。你需要擁有自己的夢想。
    一 部電影,《楚門秀》,楚門伯班(金凱瑞飾)老是覺得他一直受到監視。他沒想到這竟然是真的。從他呱呱落地開始的三十年來,楚門伯班就是史上播映最久、最受 歡迎的記錄片肥皂劇的主角,他居住的理想小鎮海景鎮居然是一個龐大的攝影棚,而他的親朋好友和他每天碰到的人全都是職業演員。他生命中的一舉一動分秒都曝 露在隱藏在各處的攝影鏡頭面前。這就是「楚門的世界」,全球上億觀眾都注意著他的一舉一動,而他自己卻不自知。
    然后經過三十年的渾噩生活后,楚門 終于感到他的生活有點不對勁,當他發現他就像是活在玻璃罐里的蝴蝶時,他決定要不計代價地逃離海景鎮。但是他必須面對「楚門的世界」的創始人、制作人和導 演克里斯托,并且克服他內心最大的恐懼,才能突破藩籬,獲得自由他在內心對自己說,NO! I DONT WANT!(不!我不要過這種生活,我不要過這種受別人操縱的生活!)王宗立借這個例子是想說明,一個人的命運是沒有人能夠操縱的,只要他下定決心,而且 用生命去爭取,他就可以去爭取他想要的東西,過他想要的生活。你也有一合錄影帶,1天24小時,記錄你一生,你的導演是誰呢,你是也在過一種別人操縱的生 活呢?你的生活是否是在于達成別人的目的的一種工具而已呢,而不是在過你想要的生活的做對的事情,起而行動,下定決心,用生命去爭取!
    你滿不滿意你自己的劇本,你敢不敢夢想5年后的你?
    亞洲首富孫正義有句名言——最初所擁有的只是夢想和毫無根據的自信而已,但是所有的一切都從這里開始。
    8、銷售是世界上最賺錢的工作。
    王宗立,21歲,財富達300億,選擇業務工作。
    這個世界上收入最高的工作就是業務。他說:說服任何人,幫我做任何事。
    銷售,什么是銷售,就是說明、教育、幫助別人作決定。需要三大能力:開發客戶,網羅干部,締結業務。
    21歲,16個月的時間賺了300萬,然后4個月賠光22歲賺了700萬,半年賠光,銷售房子,幫助別人做決定。人喜歡別人幫他做決定。不管是選衣服,交異性朋友還是選吃什么東西,你都希望別人替你做決定。
    一個女人如果有兩個男朋友,她該選擇哪一個?如果你是其中之一,你要幫她下決定,你該如何說服她要她選擇你?
    二次創業失敗,失敗了沒關系,重要的是學到了東西沒有。成功就是交學費,早交晚交而已。越早交就交得越少。
    在人生中必須得有一個自己又愛又敬又怕的人。他的這個又愛又敬又怕的人是他父親。
    我賠過近千萬的錢,最重要的教訓——千萬別隨便轉換跑道。我見過太多的轉型(轉行)失敗的人。擴張是另一種形態的轉型(轉行)。
    9、人要成功需有三本——本人,本錢,本事。本人是指要親自去了解你所做的業務(產品和服務,甚至具體到每一個細節),本錢就是要有資本,本事是指你要有你的核心專長,核心的競爭力。
    一個人要成功,要有很多的貴人。 8位數字與9位數字相差一萬倍。
    億萬富翁靠經營管理,靠大智慧,靠忍。
    老板的大忌:全天下的男人都會犯下的錯誤是色,英雄難過美人關。很多人有錢到一半,就會享受,開始酒池肉林,百花叢中有花就堪折,這樣很快就會財富消散,因為賺錢不是加減法而是乘除法,來得快去得也會更快。所以做領導還要有憂患意識。
    10、人生不在于機會而在于選擇。人生的命運就取決于你一剎那所做的決定。
    我做了哪些選擇,以致于有我輝煌的成就——23歲月入百萬,26歲成為億萬富翁,28歲收購成功雜志,兩岸三地不同形態的業務?首先要選個好的工作和職業。
    (1)、 寧為牛后,不為雞首。1993年24歲時,日子非常不錯,在忠孝東路有900平米的辦公樓,銷售房地產,遇到事業瓶頸,因為無法copy銷售模式,好象個 人打拼一樣,沒有未來愿景。而會**的人都有一套模式。象麥當勞,只要按照他的這套模式,copy一下,就能賺很多很多的錢,或者有一套模式讓下屬 ALONG依循就可以賺錢了。必須要有一個KNOW HOW歷史學家分析說,日本之所以會成功是因為明治維新和大化革新。所以學會**比現在**更重要。
    (2)、 底子比面子更重要,收入比頭銜更重要,實務經驗比虛名更重要,識時務者為俊杰。看得到的結果比幻想的未來更重要。幻想的未來是假的。怎樣銷售?說服?怎樣 賣東西?賣咖啡是在賣感覺,賣那種走在咖啡廳外面就問到濃濃的香味,進去之后看到那些擺設和文化氣息,賣咖啡是在賣文化。說的是星巴克咖啡廳。
    其 次要找個好的伴侶。他說他娶了一個好老婆。你要做應該做的事而不是你喜歡做的事情。我老婆很會欣賞我的優點,很會崇拜我看你的眼神就讓你找到自信。 演講后會很正面的評價我沒有人不喜歡贊美,人的肯定來自于很多人的肯定,你想要別人贊美你你也要去贊美別人。我老婆的優點就是會鼓勵、贊美、肯定和欣賞我 同時她是節省的女人。失敗的婚姻會讓人處于低潮,所以選老婆要選能助夫蔭子的人。不要找一個勉強的老婆(老公),這種婚姻是不會幸福的,他(或者她)絕對 會帶給你人生的負面的東西。你所愛的人,你要感覺到他(她)也很愛你。她愛你的程度甚于你或至少與你相當。你也許只是so so喜歡她,她卻要very much喜歡你,不要找自己一相情愿喜歡的女人,否則你不會高枕無憂。
    再次,關鍵是要激發潛能,忠于原主。他自己的例子。95年,他的原來的老 板,議員落選,新聞傳媒的消息,造成很多負面的影響,屬下的61家中60家都眾叛親離,只有王宗立他沒有,因為他說他實在找不出更好的理由離開,經營狀況 很不錯, 使那個老板很感動,要他立即承諾如果能馬上開出12張支票共計 7.2億的單子,將給非常優厚的利潤,……
    這樣呢,他說人生就是算和賭,他覺得自己算準了,雖然心理也不是非常有把握,但覺得非常值得賭一把,這樣他的財富一下由千萬富翁變成億萬富翁。那段時間的壓力非常大,但是,要創造壓力,享受壓力。這樣才能成功!
    11、均衡式的發展。訓練很貴,不訓練更貴。
    12、 改變命運很重要的三個關鍵。其中之一是選擇好的老師非常重要。眾人生死全看你,力挽狂瀾只一人。要想人前顯貴,必先人后受罪。霸王別姬,甘之如飴。少年得 志大不幸。樂極生悲。5000年來的魔咒。驕傲就會停止學習,要高而不危。每個人都有4張A,只是有些人幸運早翻到而已,而道路很漫長,要時常停下來思 考,不要跨太大的步驟,地雷。他作過3個重要的決策。良師有很多包括負面的,要從負面的東西看到學習到,從失敗的人的經歷里也能學習到很多東西,意見值多 少錢?不可限量。衷心的勸告。人不會永遠都有好運氣。
    齊恒公,管仲,好酒會使寡人亡國嗎,好色會使寡人亡國嗎,好郊游會使寡人亡國嗎,管仲說都不會,只有遠賢臣近小人才會使你亡國。
    13、要心懷一顆感恩的心。
    14、怎么系統運用潛意識?馬修史維的方法。
    15、 歐那西斯的方法。看到任何人,經歷任何事,每天晚上用本子記下。以決定下一次怎樣花時間在他身上。這個不象學校教的有教無類,不能以貌取人,而真理是 say no,懂得拒絕。待人處世一定要因人而異,要學會拒絕否則會浪費時間,要交你應該交的朋友而不是你喜歡交的朋友。
    歐那西斯說,要成功需要盟友,要非常大的成功就需要敵人,戰友。康熙敬三碗酒,第三杯是向他的敵人敬的。他說如果沒有這些人,就不會成就的大事業。所以說益友可能是競爭對手,要學會向競爭對手學習很多的東西。
    16、功課不重要,一定要靈活。因為交際手腕高的人會更成功。
    17、 如何分辨朋友,選擇朋友?選擇戰友,選擇敵人?如何選擇環境,創造環境?他講了他的三個女朋友。第一個非常愛玩,第二個非常情緒化,多愁善感,負面的情緒 非常多的人。第三個女朋友是說相信他會大富大貴,有非凡前途的人。崇拜,鼓勵,相信他的人。我相信我就能看見18、會學習比肯學習愿意學習來得更重要。前 車之鑒,后車之履。要試著去教別人你想要學的東西。
    19、每一個決定不是離成功越來越遠就是離成功越來越近。思想決定態度,態度決定語言,語言決定行為,行為養成習慣,習慣形成性格,性格決定命運。
    20、苦并不可怕,怕就怕苦得沒有代價。
    21、如何做領導統御?科學家是把簡單的東西復雜化,企業家是把復雜的東西簡單化。管理團隊就是連鎖人,大量copy,東方不敗的葵花寶典,木蘭詩背下來,銷售房地產的腳本交戰手冊,實戰手冊。
    領導統御的秘訣——四句話,開發,復制,管理,交換。
    開發客戶,公司來做,教業務員去做。復制:讓每一個人都會做。管理:統一的去管理,團隊成功。一個企業里有三種人,攻城者,開疆辟域。守城者,守天下。教練者,教育部長,復制的工作。管理就是整合不同類型的人。交換就是資源共享,集體學習,絕不否認每一個個體的價值。
    22、如何選項目?要看適合不適合你。你的核心專長,核心競爭力是什么?
    怎樣融資?借錢?銀行的錢是借給有錢的人而不是需要錢的人。天上下雨地上滑,自己跌倒自己爬。所以你要塑造自己被利用的價值,你的可被利用的價值是什么?保——呆人。
    23、 如何管理好人才?識才,留才,養才,用才。識才——不要找一個完美無缺的人,沒有這種人。留才——心靜而后定,心定而后安,心安而后求知求財。養才——舍 得對你的員工投資,投資!把員工當作你的資產。員工是最寶貴的資產,人是無價之寶。外國企業平均花3-5%去培訓他的員工,而中國的企業平均只花 0.03 -0.05%用來培訓員工。用才——就是要把人才擺在適當的位置。
    24、不管做什么都要有銷售通路。
    25、任何企業都有窮人,成功的企業家不應該停止不前。
    26、行善與行孝——這是人生的兩件不能等待的事情。
    27、為什么要成功比怎樣成功更重要!!!
    28、世界上沒有笨人,笨人都是罵出來的。所以一個贊美鼓勵的家庭很重要。
    如何選擇環境?一等人創造環境,二等人跟隨環境,三等人抱怨環境。要輸入正面積極的關于環境的潛意識信息。所有與我有關的一切都必將欣欣向榮,不論白天與夜晚,所有與我有關的一切都必將欣欣向榮。用潛意識營造一個積極的環境,一個特別的know how.
    每一天都有86400秒,如果你把每天的86400秒換算成86400塊錢,如果沒有用掉的話,會蒸發掉的,你會不會珍惜這些時間?王永慶一分鐘賺6萬塊。年齡不能代表一切。激發潛能既是有效運用時間的最佳方法。安東尼羅賓說你每分每秒都要做最有生產力的事情。
    29、我使用人才的方法是,他有10分才能,不會給他7分的活,而要相反,這樣才能激發他的潛能。
    30、一日之計在于昨晚。做最重要的事情。所謂的最重要的事情是指非自己親自出馬不可的事情,要思考3次,不要去做那些僅僅是因為自己喜歡做的事情。每天晚上安排6件重要的事情。締造高度的壓力。辛苦不可怕,關鍵是辛苦要值得。要創造壓力并享受壓力。
    31、每周一星。稀有性,不可替代性。
    32、學習催眠最重要的方法是as if(假裝)。
    33、 一個人與自己人性對抗的力量越強就越能取得成功。晚起床,熬夜,吃宵夜,吸煙等都是壞習慣。一定要養成運動的好習慣。慢跑或游泳都很好。會讓你兩眼炯炯有 神。使你每天都是熱情效益有力量的一天。每天起床之后對自己說:生命多美好暗示性的語言:我喜歡健康,我喜歡保持優美的身材,我知道我追求成功……34、 當你有足夠的理由,你就會作出不可思議的事情。每個人都要自問:我現在為了自己成功的人生,可以作出什么樣的決定?
    35、人才最難找!
    36、四到——知道、悟到、做到、得到。
    37、要做那些危險而享受的事情。紅色代表賺錢、競爭、占有欲和掌控性。蘭色代表人群、party、放松等等。綠色代表證據、數據、精確性。黃色代表使命感、義工、幫助人。
    38、學習——為自己,為身邊的人,為千千萬萬。
    39、你為什么能賺10萬美金?原因有三個。第一是你的習慣讓你的收入沒辦法提升。包括決策的習慣、時間管理的習慣等等。第二是你所交的朋友,要交比你強的人。第三提升你核心圈的人的品質如你管理的團隊的品質。
    40、知道不夠多,復習很重要。學習的秘訣在于所謂的六圈哲學:100%——50%——25%——12%——6%——3%,任何人不能成功是因為沒人跟100%的人學習。所以我們要盡量的跟100%的人學習,跟最優秀的學習。接近那個100%的人。
    41、臺基集團的企業文化——孝順,感恩,存錢,競爭。早會,演講競賽,每日一星。歐那西斯說一個人要獲得巨大的成功必須有敵人,需要競爭才行。
    42、成功的法則是拿來記住的。
    43、教育訓練者是使命傳播者。
    44、 人不可能永遠處在顛峰狀態,那么怎樣克服低潮沮喪和消極的心態呢?當你遇到挑戰時,你要想你是在高速飛行,從而才會遇到不可或缺的空氣的阻力,從南京到北 京,你盡可以走路慢悠悠的走去,那樣不會遇到象飛機高速飛行一樣遇到的阻力,但是你的速度很慢很慢。恐怕要花半年時間才能到達目的地。
    45、不遭人忌是庸才。
    46、 好的環境是鼓風爐。POWER能量。當你走出去,你會遇到挑戰,你會遇到拒絕,會有潑冷水的,雖然你開始還象720度的燒得通紅的木炭,但一遇到冷水又會 逐漸降溫。只有你內心的力量使你自己變成一個鼓風爐,你才又會慢慢升溫到100度,200度,300度,500度,最后又達到甚至750度的火紅的木炭。 你應該如何作到這一點呢???你要一遇到這些挑戰,一遇到沮喪的時候,你要馬上在心中說,I AM& nbspFIRE ,你犧牲了自己,照亮了別人。你想別人贊美,就要贊美別人,你想別人鼓勵,就要鼓勵別人,你想別人幫助,就幫助別人。
    47、心理學家的實驗。一只 狗,被窮追,不斷的被追,直到倒在地上,嘴冒白沫,然后抽取其血液,有疲勞毒素在里面,用這些毒素注射在一只剛吃飽的活蹦亂跳的狼狗身上,立即要昏昏欲 睡,為什么?因為血液總是會疲勞的。人有兩個器官是永遠不會痛的,一個是頭發和指甲另一個是肝臟,如果肝臟會痛這人肯定完了。
    48、惟有堅持百忍,才能無所不能。
    49、 天下有兩難,登天難求人更難;世間有兩苦,黃連苦,貧窮更苦;世上有兩險,江湖險人心更險。所以要做最壞的打算。水能載舟亦能覆舟。一切都要能看得開,只 有你自己不會背叛你自己,所以要投資你自己。你要愛你自己,要愛跟你有血緣關系的親人。世上還有兩薄:春冰薄,人情更保所以要塑造自己永不被替代的價值, 永遠被利用的價值。不要怪別人背叛你,你要怪自己沒有創造自己被利用的環境。但你真的要堅持百忍才能立于不敗之地,才能無所不能……處于低潮時,我會想, 如果是王永慶他會怎么做?知其難,忍其苦,測其險,耐其薄,可處世也。
    50、感恩,精進,嚴謹。
    51、記住別人任何的壓力都不會壓跨你,只有自己的壓力會毀滅你自己。你要自己去調試自己的心靈。方法中,音樂電影的方法對于調試的幫助很大。用音樂治療自己的痛苦。
    52、人一定要克服自己的沮喪。
    53、沒有不景氣,只有不爭氣。巧克力精神——巧妙地克服阻力。
    54、OPT與OPM——運用別人的時間與金錢。
    55、 王宗立的座右銘有三條。1、在生命的歷程中要告訴自己,軟弱的是時候要堅強,恐懼的是時候要勇敢,迷惑的時候要明智,抓不住的時候就要放手,真正的勝利是 活在自己的心中。2、冷靜地面對一切問題,積極不斷地超越自我,惜福永不消極怠惰,活在當下就是最美。3、上帝賜給我鎮定和沉著,讓我接受不可改變的事 情;上帝賜給我勇氣和力量,讓我改變我有能力改變的事情;上帝賜給我智慧,讓我去分辨哪些事情是我有能力改變的,哪些事情是我無法改變的。
    56、為什么要冷靜?做業務很辛苦的,要很善于處理危機的。
    57、做業務的三大法寶——走出去,說出來,把錢收回來。
    58、可憐之人必有可恨之處。
    59、什么是大智慧,就是怎樣運用心靈的智慧,心靈的力量。哀莫大于心死。大部分人都會很沮喪。
    60、寒冰不能斷流水,枯木也能再逢春。
    61、要善于運用心靈的力量。有了它,跌倒了再爬起來,失敗了再成功。
    62、羅伯特清崎的投資理財,四象限理論。E,S,B,I.窮爸爸——公家機關,最講排場,請最多人,花最多的錢,講氣派。富爸爸——企業,私人企業。企業是花最少的錢要創造最大的效益,沒有獲利的企業是最大的罪惡。因為沒有獲利的企業會造成很多問題家庭。
    63、并不是讀書讀得很多就會很有錢。
    64、 過安定的生活有兩種辦法一種是在30歲之前賺了足夠的錢,比如說30個億,然后把這些錢放在銀行,投資基金等。第二種是永遠不要冒險,安心做一個雇員, 有職業保障但是真的有職業保障嗎?沒有!!!那些所謂的有職業保障的人只不過是在做錢的黑奴。你是否一輩子在為錢做奴隸。為錢而工作?
    65、你是為生活而工作還是為工作而生活?如果你認為你的工作是享受,那么你就是在為工作而生活,否則的話,你是在為生活而工作。你要為了生活而工作?NO!
    66、你所擁有的就是最好的。只要是你的就是最好的。
    67、S象限里是自由職業者。是做業務,賺獎金收入的人。剛開始時建立通路。
    王想建立的事業。把消費者變成銷售者,把銷售者變成領導者,管理者。如果不會銷售就不會賺錢。
    68、怎樣學會銷售?走出去,說出來,把錢收回來。
    69、銷售的重點是開發客戶,締結業務。這就需要1、專業知識,關于產品和服務的知識。2、要知道顧客購買我的產品的至少5大理由?把這些理由背得很熟很熟。3、要提供證據,提供見證者。4、要知道CLOSE的技巧。敢于幫助別人下決定。
    70、客戶說NO是很正常的,業務最大的困難在于膽量,接下來的開場白,產品介紹等等等。萬般草木皆兵器,資源,看到人在走路就如同錢在向你招手。
    71、B,利用別人的時間來幫你賺錢。人有四種,消費者——銷售者——管理者——領導者。銷售者是說明教育幫助顧客下決定的人。領導者是解說者。
    72、怎樣說服顧客,當你把產品形容得并使客戶相信使得客戶認為價值超過價格時,就成交了。價值超過價格就不貴。
    73、要立大志才能做大事。領導者就是說服,說明,教育,幫助別人下決定的人。
    74、 I象限的人,是投資者資本家。利用錢來賺錢的人。投資致富法則,沃倫巴菲特的秘訣——第一個法則,絕對不能賠錢。就是說不能在股票價格低于你當初的買入價 時拋出。一定要等最好的時機。逆向思考法則。沒有投資智慧,只有理財EQ.那么怎么作到處變不驚?少賠就好。第二條,絕對不要忘記第一個法則。切記切記切 記!
    75、世界上最恐怖的力量是復利。世界上沒有聰明不聰明之分,只有懂與不懂。
    76、如何增加人生效率?
    77、一定不能滿足于現狀,要巨觀而不是微觀。
    78、老板發現員工剽竊了他的智慧,資產等時怎么辦?他不要想不開,你也可以挖別的企業的人才。網羅別人的員工,學習別人的智慧。創造你公司的不可被替代性。對于夫妻來說也是如此,要創造你在你老婆(老公)心目中不可被替代性。而不是一雙玉臂錢人枕,半點朱唇萬人嘗。
    79、人生最痛苦的事情莫過于開創和從低潮走向高潮。調整的方法是不要鉆牛角尖,而是用另外一個來代替。用催眠錄音帶,馬修史維的方法。
    80、放松,放松,毫不批判的接受成功者的指令。
    81、 時間管理,成功者成功的原因之一就是很會管理時間。把事情分為四類,A——很重要又很急的,B——很重要但不很急,如運動,健康檢查,看書學習,上課等, C——很急但不重要,因人而異,如女朋友要我下班接她等等。這些也許可以要別人去替你做。D——既不著急也不重要。關鍵點是如何區分B和C類的事情。急或 重要是針對目標和價值觀而言的。把第二天自己要做的事情6大項,在每晚做好計劃。王宗立做中層管理者一般有以下6大件事情:1、召集員工激勵員工。2、邀 約一組客戶,去拜訪說服,如果沒有至少要去做問卷調查一組CASE.3、幫助我的干部CLOSE一個客戶。4、幫助我的干部救一個客戶。救要退貨的。5、 有些情緒不好的員工要鼓勵激發他。6、在公司親自演示一個產品說明會。培訓示范作用。身系公司生死一線之間。
    82、如果一天做6件重要的事,那么一個月就能做180件重要的事情,一年能做2190件事情,你能不成功嗎?
    83、養成兩個習慣。準備好兩個小本子,一個專門用于記那些你當天你遇到的人,和事情。另一個用于記你明天要做的6件事情。
    84、一點總比沒有好,晚做總比不做好。要做最重要的事情。
    85、 關于時間管理的,是安東尼羅賓的老師亞伯拉罕的課程。人有三種時間:Focus day焦點日,專門用于處理與實現最重要的目標有關的事情。在焦點日不做任何事除了最重要的事情之外。Buffer day:準備日:不怕沒有機會,就怕沒有準備。準備日是比如說去上課,去培訓,去交一些朋友。等等。不是去締結業務去收錢,但是去做之前的準備工作。 Free& nbspday:自由日,休息,與家人在一起。獎勵,平衡等。
    86、人有四種,人物,人才,人手,人渣。
    87、全天下最長的距離是別人的錢包到你的錢包的距離。
    88、馬修史維:只要是正面的,有力量的對你有幫助的,那么DO IT NOW!
    89、行善行孝感恩這三件事情都不能等,不然就沒有機會了。
    90、當別人潑你冷水時,輕視你,嘲笑你,侮辱你,打擊你,為難你時,你不但不要罵他,責怪他,相反你要感謝他,因為他不僅在你沮喪時,在你的油箱里加滿了油,讓你一路勇往直前沖到底。
    91、凡事沒有任何意義,除非你賦予它定義。
    92、人人都不是在推銷產品,而是在推銷自己。
    93、投資大腦,回報率最高。
    94、完美主義會殺人。不要等準備好了再說,差不多就要去做。完美主義會打斷習慣。凡事最怕開頭,有了開頭就會繼續,有繼續就會養成習慣,習慣就會成自然,自然就是美。
    95、相信就會看見。一般人是看見了才相信。所以信念很重要。
    96、人無法成功的原因只有兩個:懶惰和懼怕。人有三大最怕:火,高處往下跳,在公眾面前演講。
    97、不要自己掙不到錢,就希望別人也破產。要創造好的環境,要做正面的暗示:無論白天與夜晚,所有與我有關的一切都必將欣欣向榮。
    98、一等人創造環境,二等人跟隨環境,三等人抱怨環境。
    99、如果你有足夠的理由,當你遇到令你興奮得發抖的機會,你體內的火山就會自動爆發,你心靈的巨人就會被喚醒。
    100、凡事皆正面,能量永不減。

    posted @ 2009-08-24 21:45 石頭@ 閱讀(255) | 評論 (0)編輯 收藏

    經典開源項目集

    操作系統

    Linux

    項目主頁:http://www.linux.org/

    數據庫

    MySQL

    項目主頁:http://www.mysql.org/

    HSQLDB(Hypersonic SQL)

    項目主頁:http://hsqldb.sourceforge.net/

    Apache Derby

    項目主頁:http://db.apache.org/derby/

    Excel JDBC Driver

    項目主頁:http://nilostep.com

    Web開發框架

    WebWork

    WebWork是由OpenSymphony組織開發的,致力于組件化和代碼重用的拉出式MVC模式J2EE Web框架。

    項目主頁:http://opensymphony.com/webwork/

    Struts

    Struts是一個基于Sun J2EE平臺的MVC框架,主要是采用Servlet和JSP技術來實現的。

    項目主頁:http://struts.apache.org/

    Spring MVC

    Spring MVC是結構最清晰的MVC Model 2實現

    項目主頁:http://www.springframework.org/

    EasyJWeb

    EasyJWeb是基于java技術,應用于WEB應用程序快速開發的MVC框架,框架設計構思來源于國內眾多項目實踐,框架充分借簽了當前主要流 行的開源Web框架(Struts、JSF、Tapestry 、Webwork),吸取了其優點及精華,利用Velocity作為模板頁面引擎,是一個實現了頁面及代碼完全分離的MVC開發框架。是一個能實現中小型 Web應用系統快速開發的簡易Web框架。

    項目主頁:http://www.easyjf.com/easyjweb/

    JavaServer(TM) Faces(JSF)

    JavaServer(TM) Faces技術簡化了JavaServer應用程序用戶界面的開發.各種技術水平的開發者都能夠快速創建web應用程序通過在一個頁面中裝配一些可重復使 用UI組件;并可把這些組件與應用程序的數據源連接起來;也可把客戶端產生的事件與服務端事件處理者連接起來.這個項目是Sun對JSF技術規范的最完整 實現。

    項目主頁:https://javaserverfaces.dev.java.net/

    OpenBlueLab

    OpenBlueLab是一個用于構建Web2.0 Portal系統的快速開發框架。其主頁就是采用該框架開發的一個Demo。Portal布局可以通過UI進行配置。Widget將自動組裝,在運行期不 需要編寫任何數據庫交互代碼就能夠使它們自動實現數據感知。基于Ajax與HTML的form也將從XML widget定義自動構建。XML widget定義可以從描述信息系統設計的UML模型快速生成。這個框架讓你只需關注信息系統的設計,而form和portal的系統架構將自動生成。

    項目主頁:http://www.openbluelab.org/

    JSP標簽

    Displytag

    項目主頁:http://displaytag.sourceforge.net/11/

    AJAX框架

    DWR

    項目主頁:http://www.getahead.ltd.uk/dwr/

    應用服務器

    Jakarta Tomcat

    項目主頁:http://jakarta.apache.org/tomcat/index.html

    JBoss

    項目主頁:http://www.jboss.org

    GlassFish

    項目主頁:https://glassfish.dev.java.net/

    Caucho Resin

    項目主頁:http://www.caucho.com/

    Java開發工具

    Eclipse

    項目主頁:http://www.eclipse.org

    NetBeans

    項目主頁:http://www.netbeans.org

    EasyEclipse

    項目主頁:http://www.easyeclipse.org/

    Jedit

    項目主頁:http://www.jedit.org/

    UML建模工具

    ArgoUML

    項目主頁:http://argouml.tigris.org/

    Alma

    項目主頁:http://www.memoire.com/guillaume-desnoix/alma/

    源碼管理工具

    SVNKit

    項目主頁:http://svnkit.com/

    JCVS

    項目主頁:http://www.jcvs.org/

    JSVN

    項目主頁:http://www.alternatecomputing.com/jsvn/index.php3

    團隊協作工具

    Mindquarry

    項目主頁:http://www.mindquarry.com/

    Java Enterprise TeamWork

    項目主頁:http://jeteam.sourceforge.net/

    Coefficient

    項目主頁:http://coefficient.sourceforge.net/

    Open-Xchange

    項目主頁:http://mirror.open-xchange.org/ox/EN/community/

    項目管理工具

    Memoranda

    項目主頁:http://memoranda.sourceforge.net/

    Open Workbench

    項目主頁:http://www.openworkbench.org/

    Onepoint Project

    項目主頁:http://www.onepoint.at/?action=setLanguage&language=en

    OpenProj

    項目主頁:http://sourceforge.net/projects/openproj

    Project

    項目主頁:http://www.project.net/

    發布打包工具

    JSmooth

    項目主頁:http://jsmooth.sourceforge.net/

    Launch4j

    項目主頁:http://launch4j.sourceforge.net

    VAInstall

    項目主頁:http://vainstall.sourceforge.net/


    摘自:http://hi.baidu.com/computertao/blog/item/b06285335a45f8fc1a4cff6d.html

    posted @ 2009-08-21 19:21 石頭@ 閱讀(1118) | 評論 (0)編輯 收藏

    做java最起碼掌握的十項技術

    一個Java程序員應該掌握的10項技能

    1、語法:必須比較熟悉,在寫代碼的時候IDE的編輯器對某一行報錯應該能夠根據報錯信息知道是什么樣的語法錯誤并且知道任何修正。
    2、命令:必須熟悉JDK帶的一些常用命令及其常用選項,命令至少需要熟悉:appletviewer、 HtmlConverter、jar、 java、javac、javadoc、javap、javaw、native2ascii、serialver,如果這些命令你沒有全部使用過,那么你 對java實際上還很不了解。
    3、工具:必須至少熟練使用一種IDE的開發工具,例如Eclipse、Netbeans、JBuilder、Jdeveloper、IDEA、JCreator或者Workshop,包括進行工程管理、常用選項的設置、插件的安裝配置以及進行調試。
    4、API:Java的核心API是非常龐大的,但是有一些內容筆者認為是必須熟悉的,否則不可能熟練的運用Java,包括:
    ◆java.lang包下的80%以上的類的功能的靈活運用。
    ◆java.util包下的80%以上的類的靈活運用,特別是集合類體系、規則表達式、zip、以及時間、隨機數、屬性、資源和Timer.
    ◆java.io包下的60%以上的類的使用,理解IO體系的基于管道模型的設計思路以及常用IO類的特性和使用場合。
    ◆java.math包下的100%的內容。
    ◆java.net包下的60%以上的內容,對各個類的功能比較熟悉。
    ◆java.text包下的60%以上的內容,特別是各種格式化類。
    ◆熟練運用JDBC. 8)、java.security包下40%以上的內容,如果對于安全沒有接觸的話根本就不可能掌握java.
    ◆AWT的基本內容,包括各種組件事件、監聽器、布局管理器、常用組件、打印。
    ◆Swing的基本內容,和AWT的要求類似。
    ◆XML處理,熟悉SAX、DOM以及JDOM的優缺點并且能夠使用其中的一種完成XML的解析及內容處理。
    5、測試:必須熟悉使用junit編寫測試用例完成代碼的自動測試。
    6、管理:必須熟悉使用ant完成工程管理的常用任務,例如工程編譯、生成javadoc、生成jar、版本控制、自動測試。
    7、排錯:應該可以根據異常信息比較快速的定位問題的原因和大致位置。
    8、思想:必須掌握OOP的主要要求,這樣使用Java開發的系統才能是真正的Java系統。
    9、規范:編寫的代碼必須符合流行的編碼規范,例如類名首字母大寫,成員和方法名首字母小寫,方法名的第一個單詞一般是動詞,包名全部小寫等,這樣程序的可讀性才比較好。
    10、博學:掌握J2EE 、Oracle 、WebLogic、Jboss、Spring、Struts、Hibernate 等流行技術,掌握軟件架構設計思想、搜索引擎優化、緩存系統設計、網站負載均衡、系統性能調優等實用技術。
    本文摘自:http://hi.baidu.com/st_sen/blog/item/85333209ae157e2d6b60fbc9.html

    posted @ 2009-08-09 18:16 石頭@ 閱讀(1182) | 評論 (4)編輯 收藏

    很有哲理的一些話!

    淚的存在,是為了證明悲傷不是一場幻覺。

      兩人相愛時,渴求無限甜蜜的吻,但為何在爭吵時,卻要用接吻的嘴互相傷害呢?    

      愛其實就像打計程車。第一,不像公共汽車,只需等待就會自動來到你的面前,而需要你先向 它招手才停;第二,如果你碰到的是空車,那就是你的幸運,但往往車上已經有人了。這時你只能搭便車,只有先到的乘客下了車后,才能去你想去的地方;第三, 走了多少距離就要付出多少代價。    

      當你認為被拋棄的時候,受損失的其實是對方;因為他失去了一個真正喜歡的人,而你只不過少了一個不愛你的人。 

      要做的事情總找得出時間和機會,不要做的事情總找得出借口。    

      令人不能自拔的,除了牙齒還有愛情.    

      你以為最酸的感覺是吃醋嗎?不是的,最酸溜溜的感覺是沒權吃醋,根本就輪不到你吃醋,那就是最酸最酸的。    

      青春有限,可以驕傲的時候,盡管驕傲吧。有一天,當你死心塌地地愛上一個人的時候,你也許無法在驕傲。    

      寵和愛是不同的兩件事,寵可以沒有交流,而愛則不能。    

      一個人有生就有死,但只要你活著,就要以最好的方式活下去。    

      思戀一個人的滋味就像喝了一大杯冰水,然后用很長很長的時間流成熱淚。    

      幸福像掉到沙發下面的一粒紐扣-----你專心找,怎么也找不到,等你淡忘了,它自己就滾出來了。    

      快樂就像香水,灑在別人身上的同時,自己也會沾上一點。    

      一只腳踩在紫羅蘭上它卻將香味留在了你的腳上------這就叫寬容。    

      離開我就別安慰我,要知道每一次縫補,那顆心都會遭遇穿刺的痛。    

      人生好比一只杯子,杯中的水滿了就得施一半給人,待杯里又滿了,再施一半。只有不斷地進,不斷地出,這只杯子里才會是活水,才會有價值。    

      人生試題一共有四道題目:學業.事業.婚姻.家庭.平均分高才能及格,切莫花太多的時間和精力在任一題目上。    

      因為懂得,所以慈悲。    

      愛情就像一雙襪子,越是瞧起來不順眼的襪子,越有可能永遠陪在你身邊,越是喜歡的漂亮襪子經常會少一只.    

      微小的幸福就在身邊,容易滿足就是天堂。    

      只有向后才能理解生活;但要生活好,則必須向前看。    

      對于你來說,我的出現只是你生命中的100+1=101;但對于我來說,你的出現在我的生命中卻是0+1=1的算式。    

      世界上沒有不傷人心的感情,或多或少,或大或小,它都會在你的靈魂上留下傷痕。以傷痕為代價換得感情的喜悅,以感情的喜悅作為傷痕的回報。    

      沒有人因水的平淡而厭倦飲水,也沒有人因生活的平淡而摒棄生活。    

      一片空白中兩條細細的直線,它們從遙遠的兩頭隱隱現出,急急忙忙地在彼此的身體上留下一個點,然后再次展向無限制的遠方,一去不復返。    

      愛情的開始可能是友誼,可能是利用,可能是欺騙,也可能是需要或寂寞,甚至可能是報復,可那又有什么關系呢?只要最后的結果是演變成了愛情。    

      傷害你的人不是比你強大就是比你弱小。如果他比你弱小,寬恕他;如果他比你強大,寬恕自己。     

      我能從一千個從我身邊經過的人中聽出你的腳步,因為那999個人的腳是踏在地上,只有你的腳步聲是踏在我的心上。    

      我喜歡你,可是我不敢說;我怕說了,我會死去;我不怕死,但是我怕死了以后,再也沒有人會像我一樣喜歡你。    

      得不到你所愛的,就愛你所得的。    

      眼淚的溫度有530℃,只是因為外面的世界太冷,流出來的時候才會降到53℃。    

    愛一個人就是在撥通電話時忽然不知道說什么好,原來只是想聽聽那熟悉的聲音,真正想撥通的只是自己心底的一根弦

    posted @ 2009-08-05 17:34 石頭@ 閱讀(417) | 評論 (0)編輯 收藏

    java推薦讀物

    http://blog.csdn.net/sqw131/archive/2009/06/22/4287749.aspx

    posted @ 2009-07-30 19:25 石頭@ 閱讀(443) | 評論 (0)編輯 收藏

    初級程序員與高級程序員的做事

    一般對于一個問題,初級程序員和高級程序員考慮問題的方法絕對是不同的。比如,在初級程序員階段時,他會覺得VB也能做出應用來,且看起來也不錯。

    但到了中級程序員時,他可能就不會選擇VB了,可能會用MFC,這時,也能做出效果不錯的程序。

    到高級程序員時,他絕對不是首先選擇以上工具,VB也好,VC也好,這些都不是他考慮的問題。這時考慮的絕對是什么才是具有最快效率、最穩定性能的解決問題的方法。

    軟件和別的產品不同。比如,在軟件中要達到某個目標,有n種方法,但是在n種方法中,只有一種方法或兩種方法是最好的,其他的都很次。所以,要做一個好的系統,是很需要耐心的。如果沒有耐心,就不會有細活,有細活的東西才是好東西。我覺得做軟件是這樣,做任何事情也是這樣的,一定要投入。

     

    程序員到達最高境界的時候,想的就是“我就是程序,程序就是我”。這時候我要做一個軟件,不會有自己主觀的思路,而是以機器的思路來考慮問題,也就是說,就是以程序的思考方式來思考程序,而不是以我去設計程序的方式去思考程序。這一點如果不到比較高的層次是不能明白的。

    你設計程序不就是你思考問題,然后按自己的思路去做程序嗎?

    其實不是的。在我設計這個程序的時候,相當于我“鉆”入這個程序里面去了。這時候沒有我自己的任何思維,我的所有思維都是這個程序,這步該怎么走,下步該怎么走,它可能會出現什么情況。我動這個部分的時候,別的部分是否要干擾,也許會動一發而牽全身,它們之間是怎么相互影響的?

    也只有到達這個境界,你的程序才能真正地寫好,絕對不是做個什么可視化。可視化本身就是“我去設計這個程序”,而真正的程序高手是“我就是程序”,這兩種方法絕對是不同的。比如,我要用VB去設計一個程序,和我本身就是一個程序的思維方式,是不一樣的。別人也許覺得操作系統很深奧,很復雜,其實,如果你到達高手狀態,你就是操作系統,你就能做任何程序。

    對待軟件要有一個全面的分析方法,光說理論是沒有用的。如果你沒有經過第一、第二、第三、第四這四個階段,則永遠到達不了高境界。因為空中樓閣的理論沒有用,而這些必須是一步一步地去做出來。

    一 個高級程序員應該具備開放性思維,從里到外的所有的知識都能了解。然后,看到世界最新技術就能馬上掌握,馬上了解。實際上,技術到達最高的境界后,是沒有 分別的。任何東西都是相通的,只要你到達這個境界以后,什么問題一看就能明白,一看就能抓住最核心的問題,最根本的根本,而不會被其他的枝葉或表象所迷 惑,做到這一步后才算比較成功。

    從 程序員本身來說,如果它到達這一步以后,他就已經形成了開闊的思維。他有這種開放性思維的話,他就能做戰略決策,這對他將來做任何事情都有好處。事實上, 會做程序后,就會有一種分析問題的方法,學會怎么樣把問題的表象剖開,看到它的本質。這時你碰到任何具體的問題,只要給點時間,都能輕而易舉地解決。實際 上,對開發計算機軟件來說,沒有什么做不了的軟件,所有的軟件都能做,只是看你有沒有時間,有沒有耐心,有沒有資金做支撐。

    這幾年,尤其是這兩三年,估計到2005年前,中國軟件這個行業里面大的軟件公司就能形成。現在就已經在形成,例如用友,它上市后,地位就更加穩固了。其他大的軟件企業會在這幾年內迅速長大。這時候,包括流通渠道、經銷商的渠道也會迅速長大。也就是說,到2005年以后,中國軟件這個行業的門檻比現在還要高很多,與美國不會有太大的差別。此時,中國軟件才真正體現出它的威力來。如果你是這些威力中的一員,就已經很厲害了。

    別 人可能知道比爾·蓋茨是個談判的高手,是賣東西的高手,其實,比爾·蓋茨從根本上來說是個程序高手,這是他根本中的根本。他對所有的技術都非常敏感,一眼 就看到本質,而且他本身也能做程序,時常在看程序。現在他不做董事長,而做首席設計師,這時他就更加接近程序的本質。因為他本身就有很開闊的思維,又深入 到技術的本身,所以他就知道技術的方向。這對于一個公司,對他這樣的人來說,是非常重要的。

    如果他判斷錯誤一步,那公司以后再回頭就很難了。計算機的競爭是非常激烈的,不能走錯半步。很多公司以前看上去很火,后來就

    銷聲匿跡了,就是因為它走錯一步,然后就不行了。為什么它會走錯?因為他不了解技術的本質在哪里,技術的發展方向在哪里。

    比爾·蓋茨因為父母是學法律的,所以他本身就很能“侃”,很有說服力,而他又是做技術的,就非常清楚技術的方向在哪里,所以他才能把方向把握得很準確,公司越來越大。而別的公司只一陣子,他卻火了還會再火。就算微軟再龐大,你如果不把握好軟件技術的最前沿,一樣也會玩完。就像Intel時刻把握著CPU的最新技術,才能保證自己是行業老大。技術決定它的將來。

     

    所以,程序員要能達到這樣的目標,就要有非常強的耐心和非常好的機遇才有可能。事實上,現在的機會挺好的,2005年 以前機會都非常大,以后機會會比較小。但是,如果有耐心的話,你還是會有機會的,機會都是出在耐心里。我記得有句話說“雄心的一半是耐心”,我認為雄心的 三分之二都是耐心。如果你越有野心,你就越要有耐心,你的野心才有可能實現。如果你有野心而沒有耐心,那都是胡思亂想,別人一眼就能看穿。最后在競爭中, 對手一眼就看到你的意圖,那你還有什么可競爭的?



    轉自:http://blog.pfan.cn/vagrant/31151.html

    posted @ 2009-07-27 21:04 石頭@ 閱讀(802) | 評論 (0)編輯 收藏

    主站蜘蛛池模板: 亚洲免费一区二区| 国产乱码免费卡1卡二卡3卡| 亚洲AV本道一区二区三区四区| 黄色片免费在线观看| 亚洲精品福利你懂| 在线亚洲精品自拍| 97国产免费全部免费观看 | 一级人做人爰a全过程免费视频| 亚洲自偷自偷偷色无码中文| 亚洲一区免费视频| 特级毛片爽www免费版| 亚洲视频在线观看网站| 全亚洲最新黄色特级网站| 99国产精品免费观看视频| 国产亚洲蜜芽精品久久| 久久久久久久亚洲Av无码| 国产又大又黑又粗免费视频| 日韩精品极品视频在线观看免费| 亚洲熟妇av午夜无码不卡 | 亚洲综合无码一区二区三区| 全部免费国产潢色一级| 222www免费视频| 一级毛片完整版免费播放一区| 亚洲六月丁香六月婷婷色伊人| 2048亚洲精品国产| 日本免费的一级v一片| 一级毛片免费观看| 中文字幕a∨在线乱码免费看 | 色一情一乱一伦一视频免费看| 久久久久亚洲av无码专区| 亚洲 无码 在线 专区| 曰批视频免费30分钟成人| 日韩免费高清播放器| 色一情一乱一伦一视频免费看| 67194在线午夜亚洲| 亚洲国产精品自在在线观看| 国产亚洲精品国看不卡| 亚洲电影日韩精品| 午夜神器成在线人成在线人免费| 亚洲成人在线免费观看| 免费日本一区二区|