• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            chaosuper85

            C++博客 首頁 新隨筆 聯(lián)系 聚合 管理
              118 Posts :: 0 Stories :: 3 Comments :: 0 Trackbacks

            #

            http://www.iciba.com/
            posted @ 2010-02-05 16:58 chaosuper 閱讀(49) | 評論 (0)編輯 收藏

            Debian/Ubuntu Linux下內(nèi)核編程者必備的幾件法寶
            鏈接 : http://zhoulifa.bokee.com/index.html
            如果你想要升級你的Debian/Ubuntu Linux內(nèi)核,或者你希望為內(nèi)核開發(fā)新的模塊,或者您要為某個硬件寫新的驅(qū)動程序……這一切都涉及到Debian/Ubuntu Linux內(nèi)核編程。 作為一個內(nèi)核編程者,有那么幾個軟件是你必須要有的,看作是你進行內(nèi)核編程的幾件法寶吧,下面我一一列舉出來: 1、gcc 大名鼎鼎的gcc我想沒有人不知道的吧?它是任何編程者必然要先安裝的一個武器了。不過一般如果你是安裝的Debian系統(tǒng),應(yīng)該已經(jīng)默認(rèn)安裝了的。要是Ubuntu你就安裝一下吧,安裝方法嘛,就是輸入: apt-get install gcc 2、make 如果你實實在在地寫過有用的程序,你一定輸入過make clean、make、make install等命令的,make是一個源代碼維護工具,它能自動檢測出需要重新編譯的源文件并根據(jù)你設(shè)定的編譯規(guī)則去重新編譯程序。這里也不多說,如果不了解的朋友就google一下吧。不過一般如果你是安裝的Debian系統(tǒng),應(yīng)該已經(jīng)默認(rèn)安裝了的。要是Ubuntu你就安裝一下吧,安裝方法一樣,輸入: apt-get install make 3、kernel-source 從這個包的名稱上已經(jīng)知道了,這是內(nèi)核源碼包。你可以apt-cache search kernel-source搜索到內(nèi)核源代碼包,并用uname -r命令查看到當(dāng)前系統(tǒng)內(nèi)核版本,然后用apt-get install kernel-source-xxxx來安裝和你內(nèi)核版本一致的內(nèi)核源代碼包。 但我并不建議你這樣做,因為大多數(shù)發(fā)行版的Linux的內(nèi)核源代碼包并不是和你從kernel.org上下載來的完全一致,應(yīng)該是經(jīng)過發(fā)行者們修改優(yōu)化過的包,雖然發(fā)行版的制作者們花了心血在上面,但對我們編程者來說這并不是件好事,因為大多發(fā)行版的源代碼包缺少某些必要的頭文件和某些有用的腳本程序,這會導(dǎo)致我們在編寫內(nèi)核模塊時遇到麻煩,比如編譯時可能會報錯說某個頭文件找不到,又可能報錯說某個腳本程序不存在啦。 如果你直接去kernel.org上下載一個新的內(nèi)核來編譯升級你的內(nèi)核,并在此基礎(chǔ)上進行內(nèi)核編程可能會省事一些,至少我后面講到的這些包你都可以不用安裝了,把KERNEL_DIR變量設(shè)置為你內(nèi)核源代碼包的位置就夠了。 在這里還是以Debian 3.1、內(nèi)核2.6.8-2-386為基礎(chǔ)來教大家準(zhǔn)備內(nèi)核編程環(huán)境吧。那么你依次用這幾個命令來安裝kernel-source包吧。 apt-cache search kernel-source uname -r apt-get install kernel-source-xxxx 注:如果你不想重新編譯內(nèi)核,內(nèi)核源代碼包kernel-source是完全可以不下載來的。 4、kernel-headers 這是內(nèi)核源代碼頭文件包,不管你是要進行內(nèi)核模塊開發(fā)還是進行驅(qū)動程序開發(fā),這個包都是必須要安裝的。因為作為一個內(nèi)核模塊編寫者,通常會調(diào)用內(nèi)核里的一些東西,比如內(nèi)核頭文件,內(nèi)核數(shù)據(jù)結(jié)構(gòu)申明等。它里面包含了一些關(guān)鍵的內(nèi)核頭文件。否則在編譯內(nèi)核時會報類似下面的錯誤: HOSTCC scripts/basic/fixdep scripts/basic/fixdep.c:105:23: error: sys/types.h: 沒有那個文件或目錄 輸入如下命令來安裝吧: apt-cache search kernel-headers uname -r apt-get instakk kernel-headers-xxxx 注:在Ubuntu下,好象這個包的前面都加上了linux-,從而變成了linux-kernel-headers。 如果之前沒有安裝過kernel-kbuild包,安裝此包的過程中會安裝kernel-kbuild包,這個包在下面介紹。 關(guān)于本文檔: /********************************************************************* *filename: Debian/Ubuntu Linux下內(nèi)核編程者必備的幾件法寶 *purpose: 記錄Linux內(nèi)核開發(fā)者必備的幾個軟件包 *wrote by: zhoulifa(zhoulifa@163.com) 周立發(fā)(http://zhoulifa.bokee.com) Linux愛好者 Linux知識傳播者 SOHO族 開發(fā)者 最擅長C語言 *date time:2006-07-01 22:50:00 *Note: 任何人可以任意復(fù)制代碼并運用這些文檔,當(dāng)然包括你的商業(yè)用途 * 但請遵循GPL *********************************************************************/ 5、kernel-kbuild 這個包是用來編譯內(nèi)核模塊的,下載安裝這個包后會發(fā)現(xiàn)在/usr/src目錄下多了一個kernel-kbuild-xxxx開頭的目錄,下面只有scripts一個目錄,顯然這是用來編譯內(nèi)核模塊的一些腳本程序。安裝方法一樣: apt-cache search kernel-kbuild uname -r apt-get install kernel-kbuild-xxxx 注:你也會發(fā)現(xiàn),在上面安裝kernel-headers包后,/usr/src/kernel-headers-xxxx目錄下有個scripts目錄,其實是到/usr/src/kernel-kbuild-xxxx目錄下的scripts的一個鏈接。 6、build-essential 這個包包含一個在建立deb包過程中起關(guān)鍵作用的包的信息列表,如果你不想建立deb包你就不需要安裝此表,如果需要生成deb包就最好安裝一下這個包吧。安裝方法: apt-get install build-essential 7、kernel-package 如果你想把內(nèi)核鏡像做成一個deb包來用,那么必須用安裝這個包了。也就是說只有安裝了這個軟件包你才能有make-kpkg命令可用。安裝方法一樣了: apt-get install kernel-package 8、initrd-tools 如果你想制作啟動過程的initrd鏡像,則這個包是必不可少的。安裝了這個包之后才有mkinitrd命令可用的。安裝方法: apt-get instakk initrd-tools 最后來一個內(nèi)核模塊編程示例吧: 假設(shè)你編寫了一個內(nèi)核模塊程序,源代碼如下: /* hello.c */ #include #include #include static int hello_init(void) { printk(KERN_ALERT "Hello, linux kernel module\n"); return 0; } static void hello_exit(void) { printk(KERN_ALERT "Goodbye, I've created a linux kernel module sucessfully\n"); } module_init(hello_init); module_exit(hello_exit); MODULE_LICENSE("GPL"); 你需要這此源程序編寫一個makefile,內(nèi)容如下: #Makefile for hello.c file # KERNEL_DIR:=/usr/src/linux obj-m:=hello.o default: $(MAKE) -C $(KERNEL_DIR) SUBDIRS=$(PWD) modules clean: $(RM) .*.cmd *.mod.c *.o *.ko -r .tmp 注意:這里的KERNEL_DIR是指內(nèi)核源代碼頭文件所在目錄的上一級目錄,通常就是指內(nèi)核源代碼目錄。該目錄一般包括有arch,drivers,fs,include,init,ipc,kernel,lib,mm,net,scripts,usr,sound,security等目錄。 在本示例中,/usr/src/linux是一個鏈接,指向了/usr/src/kernel-headers-2.6.8-3目錄。 編寫好makefile后就可以輸入make命令生成hello.ko內(nèi)核模塊了,然后你可以用: insmode hello.ko 命令來加入內(nèi)核模塊,然后用: rmmod hello 來刪除內(nèi)核模塊。 當(dāng)然,操作過程中,你可以用dmesg命令來查看運行結(jié)果。
            posted @ 2010-02-05 14:10 chaosuper 閱讀(159) | 評論 (0)編輯 收藏

            Linux 2.6內(nèi)核中提高網(wǎng)絡(luò)I/O性能的新方法epoll 正如我昨天在“Linux下各類TCP網(wǎng)絡(luò)服務(wù)器的實現(xiàn)源代碼”(http://zhoulifa.bokee.com/5345930.html)一文中提到的那樣,I/O多路復(fù)用技術(shù)在比較多的TCP網(wǎng)絡(luò)服務(wù)器中有使用,即比較多的用到select函數(shù)。 感謝chinaunix.net上朋友safedead(http://bbs.chinaunix.net/viewpro.php?uid=407631)提醒,我今天仔細研究了一下,證實了在2.6內(nèi)核中的新的I/O技術(shù)epoll。 1、為什么select是落后的? 首先,在Linux內(nèi)核中,select所用到的FD_SET是有限的,即內(nèi)核中有個參數(shù)__FD_SETSIZE定義了每個FD_SET的句柄個數(shù),在我用的2.6.15-25-386內(nèi)核中,該值是1024,搜索內(nèi)核源代碼得到: include/linux/posix_types.h:#define __FD_SETSIZE 1024 也就是說,如果想要同時檢測1025個句柄的可讀狀態(tài)是不可能用select實現(xiàn)的?;蛘咄瑫r檢測1025個句柄的可寫狀態(tài)也是不可能的。 其次,內(nèi)核中實現(xiàn)select是用輪詢方法,即每次檢測都會遍歷所有FD_SET中的句柄,顯然,select函數(shù)執(zhí)行時間與FD_SET中的句柄個數(shù)有一個比例關(guān)系,即select要檢測的句柄數(shù)越多就會越費時。 當(dāng)然,在前文中我并沒有提及poll方法,事實上用select的朋友一定也試過poll,我個人覺得select和poll大同小異,個人偏好于用select而已。 /************關(guān)于本文檔******************************************** *filename: Linux 2.6內(nèi)核中提高網(wǎng)絡(luò)I/O性能的新方法epoll *purpose: 補充“Linux下各類TCP網(wǎng)絡(luò)服務(wù)器的實現(xiàn)源代碼”一文的不足之處 *wrote by: zhoulifa(zhoulifa@163.com) 周立發(fā)(http://zhoulifa.bokee.com) Linux愛好者 Linux知識傳播者 SOHO族 開發(fā)者 最擅長C語言 *date time:2006-07-06 22:30:00 *Note: 任何人可以任意復(fù)制代碼并運用這些文檔,當(dāng)然包括你的商業(yè)用途 * 但請遵循GPL *Hope:希望越來越多的人貢獻自己的力量,為科學(xué)技術(shù)發(fā)展出力 *********************************************************************/ 2、2.6內(nèi)核中提高I/O性能的新方法epoll epoll是什么?按照man手冊的說法:是為處理大批量句柄而作了改進的poll。要使用epoll只需要這三個系統(tǒng)調(diào)用:epoll_create(2), epoll_ctl(2), epoll_wait(2)。 當(dāng)然,這不是2.6內(nèi)核才有的,它是在2.5.44內(nèi)核中被引進的(epoll(4) is a new API introduced in Linux kernel 2.5.44) 以下文章轉(zhuǎn)自滕昱的Web Log http://mechgouki.spaces.msn.com/blog/PersonalSpace.aspx/*********************************引用開始******************************/ Linux2.6內(nèi)核epoll介紹---我的blog 2005/3/30 [作者]:滕昱,2005/3/30,0.1版本 [版權(quán)聲明]:此文檔遵循GNU自由文檔許可證(GNU Free Documentation License).任何人可以自由復(fù)制,分發(fā),修改,不過如果方便,請注明出處和作者:) (1)導(dǎo)言: 首先,我強烈建議大家閱讀Richard Stevens著作《TCP/IP Illustracted Volume 1,2,3》和《UNIX Network Programming Volume 1,2》。雖然他離開我們大家已經(jīng)5年多了,但是他的書依然是進入網(wǎng)絡(luò)編程的最直接的道路。其中的3卷的《TCP/IP Illustracted》卷1是必讀-如果你不了解tcp協(xié)議各個選項的詳細定義,你就失去了優(yōu)化程序重要的一個手段。卷2,3可以選讀一下。比如卷2 講解的是4.4BSD內(nèi)核TCP/IP協(xié)議棧實現(xiàn)----這個版本的協(xié)議棧幾乎影響了現(xiàn)在所有的主流os,但是因為年代久遠,內(nèi)容不一定那么vogue. 在這里我多推薦一本《The Linux Networking Architecture--Design and Implementation of Network Protocols in the Linux Kernel》,以2.4內(nèi)核講解Linux TCP/IP實現(xiàn),相當(dāng)不錯.作為一個現(xiàn)實世界中的實現(xiàn),很多時候你必須作很多權(quán)衡,這時候參考一個久經(jīng)考驗的系統(tǒng)更有實際意義。舉個例子,linux內(nèi)核中sk_buff結(jié)構(gòu)為了追求速度和安全,犧牲了部分內(nèi)存,所以在發(fā)送TCP包的時候,無論應(yīng)用層數(shù)據(jù)多大,sk_buff最小也有272的字節(jié). 其實對于socket應(yīng)用層程序來說,《UNIX Network Programming Volume 1》意義更大一點.2003年的時候,這本書出了最新的第3版本,不過主要還是修訂第2版本。其中第6章《I/O Multiplexing》是最重要的。Stevens給出了網(wǎng)絡(luò)IO的基本模型。在這里最重要的莫過于select模型和Asynchronous I/O模型.從理論上說,AIO似乎是最高效的,你的IO操作可以立即返回,然后等待os告訴你IO操作完成。但是一直以來,如何實現(xiàn)就沒有一個完美的方案。最著名的windows完成端口實現(xiàn)的AIO,實際上也是內(nèi)部用線程池實現(xiàn)的罷了,最后的結(jié)果是IO有個線程池,你應(yīng)用也需要一個線程池...... 很多文檔其實已經(jīng)指出了這帶來的線程context-switch帶來的代價。 在linux 平臺上,關(guān)于網(wǎng)絡(luò)AIO一直是改動最多的地方,2.4的年代就有很多AIO內(nèi)核patch,最著名的應(yīng)該算是SGI那個。但是一直到2.6內(nèi)核發(fā)布,網(wǎng)絡(luò)模塊的AIO一直沒有進入穩(wěn)定內(nèi)核版本(大部分都是使用用戶線程模擬方法,在使用了NPTL的linux上面其實和windows的完成端口基本上差不多了)。2.6內(nèi)核所支持的AIO特指磁盤的AIO---支持io_submit(),io_getevents()以及對Direct IO的支持(就是繞過VFS系統(tǒng)buffer直接寫硬盤,對于流服務(wù)器在內(nèi)存平穩(wěn)性上有相當(dāng)幫助)。 所以,剩下的select模型基本上就是我們在linux上面的唯一選擇,其實,如果加上no-block socket的配置,可以完成一個"偽"AIO的實現(xiàn),只不過推動力在于你而不是os而已。不過傳統(tǒng)的select/poll函數(shù)有著一些無法忍受的缺點,所以改進一直是2.4-2.5開發(fā)版本內(nèi)核的任務(wù),包括/dev/poll,reltime signal等等。最終,Davide Libenzi開發(fā)的epoll進入2.6內(nèi)核成為正式的解決方案 (2)epoll的優(yōu)點 <1>支持一個進程打開大數(shù)目的socket描述符(FD) select 最不能忍受的是一個進程所打開的FD是有一定限制的,由FD_SETSIZE設(shè)置,默認(rèn)值是2048。對于那些需要支持的上萬連接數(shù)目的IM服務(wù)器來說顯然太少了。這時候你一是可以選擇修改這個宏然后重新編譯內(nèi)核,不過資料也同時指出這樣會帶來網(wǎng)絡(luò)效率的下降,二是可以選擇多進程的解決方案(傳統(tǒng)的Apache方案),不過雖然linux上面創(chuàng)建進程的代價比較小,但仍舊是不可忽視的,加上進程間數(shù)據(jù)同步遠比不上線程間同步的高效,所以也不是一種完美的方案。不過 epoll則沒有這個限制,它所支持的FD上限是最大可以打開文件的數(shù)目,這個數(shù)字一般遠大于2048,舉個例子,在1GB內(nèi)存的機器上大約是10萬左右,具體數(shù)目可以cat /proc/sys/fs/file-max察看,一般來說這個數(shù)目和系統(tǒng)內(nèi)存關(guān)系很大。 <2>IO效率不隨FD數(shù)目增加而線性下降 傳統(tǒng)的select/poll另一個致命弱點就是當(dāng)你擁有一個很大的socket集合,不過由于網(wǎng)絡(luò)延時,任一時間只有部分的socket是"活躍"的,但是select/poll每次調(diào)用都會線性掃描全部的集合,導(dǎo)致效率呈現(xiàn)線性下降。但是epoll不存在這個問題,它只會對"活躍"的socket進行操作---這是因為在內(nèi)核實現(xiàn)中epoll是根據(jù)每個fd上面的callback函數(shù)實現(xiàn)的。那么,只有"活躍"的socket才會主動的去調(diào)用 callback函數(shù),其他idle狀態(tài)socket則不會,在這點上,epoll實現(xiàn)了一個"偽"AIO,因為這時候推動力在os內(nèi)核。在一些 benchmark中,如果所有的socket基本上都是活躍的---比如一個高速LAN環(huán)境,epoll并不比select/poll有什么效率,相反,如果過多使用epoll_ctl,效率相比還有稍微的下降。但是一旦使用idle connections模擬WAN環(huán)境,epoll的效率就遠在select/poll之上了。 <3>使用mmap加速內(nèi)核與用戶空間的消息傳遞。 這點實際上涉及到epoll的具體實現(xiàn)了。無論是select,poll還是epoll都需要內(nèi)核把FD消息通知給用戶空間,如何避免不必要的內(nèi)存拷貝就很重要,在這點上,epoll是通過內(nèi)核于用戶空間mmap同一塊內(nèi)存實現(xiàn)的。而如果你想我一樣從2.5內(nèi)核就關(guān)注epoll的話,一定不會忘記手工 mmap這一步的。 <4>內(nèi)核微調(diào) 這一點其實不算epoll的優(yōu)點了,而是整個linux平臺的優(yōu)點。也許你可以懷疑linux平臺,但是你無法回避linux平臺賦予你微調(diào)內(nèi)核的能力。比如,內(nèi)核TCP/IP協(xié)議棧使用內(nèi)存池管理sk_buff結(jié)構(gòu),那么可以在運行時期動態(tài)調(diào)整這個內(nèi)存pool(skb_head_pool)的大小--- 通過echo XXXX>/proc/sys/net/core/hot_list_length完成。再比如listen函數(shù)的第2個參數(shù)(TCP完成3次握手的數(shù)據(jù)包隊列長度),也可以根據(jù)你平臺內(nèi)存大小動態(tài)調(diào)整。更甚至在一個數(shù)據(jù)包面數(shù)目巨大但同時每個數(shù)據(jù)包本身大小卻很小的特殊系統(tǒng)上嘗試最新的NAPI網(wǎng)卡驅(qū)動架構(gòu)。 (3)epoll的使用 令人高興的是,2.6內(nèi)核的epoll比其2.5開發(fā)版本的/dev/epoll簡潔了許多,所以,大部分情況下,強大的東西往往是簡單的。唯一有點麻煩是epoll有2種工作方式:LT和ET。 LT(level triggered)是缺省的工作方式,并且同時支持block和no-block socket.在這種做法中,內(nèi)核告訴你一個文件描述符是否就緒了,然后你可以對這個就緒的fd進行IO操作。如果你不作任何操作,內(nèi)核還是會繼續(xù)通知你的,所以,這種模式編程出錯誤可能性要小一點。傳統(tǒng)的select/poll都是這種模型的代表. ET (edge-triggered)是高速工作方式,只支持no-block socket。在這種模式下,當(dāng)描述符從未就緒變?yōu)榫途w時,內(nèi)核通過epoll告訴你。然后它會假設(shè)你知道文件描述符已經(jīng)就緒,并且不會再為那個文件描述符發(fā)送更多的就緒通知,直到你做了某些操作導(dǎo)致那個文件描述符不再為就緒狀態(tài)了(比如,你在發(fā)送,接收或者接收請求,或者發(fā)送接收的數(shù)據(jù)少于一定量時導(dǎo)致了一個EWOULDBLOCK 錯誤)。但是請注意,如果一直不對這個fd作IO操作(從而導(dǎo)致它再次變成未就緒),內(nèi)核不會發(fā)送更多的通知(only once),不過在TCP協(xié)議中,ET模式的加速效用仍需要更多的benchmark確認(rèn)。 epoll只有epoll_create,epoll_ctl,epoll_wait 3個系統(tǒng)調(diào)用,具體用法請參考http://www.xmailserver.org/linux-patches/nio-improve.html , 在http://www.kegel.com/rn/也有一個完整的例子,大家一看就知道如何使用了 (4)Leader/follower模式線程pool實現(xiàn),以及和epoll的配合 .....未完成,主要是要避免過多的epoll_ctl調(diào)用,以及嘗試使用EPOLLONESHOT加速...... (5)benchmark .......未完成 /*********************************引用結(jié)束******************************/ 3、epoll的使用方法 這是epoll的man手冊提供的一個例子,這段代碼假設(shè)一個非阻塞的socket監(jiān)聽listener被建立并且一個epoll句柄kdpfd已經(jīng)提前用epoll_create建立了: struct epoll_event ev, *events; for(;;) { nfds = epoll_wait(kdpfd, events, maxevents, -1);/*wait for an I/O event. All notes here added by zhoulifa(http://zhoulifa.bokee.com) on 2006-7-6 22:10:00*/ for(n = 0; n < nfds; ++n) { if(events[n].data.fd == listener) {/*if listen socket has an I/O, accept the new connect*/ client = accept(listener, (struct sockaddr *) &local, &addrlen); if(client < 0){ perror("accept"); continue; } setnonblocking(client); ev.events = EPOLLIN | EPOLLET;/*EPOLLIN-available for read*/ ev.data.fd = client; if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, client, &ev) < 0) {/*add the new socket into the epoll file descriptors*/ fprintf(stderr, "epoll set insertion error: fd=%d\n", client); return -1; } } else do_use_fd(events[n].data.fd);/*read from a socket which has data come*/ } } 4、epoll使用方法示意代碼 以下代碼由chinaunix.net上BBS用戶safedead(http://bbs.chinaunix.net/viewpro.php?uid=407631)提供: static int s_epfd;//epoll描述字 {//初始化epoll &nsp; struct epoll_event ev; //設(shè)置epoll s_epfd = epoll_create(65535); {//這個過程可以循環(huán)以便加入多個LISTEN套接字進入epoll事件集合 //服務(wù)器監(jiān)聽創(chuàng)建 rc = listen();//listen參數(shù)這里省略 //加入epoll事件集合 ev.events = EPOLLIN; ev.data.fd = rc; if (epoll_ctl(s_epfd, EPOLL_CTL_ADD, rc, &ev) < 0) { fprintf(stderr, "epoll set insertion error: fd=%d", rc); return(-1); } } } {//epoll事件處理 int i, nfds, sock_new; struct epoll_event events[16384]; for( ; ; ) { //等待epoll事件 nfds = epoll_wait(s_epfd, events, 16384, -1); //處理epoll事件 for(i = 0; i < nfds; i++) { //events[i].data.fd是epoll事件中彈出的套接字 //接收連接 sock_new = accept(events[i].data.fd);//accept其它參數(shù)這里省略了 if(0 > sock_new) { fprintf(stderr, "接收客戶端連接失敗\n"); continue; } } } } 對照safedead和前面的一份代碼,我想大家一定是明白了的。
            posted @ 2010-02-05 14:06 chaosuper 閱讀(147) | 評論 (0)編輯 收藏

            select, poll和epoll的區(qū)別(轉(zhuǎn)載) select()系統(tǒng)調(diào)用提供一個機制來實現(xiàn)同步多元I/O: #include #include #include int select (int n, fd_set *readfds, fd_set *writefds, fd_set *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); 調(diào)用select()將阻塞,直到指定的文件描述符準(zhǔn)備好執(zhí)行I/O,或者可選參數(shù)timeout指定的時間已經(jīng)過去。 監(jiān)視的文件描述符分為三類set,每一種對應(yīng)等待不同的事件。readfds中列出的文件描述符被監(jiān)視是否有數(shù)據(jù)可供讀?。ㄈ绻x取操作完成則不會阻塞)。writefds中列出的文件描述符則被監(jiān)視是否寫入操作完成而不阻塞。最后,exceptfds中列出的文件描述符則被監(jiān)視是否發(fā)生異常,或者無法控制的數(shù)據(jù)是否可用(這些狀態(tài)僅僅應(yīng)用于套接字)。這三類set可以是NULL,這種情況下select()不監(jiān)視這一類事件。 select()成功返回時,每組set都被修改以使它只包含準(zhǔn)備好I/O的文件描述符。例如,假設(shè)有兩個文件描述符,值分別是7和9,被放在readfds中。當(dāng)select()返回時,如果7仍然在set中,則這個文件描述符已經(jīng)準(zhǔn)備好被讀取而不會阻塞。如果9已經(jīng)不在set中,則讀取它將可能會阻塞(我說可能是因為數(shù)據(jù)可能正好在select返回后就可用,這種情況下,下一次調(diào)用select()將返回文件描述符準(zhǔn)備好讀?。? 第一個參數(shù)n,等于所有set中最大的那個文件描述符的值加1。因此,select()的調(diào)用者負責(zé)檢查哪個文件描述符擁有最大值,并且把這個值加1再傳遞給第一個參數(shù)。 timeout參數(shù)是一個指向timeval結(jié)構(gòu)體的指針,timeval定義如下: #include struct timeval { long tv_sec; /* seconds */ long tv_usec; /* 10E-6 second */ }; 如果這個參數(shù)不是NULL,則即使沒有文件描述符準(zhǔn)備好I/O,select()也會在經(jīng)過tv_sec秒和tv_usec微秒后返回。當(dāng)select()返回時,timeout參數(shù)的狀態(tài)在不同的系統(tǒng)中是未定義的,因此每次調(diào)用select()之前必須重新初始化timeout和文件描述符set。實際上,當(dāng)前版本的Linux會自動修改timeout參數(shù),設(shè)置它的值為剩余時間。因此,如果timeout被設(shè)置為5秒,然后在文件描述符準(zhǔn)備好之前經(jīng)過了3秒,則這一次調(diào)用select()返回時tv_sec將變?yōu)?。 如果timeout中的兩個值都設(shè)置為0,則調(diào)用select()將立即返回,報告調(diào)用時所有未決的事件,但不等待任何隨后的事件。 文件描述符set不會直接操作,一般使用幾個助手宏來管理。這允許Unix系統(tǒng)以自己喜歡的方式來實現(xiàn)文件描述符set。但大多數(shù)系統(tǒng)都簡單地實現(xiàn)set為位數(shù)組。FD_ZERO移除指定set中的所有文件描述符。每一次調(diào)用select()之前都應(yīng)該先調(diào)用它。 fd_set writefds; FD_ZERO(&writefds); FD_SET添加一個文件描述符到指定的set中,F(xiàn)D_CLR則從指定的set中移除一個文件描述符: FD_SET(fd, &writefds); /* add 'fd' to the set */ FD_CLR(fd, &writefds); /* oops, remove 'fd' from the set */ 設(shè)計良好的代碼應(yīng)該永遠不使用FD_CLR,而且實際情況中它也確實很少被使用。 FD_ISSET測試一個文件描述符是否指定set的一部分。如果文件描述符在set中則返回一個非0整數(shù),不在則返回0。FD_ISSET在調(diào)用select()返回之后使用,測試指定的文件描述符是否準(zhǔn)備好相關(guān)動作: if (FD_ISSET(fd, &readfds)) /* 'fd' is readable without blocking! */ 因為文件描述符set是靜態(tài)創(chuàng)建的,它們對文件描述符的最大數(shù)目強加了一個限制,能夠放進set中的最大文件描述符的值由FD_SETSIZE指定。在Linux中,這個值是1024。本章后面我們還將看到這個限制的衍生物。 返回值和錯誤代碼 select()成功時返回準(zhǔn)備好I/O的文件描述符數(shù)目,包括所有三個set。如果提供了timeout,返回值可能是0;錯誤時返回-1,并且設(shè)置errno為下面幾個值之一: EBADF 給某個set提供了無效文件描述符。 EINTR 等待時捕獲到信號,可以重新發(fā)起調(diào)用。 EINVAL 參數(shù)n為負數(shù),或者指定的timeout非法。 ENOMEM 不夠可用內(nèi)存來完成請求。 -------------------------------------------------------------------------------------------------------------- poll()系統(tǒng)調(diào)用是System V的多元I/O解決方案。它解決了select()的幾個不足,盡管select()仍然經(jīng)常使用(多數(shù)還是出于習(xí)慣,或者打著可移植的名義): #include int poll (struct pollfd *fds, unsigned int nfds, int timeout); 和select()不一樣,poll()沒有使用低效的三個基于位的文件描述符set,而是采用了一個單獨的結(jié)構(gòu)體pollfd數(shù)組,由fds指針指向這個組。pollfd結(jié)構(gòu)體定義如下: #include struct pollfd { int fd; /* file descriptor */ short events; /* requested events to watch */ short revents; /* returned events witnessed */ }; 每一個pollfd結(jié)構(gòu)體指定了一個被監(jiān)視的文件描述符,可以傳遞多個結(jié)構(gòu)體,指示poll()監(jiān)視多個文件描述符。每個結(jié)構(gòu)體的events域是監(jiān)視該文件描述符的事件掩碼,由用戶來設(shè)置這個域。revents域是文件描述符的操作結(jié)果事件掩碼。內(nèi)核在調(diào)用返回時設(shè)置這個域。events域中請求的任何事件都可能在revents域中返回。合法的事件如下: POLLIN 有數(shù)據(jù)可讀。 POLLRDNORM 有普通數(shù)據(jù)可讀。 POLLRDBAND 有優(yōu)先數(shù)據(jù)可讀。 POLLPRI 有緊迫數(shù)據(jù)可讀。 POLLOUT 寫數(shù)據(jù)不會導(dǎo)致阻塞。 POLLWRNORM 寫普通數(shù)據(jù)不會導(dǎo)致阻塞。 POLLWRBAND 寫優(yōu)先數(shù)據(jù)不會導(dǎo)致阻塞。 POLLMSG SIGPOLL消息可用。 此外,revents域中還可能返回下列事件: POLLER 指定的文件描述符發(fā)生錯誤。 POLLHUP 指定的文件描述符掛起事件。 POLLNVAL 指定的文件描述符非法。 這些事件在events域中無意義,因為它們在合適的時候總是會從revents中返回。使用poll()和select()不一樣,你不需要顯式地請求異常情況報告。 POLLIN | POLLPRI等價于select()的讀事件,POLLOUT | POLLWRBAND等價于select()的寫事件。POLLIN等價于POLLRDNORM | POLLRDBAND,而POLLOUT則等價于POLLWRNORM。 例如,要同時監(jiān)視一個文件描述符是否可讀和可寫,我們可以設(shè)置events為POLLIN | POLLOUT。在poll返回時,我們可以檢查revents中的標(biāo)志,對應(yīng)于文件描述符請求的events結(jié)構(gòu)體。如果POLLIN事件被設(shè)置,則文件描述符可以被讀取而不阻塞。如果POLLOUT被設(shè)置,則文件描述符可以寫入而不導(dǎo)致阻塞。這些標(biāo)志并不是互斥的:它們可能被同時設(shè)置,表示這個文件描述符的讀取和寫入操作都會正常返回而不阻塞。 timeout參數(shù)指定等待的毫秒數(shù),無論I/O是否準(zhǔn)備好,poll都會返回。timeout指定為負數(shù)值表示無限超時;timeout為0指示poll調(diào)用立即返回并列出準(zhǔn)備好I/O的文件描述符,但并不等待其它的事件。這種情況下,poll()就像它的名字那樣,一旦選舉出來,立即返回。 返回值和錯誤代碼 成功時,poll()返回結(jié)構(gòu)體中revents域不為0的文件描述符個數(shù);如果在超時前沒有任何事件發(fā)生,poll()返回0;失敗時,poll()返回-1,并設(shè)置errno為下列值之一: EBADF 一個或多個結(jié)構(gòu)體中指定的文件描述符無效。 EFAULT fds指針指向的地址超出進程的地址空間。 EINTR 請求的事件之前產(chǎn)生一個信號,調(diào)用可以重新發(fā)起。 EINVAL nfds參數(shù)超出PLIMIT_NOFILE值。 ENOMEM 可用內(nèi)存不足,無法完成請求。 -------------------------------------------------------------------------------------------------------------- 以上內(nèi)容來自《OReilly.Linux.System.Programming - Talking.Directly.to.the.Kernel.and.C.Library.2007》 -------------------------------------------------------------------------------------------------------------- epoll的優(yōu)點: 1.支持一個進程打開大數(shù)目的socket描述符(FD) select 最不能忍受的是一個進程所打開的FD是有一定限制的,由FD_SETSIZE設(shè)置,默認(rèn)值是2048。對于那些需要支持的上萬連接數(shù)目的IM服務(wù)器來說顯然太少了。這時候你一是可以選擇修改這個宏然后重新編譯內(nèi)核,不過資料也同時指出這樣會帶來網(wǎng)絡(luò)效率的下降,二是可以選擇多進程的解決方案(傳統(tǒng)的 Apache方案),不過雖然linux上面創(chuàng)建進程的代價比較小,但仍舊是不可忽視的,加上進程間數(shù)據(jù)同步遠比不上線程間同步的高效,所以也不是一種完美的方案。不過 epoll則沒有這個限制,它所支持的FD上限是最大可以打開文件的數(shù)目,這個數(shù)字一般遠大于2048,舉個例子,在1GB內(nèi)存的機器上大約是10萬左右,具體數(shù)目可以cat /proc/sys/fs/file-max察看,一般來說這個數(shù)目和系統(tǒng)內(nèi)存關(guān)系很大。 2.IO效率不隨FD數(shù)目增加而線性下降 傳統(tǒng)的select/poll另一個致命弱點就是當(dāng)你擁有一個很大的socket集合,不過由于網(wǎng)絡(luò)延時,任一時間只有部分的socket是"活躍"的,但是select/poll每次調(diào)用都會線性掃描全部的集合,導(dǎo)致效率呈現(xiàn)線性下降。但是epoll不存在這個問題,它只會對"活躍"的socket進行操作---這是因為在內(nèi)核實現(xiàn)中epoll是根據(jù)每個fd上面的callback函數(shù)實現(xiàn)的。那么,只有"活躍"的socket才會主動的去調(diào)用 callback函數(shù),其他idle狀態(tài)socket則不會,在這點上,epoll實現(xiàn)了一個"偽"AIO,因為這時候推動力在os內(nèi)核。在一些 benchmark中,如果所有的socket基本上都是活躍的---比如一個高速LAN環(huán)境,epoll并不比select/poll有什么效率,相反,如果過多使用epoll_ctl,效率相比還有稍微的下降。但是一旦使用idle connections模擬WAN環(huán)境,epoll的效率就遠在select/poll之上了。 3.使用mmap加速內(nèi)核與用戶空間的消息傳遞。 這點實際上涉及到epoll的具體實現(xiàn)了。無論是select,poll還是epoll都需要內(nèi)核把FD消息通知給用戶空間,如何避免不必要的內(nèi)存拷貝就很重要,在這點上,epoll是通過內(nèi)核于用戶空間mmap同一塊內(nèi)存實現(xiàn)的。而如果你想我一樣從2.5內(nèi)核就關(guān)注epoll的話,一定不會忘記手工 mmap這一步的。 4.內(nèi)核微調(diào) 這一點其實不算epoll的優(yōu)點了,而是整個linux平臺的優(yōu)點。也許你可以懷疑linux平臺,但是你無法回避linux平臺賦予你微調(diào)內(nèi)核的能力。比如,內(nèi)核TCP/IP協(xié)議棧使用內(nèi)存池管理sk_buff結(jié)構(gòu),那么可以在運行時期動態(tài)調(diào)整這個內(nèi)存pool(skb_head_pool)的大小--- 通過echo XXXX>/proc/sys/net/core/hot_list_length完成。再比如listen函數(shù)的第2個參數(shù)(TCP完成3次握手的數(shù)據(jù)包隊列長度),也可以根據(jù)你平臺內(nèi)存大小動態(tài)調(diào)整。更甚至在一個數(shù)據(jù)包面數(shù)目巨大但同時每個數(shù)據(jù)包本身大小卻很小的特殊系統(tǒng)上嘗試最新的NAPI網(wǎng)卡驅(qū)動架構(gòu)。
            posted @ 2010-02-03 22:45 chaosuper 閱讀(250) | 評論 (0)編輯 收藏

            #include
            #include
            /* 字符串的所有字符排列函數(shù),用已知字符串s中的所有字符,生成由其中n個字符組成的所有字符排列 */
            #define N 20
            char w[N];
            perm(int n, char *s)
            {
            char s1[N];
            int i;
            if(n<1)
            printf("%s\n",w); /* 一個排列生成輸出 */
            else
            {
            strcpy(s1,s); /* 保存本層次可使用的字符 */
            for(i=0;*(s1+i);i++) /* 依次選本層次可用字符 */
            {
            *(w+n-1)=*(s1+i);/* 將選用字符填入正在生成的字符排列中 */
            *(s1+i)=*s1;
            *s1=*(w+n-1);
            perm(n-1,s1+1); /* 遞歸 */
            }
            }
            }
            int main()
            {
            int n=2;
            char s[N];
            w[n]='\0';
            printf("This is a char permutation program!\nPlease input a string:\n");
            scanf("%s",s);
            puts("\nPlease input the char number of permuted:\n");
            scanf("%d",&n);
            puts("The permuted chars are:\n");
            perm(n,s);
            puts("\nPress any key to quit...");
            return 0;
            }
            posted @ 2010-02-03 21:03 chaosuper 閱讀(102) | 評論 (0)編輯 收藏

                 摘要: 學(xué)習(xí)鏈接 http://manual.luaer.cn/ -------------------------------------------------------------------------------- Lua 5.1 參考手冊 by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes ...  閱讀全文
            posted @ 2010-01-30 20:50 chaosuper 閱讀(2868) | 評論 (0)編輯 收藏

            如果你喜歡編程,那么你真是受到了上天的眷顧。你是非常幸運的少數(shù)人之一,能夠以自己喜歡的事謀生。大多數(shù)人沒有這么幸運。你認(rèn)為理所當(dāng)然的觀念“熱愛你的工作”,其實是一個很現(xiàn)代的概念。通常的看法是,工作是一種讓人很不開心的事,你為了拿工資才不得不去上班。你工作的目的是為了攢下錢去干那些自己真正喜歡干的事,但是前提是你得等到65歲退休之后才行,而且還有不少條件。條件一,你的積蓄必須足夠多;條件二,你沒有老到走不動,你還有體力去干那些事情;條件三,你喜歡的事情不需要用到脆弱的膝蓋、昏花的視力,也不要求你走上一里地不喘氣,等等。 我剛才說到哪里了?對了,我要提建議。 畢業(yè)前練好寫作 如果不是Linus Torvalds不斷地散布福音,請問Linux操作系統(tǒng)會成功嗎?雖然他是一個非常聰明的計算機天才,但是Linux吸引來全世界一大批志愿者的真正原因卻是Linus Torvalds的表達能力。他通過電子郵件和郵件列表用書面形式傳播自己的想法,最終引起了所有人的注意。 你聽說過現(xiàn)在風(fēng)靡一時的“極限編程[ ] ”(Extreme Programming)嗎?我在這個地方不談我對極限編程的看法,我只說如果你聽過這個詞,那么原因就是它的倡導(dǎo)者都是一些非常有才華的作家和演說家。 即使我們縮小范圍,將目光局限在任何一個軟件開發(fā)團體中,你也會發(fā)現(xiàn)該團體中最有權(quán)勢和影響力的程序員正是那些表達能力強的程序員,他們無論是做書面表達還是做口頭表達,都能夠清晰、自如、具有說服力地傳達觀點。此外,長得高也有助于提升影響力,不過這個不取決于你。 一個普通程序員與一個優(yōu)秀程序員的區(qū)別,不在于他們懂得的編程語言誰多誰少,也不在于他們喜歡用Python語言還是喜歡用Java語言,而在于他們能否與他人交流思想。如果你能說服其他人,你的力量就可以得到放大。如果你能寫出清晰的注釋和技術(shù)規(guī)格說明書,其他程序員就能夠理解你的代碼,因此他們就能在自己的代碼中使用,而不必重寫。如果你做不到這一點,你的代碼對其他人就沒有價值。如果你能為最終用戶寫出清晰的使用手冊,其他人就能明白你的代碼是用來干什么的,這是唯一讓別人明白你的代碼有何價值的方法。SourceForge[ ]上有許多優(yōu)美的、有用的代碼,但是它們都像被埋葬了一樣,根本沒人來用,原因就是它們的作者沒有寫好使用說明(或者壓根就沒寫)。這樣一來就沒有人知道他們的成果,他們杰出的代碼就衰亡了。 如果一個程序員不會用英語寫作、沒有良好的寫作能力,我就不會雇他。如果你能寫,不管你去哪家公司工作,你很快就會發(fā)現(xiàn)寫作技術(shù)文檔的任務(wù)會落到你頭上,這意味著你已經(jīng)開始在放大自己的影響力了,管理層正在注意到你。 大學(xué)里有些課程被公認(rèn)為“寫作密集型”(writing intensive)課程,這就是說為了拿到學(xué)分,你必須寫作多得可怕的文字。一定要去上這樣的課程!不要管學(xué)科,只要這門課每周甚至每天都要你寫東西,你就去上。 你還可以動手寫日記或者網(wǎng)志。你寫得越多,寫作就會變得越容易。寫起來越容易,你就會寫得越多。這是一個良性循環(huán)。 畢業(yè)前學(xué)好C語言 第二點我要講的是C語言。請注意,我說的是C語言,而不是C++。雖然在實際使用中C語言已經(jīng)越來越罕見,但是它仍然是當(dāng)前程序員的共同語言。C語言讓程序員互相溝通,更重要的是,它比你在大學(xué)中學(xué)到的“現(xiàn)代語言”(比如ML語言、Java語言、Python語言或者其它正在教授的流行垃圾語言)都更接近機器。你至少需要花一個學(xué)期來了解機器原理,否則你永遠不可能在高級語言的層次寫出高效的代碼。你也永遠無法開發(fā)編譯器和操作系統(tǒng),而它們恰恰屬于目前程序員能夠得到的最佳工作之列。別人也永遠不會放心將大型項目的架構(gòu)設(shè)計交給你。我不管你懂多少延續(xù)(continuation)、閉包(closure)、異常處理(exception handling),只要你不能解釋為什么while (*s++ = *t++);這句代碼的作用是復(fù)制字符串,或者不覺得這是世界上對你來說再自然不過的事情,那么你就是在盲目無知的情況下編程。在我看來,這就好像一個醫(yī)生不懂得最基本的解剖學(xué)就在開處方,他看病的根據(jù)完全是因為那些娃娃臉的醫(yī)藥廠商銷售代表說這種藥有用。 畢業(yè)前學(xué)好微觀經(jīng)濟學(xué) 如果你沒有上過任何經(jīng)濟學(xué)課程,那么我首先來做一個超短的評論:經(jīng)濟學(xué)是這樣的學(xué)科之一,剛開始學(xué)的時候轟轟烈烈,有許多有用的、言之有理的理論和可以在真實世界中得到證明的事實,等等;但是,再學(xué)下去就每況愈下,有用的東西就不多了。經(jīng)濟學(xué)一開始那個有用的部分正是微觀經(jīng)濟學(xué),它是商業(yè)領(lǐng)域所有重要理論的基礎(chǔ)。跟在微觀經(jīng)濟學(xué)后面的東西就不行了。你接下來學(xué)的是宏觀經(jīng)濟學(xué),如果你愿意,盡管跳過去,也不會有什么損失。宏觀經(jīng)濟學(xué)開頭的部分是利息理論,內(nèi)容比方說是利率與失業(yè)之間的關(guān)系,但是怎么說呢,看上去這部分里面還沒有被證實的東西多于已經(jīng)被證實的東西。學(xué)完這部分,后面的內(nèi)容越來越糟糕,許多經(jīng)濟學(xué)專業(yè)的學(xué)生實際上都變成在搞物理學(xué),因為這樣才能在華爾街上找到更好的工作。但是不管怎樣,你一定要去學(xué)微觀經(jīng)濟學(xué),因為你必須搞懂供給和需求,你必須明白競爭優(yōu)勢,你必須理解什么是凈現(xiàn)值(NPV),什么是貼現(xiàn),什么是邊際效用。只有這樣,你才會懂得為什么生意是現(xiàn)在這種做法。 為什么計算機系的學(xué)生也應(yīng)該學(xué)經(jīng)濟學(xué)?因為,從經(jīng)營一家公司的角度來看,比起那些不懂的程序員,一個理解基本商業(yè)規(guī)則的程序員將會更有價值。就是這么簡單。我無法告訴你有多少次我是那樣地充滿挫折感,因為我看到了太多的提出一些瘋狂的想法的程序員,這些想法在代碼上也許可行,但在資本主義世界中毫無意義。如果你懂得商業(yè)規(guī)則,你就是一個更有價值的程序員,你會因此得到回報的,但是前提是你要去學(xué)習(xí)微觀經(jīng)濟學(xué)。 不要因為枯燥就不選修非計算機專業(yè)的課程。 想提高GPA績點的一個好方法就是多選修非計算機系的課程。請千萬不要低估你的GPA的重大意義。千千萬萬的人事經(jīng)理和招聘人員在拿到一份簡歷的時候,第一眼就會去看GPA,包括我也是這樣。我們不會為這種做法道歉。為什么?因為GPA不反映單個的成績,而是代表了許多個教授在一段很長的時間中,在不同的情況下,對你的表現(xiàn)的一個總的評估。SAT成績難道不夠嗎?哈,那只不過是一場幾個小時的測試罷了。GPA中包括了四年大學(xué)期間你的小論文、期中考試和課堂表現(xiàn),總數(shù)有幾百次之多。當(dāng)然,GPA也有自己的問題,不是百分之百準(zhǔn)確。比如,這些年來,老師對學(xué)生的打分越來越寬松,學(xué)習(xí)成績有通貨膨脹的趨勢。再比如,GPA無法反映課程的難度,沒人能夠看出你的GPA是來自無名社區(qū)大學(xué)家政系的輕松課程還是來自加州理工學(xué)院針對研究生的量子力學(xué)課程。漸漸地,我形成了一套自己的做法,首先我會過濾掉所有來自社區(qū)大學(xué)、GPA低于2.5的簡歷,然后我會要求剩下的人給我寄成績單和推薦信。我再從中發(fā)現(xiàn)那些成績一貫優(yōu)秀的人,而不是那些僅僅在計算機系課程中得到高分的人。 為什么我要關(guān)心某人的“歐洲歷史”課程成績呢,畢竟作為雇主我要找的應(yīng)該是程序員???何況,歷史是那么枯燥,不得高分很正常。哦,這么說來,你的意思是我應(yīng)該雇用你,而不用考慮一旦工作變得枯燥你會不會努力工作?別忘了,在編程工作中也有很枯燥的東西。每一項工作都有枯燥難耐的時刻。我不想雇用那些只想干有趣事情的人。 選修有大量編程實踐的課程 我依然清楚記得我發(fā)誓絕不讀研究生的那一刻。那是在一門叫做“動態(tài)邏輯”的課程上,教師是活力十足的耶魯大學(xué)教授Lenore Zuck,她是計算機系那些聰明的老師中最聰明的人之一。 如今, 由于記憶力糟糕, 我已經(jīng)差不多把這門課的內(nèi)容忘光了,但是不管怎么說,在這里我還是想要對付著說一下。大致上,形式邏輯的意思是說,如果條件成立,你就能證明結(jié)論也成立。比如,根據(jù)形式邏輯,已知“只要成績好,就能被雇用”,然后假定“Johnny的成績好”,你就可以得到一個嶄新的結(jié)論“Johnny會被雇用”。這完全是經(jīng)典方法。但是,一個解構(gòu)主義者(deconstructionist)只需要10秒鐘就能破壞形式邏輯中所有有用的東西。這樣一來,留給你的只是一些趣味性,而不是實用性。 現(xiàn)在再來說動態(tài)邏輯。它與形式邏輯其實是一回事,但是必須再多考慮時間因素。比如,“你打開燈之后,就能看見自己的鞋子”,已知“燈以前是亮的”,那么這就意味著“你看見了自己的鞋子”。 對于像Zuck教授那樣聰明的理論家,動態(tài)邏輯充滿了吸引力,因為它看上去很有希望讓你在形式上證明一些計算機程序的相關(guān)理論問題。這樣做說不定很有用。比如,你可以用它在形式上證明,火星漫游車的閃存卡不會發(fā)生溢出(overflow)問題,不會因而整天一遍又一遍地重啟,耽誤了它在那顆赤紅色的星球上漫游尋找火星人馬文(Marvin the Martian)。 在第一堂課上,Zuck博士寫滿了整整兩面黑板,甚至黑板旁邊的墻上都寫上了很多證明步驟。需要證明的問題是,有一個控制燈泡的開關(guān),現(xiàn)在燈泡沒有亮,這時你打開了開關(guān),請證明燈泡將會點亮。 整個證明過程復(fù)雜得不可思議,處處都是陷阱,必須十分小心。保證這個證明不出錯太困難了,還不如直接相信打開開關(guān)燈就會亮。真的,雖然證明過程寫滿了許多塊黑板,但是還是有許多中間步驟被省略了,因為如果要從形式邏輯上完整證明所有步驟,那就瑣碎得無法形容了。許多步驟是用各種經(jīng)典的邏輯證明方法推導(dǎo)得到的,包括歸納法、反證法等,甚至有些部分還是由旁聽的研究生證明的。 留給我們的課后作業(yè)是證明逆命題:如果燈原來是關(guān)著的,現(xiàn)在卻亮了,那么請證明開關(guān)的狀態(tài)一定同原來相反。 我動手開始證明,我真的去證明了。 我在圖書館里待了很長時間。 我對照著Zuck博士的原始證明想依樣畫葫蘆。研究了幾個小時之后,我在其中發(fā)現(xiàn)了一個錯誤。可能我抄寫的時候抄錯了,但是這使得我想通了一件事。如果花費3個小時,寫滿了一塊又一塊的黑板,每一秒鐘都可能出錯,最后能夠證明的卻只是一個很瑣碎的結(jié)論,那么這種方式有多大的實用性呢?在活生生、充滿趣味的現(xiàn)實世界中,你永遠都不會有機會使用它。 但是,動態(tài)邏輯的理論家們對這一點不感興趣。他們看上它不是因為它有用,而是因為它可以為他們帶來終身教職。 我放棄了這門課,并且發(fā)誓絕不會去讀計算機科學(xué)的研究生。 這個故事告訴我們,計算機科學(xué)與軟件開發(fā)不是一回事。如果你真的非常幸運,你的學(xué)??赡軙_設(shè)很像樣的軟件開發(fā)課程。但是另一種可能是,你的學(xué)校根本不教你在現(xiàn)實中如何編程,因為精英學(xué)校都覺得,教授工作技能最好留給職業(yè)技術(shù)學(xué)校、犯人重返社會的培訓(xùn)項目去做。你到處都能學(xué)怎么寫代碼。別忘了,我們是耶魯大學(xué),我們的使命是培養(yǎng)未來的世界領(lǐng)袖。你交了16萬美元的學(xué)費,卻在學(xué)循環(huán)語句的寫法,這怎么可以?你以為這是什么地方,難道是機場沿途的酒店里臨時拼湊起來不靠譜的Java語言培訓(xùn)班?哼哼。 麻煩在于我們沒有一種真正教授軟件開發(fā)的專門學(xué)校。你如果想成為一個程序員,你可能只能選擇計算機科學(xué)專業(yè)。這是一個不錯的專業(yè),但是它同軟件開發(fā)不是一回事。在那些400等級的課程代號中,去尋找名稱中帶有“Practicum”這個詞的課程吧(編者注:指供人實習(xí)的課程)。不要被這個拉丁語單詞嚇倒,這些都是有用的課程,之所以起這種名字,只是為了讓那些文縐縐、裝腔作勢、滿嘴胡說八道的公司經(jīng)理們覺得高深莫測。 別擔(dān)心所有工作都被印度人搶走 我首先要說的是,如果你本身就已經(jīng)在印度了,或者你就是印度人,那么你真的毫無必要去想這件事,根本不用琢磨所有的工作機會是不是都跑到了印度。那些都是非常好的工作,好好地享受吧,祝你身體健康。 但是,我不斷聽說計算機系的入學(xué)人數(shù)下降得很厲害,已經(jīng)到了危險的程度。根據(jù)我聽到的說法,其中的一個原因是“學(xué)生們不愿去學(xué)一個工作機會都流向印度的專業(yè)”。這種擔(dān)心大錯特錯,有很多理由可以反駁。首先,根據(jù)一時性的商業(yè)潮流決定個人的職業(yè)選擇,這是愚蠢的。其次,即使編程工作無一幸存地都流向了印度和中國,但是學(xué)習(xí)編程本身依然是一種第一流的素質(zhì)訓(xùn)練,可以為各種超級有趣的工作打下基礎(chǔ),比如業(yè)務(wù)流程工程(business process engineering)。再次,不管是在美國還是在印度,真正優(yōu)秀的程序員依然是非常非常短缺的,這一點請相信我。不錯,確實有相當(dāng)一批失業(yè)的IT從業(yè)者在那里鼓噪,抱怨他們長時間找不到工作,但是你知道嗎?即使冒著觸怒這些人的風(fēng)險,我還是要說,真正優(yōu)秀的程序員根本不會失業(yè)。最后,你還能找到更好的專業(yè)嗎?你覺得什么專業(yè)好?主修歷史學(xué)?如果那樣,你畢業(yè)的時候就會發(fā)現(xiàn),根本沒有其他選擇,只能去法學(xué)院。不過我倒是知道一件事:99%的律師都痛恨他們的工作,痛恨他們當(dāng)律師的每一分鐘。可是,律師每周的工作時間偏偏長達90小時。就像我前面說過的:如果你喜歡編程,那么你真是受到了上天的眷顧。你是非常幸運的少數(shù)人之一,能夠以自己喜歡的事謀生。 不過說實話,我不覺得學(xué)生們真的有上面的想法。近年來,計算機系入學(xué)人數(shù)的下降只是回到了歷史上的正常水平,因為前些年的互聯(lián)網(wǎng)狂熱使得入學(xué)人數(shù)出現(xiàn)了大泡沫,抬高了基數(shù)。由于這種泡沫,許多并不真的喜歡編程的人也來讀計算機系。他們心里想的是,只要進了計算機系,將來就能找到誘人的高薪工作,就能獲得24歲當(dāng)上CEO、進行IPO的機會。謝天謝地,這些人現(xiàn)在都離計算機系遠遠的了。 找一份好的暑期實習(xí)工作 精明的招聘負責(zé)人都知道,喜歡編程的人高中時就將牙醫(yī)的信息輸入了數(shù)據(jù)庫,進入大學(xué)前就去過三次電腦夏令營,為校報做過內(nèi)容管理系統(tǒng),有過軟件公司的夏季實習(xí)經(jīng)歷。招聘負責(zé)人就是要在你的簡歷上找這些東西。 如果你喜歡編程, 就不要隨便什么工作都答應(yīng),否則你會犯下最大的錯誤。不管是暑期工作,還是兼職或者其他性質(zhì)的工作,只要與編程無關(guān),就不要輕易接受。我知道,其他19歲的孩子都想去購物中心里打工,在那里折疊襯衫。但是你與他們不同,你19歲時就已經(jīng)掌握了一門非常有價值的技能。將時間浪費在折疊襯衫上是很愚蠢的,等到畢業(yè)的時候,你的簡歷上本應(yīng)該寫滿了一大堆與編程相關(guān)的經(jīng)歷。就讓那些財經(jīng)類的畢業(yè)生去租車公司“幫助人們滿足他們租車的需要”吧,你要干的是別的事(在電視中扮演超人的Tom Welling注1除外)。 為了讓你的生活變得更容易一些,也為了強調(diào)這整篇文章完全是為了滿足我的個人目的,我要告訴你,我的公司——Fog Creek軟件公司——提供軟件開發(fā)方面的暑期實習(xí)機會。我們非??粗睾啔v?!氨绕鹌渌镜膶嵙?xí)工作,你在Fog Creek最有可能學(xué)到更多的編寫代碼、軟件開發(fā)、商業(yè)運作方面的知識。”這是去年夏天我們的一個實習(xí)生Ben說的。他會這樣說,并不完全是因為我派了人到他的宿舍讓他這樣說。我們接受實習(xí)申請的截止日期是2月1日。一起來吧。 如果你聽從了我的建議,你還是有可能落得一個悲慘的下場,比如很早就賣掉了微軟公司的股票,再比如拒絕了谷歌公司的工作機會,原因是你想要一間自己的可以關(guān)上門的獨立辦公室,或者做出了其他生命中愚蠢的決定。但是,這些可不是我的錯。我一開始就告訴過你,不要聽我的話。 (注1 : T o m W e l l i n g是一個美國演員, 在電視劇《超人前傳》(Smallville)中扮演超人。該電視劇講述還沒有成長為后來超人的克拉克·肯特少年時代的故事。) 作者簡介: Joel Spolsky,世界最具影響的程序員網(wǎng)志Joel on Software的主人,軟件業(yè)一位旗幟鮮明的思想者,一位傳統(tǒng)軟件管理理念的挑戰(zhàn)者。他創(chuàng)辦的這個網(wǎng)站被程序員譽為“反呆伯特宣言書”,并被翻譯為三十多種語言。Joel畢業(yè)于耶魯大學(xué),隨后即進入微軟公司工作,曾任微軟公司E x c e l 開發(fā)小組項目經(jīng)理。現(xiàn)在他在自己創(chuàng)辦的Fog Creek軟件公司任CEO。此外,他與人合辦的Stack Overflow已經(jīng)成為如今最熱門的技術(shù)網(wǎng)站。
            posted @ 2010-01-28 21:48 chaosuper 閱讀(110) | 評論 (0)編輯 收藏

            link: http://www.cnblogs.com/tomin/archive/2008/11/18/1335730.html
            如果你已經(jīng)有較多的面向?qū)ο箝_發(fā)經(jīng)驗,跳過以下這兩步:   第一步 掌握一門.NET面向?qū)ο笳Z言,C#或VB.NET 我強烈反對在沒系統(tǒng)學(xué)過一門面向?qū)ο?OO)語言的前提下去學(xué)ASP.NET。 ASP.NET是一個全面向?qū)ο蟮募夹g(shù),不懂OO,那絕對學(xué)不下去!   第二步 對.NET Framework類庫有一定的了解 可以通過開發(fā)Windows Form應(yīng)用程序來學(xué)習(xí).NET Framework。ASP.NET是建構(gòu)在.NET Framework之上的技術(shù),你對.NET Framework了解得越深,學(xué)習(xí)ASP.NET就越快。 舉個例子:下面簡單列出幾個對掌握ASP.NET非常重要的概念: 對象的內(nèi)存模型,委托,事件,多線程,程序集和應(yīng)用程序域,安全模型 .NET Framework當(dāng)然還有許多其它的東西,但不理解與把握清楚上述這些東西,是很難真正把握ASP.NET的。 出于急迫的心情與現(xiàn)實的考慮,不少人沒有扎實的面向?qū)ο蠡A(chǔ)就想直接學(xué)習(xí)ASP.NET,其結(jié)果只能是欲速則不達。 在具備了OO基礎(chǔ)之后,以下是具體的學(xué)習(xí)ASP.NET技術(shù)步驟。   第一步:學(xué)習(xí)HTML與CSS   這并不需要去學(xué)一大堆的諸如Dreamweaver,F(xiàn)irework之類的各種網(wǎng)頁設(shè)計工具,關(guān)鍵是理解HTML網(wǎng)頁嵌套的block結(jié)構(gòu)與CSS的box模型。許多ASP.NET控件最后都必須轉(zhuǎn)化為HTML。而且,div+CSS是當(dāng)前主流的網(wǎng)頁布局模型。 學(xué)習(xí)這部分時,關(guān)鍵在于理解概念,而不需要將精力花在美化頁面的許多技巧上,那是網(wǎng)站美工的工作,不是程序員的工作。   第二步:學(xué)習(xí)JavaScript   JavaScript不是Java,它主要運行于瀏覽器端。可以完成許多工作,功能也很強大:比如它將客戶端網(wǎng)頁中的HTML元素看成一棵樹,可以編寫代碼訪問并修改樹節(jié)點,動態(tài)生成新的HTML代碼,從而達到動態(tài)修改網(wǎng)頁顯示特性的目的。   JavaScript在目前的網(wǎng)站開發(fā)中用得很多,非常重要。   另外,它也是目前非常流行的AJAX技術(shù)的基礎(chǔ)。   第三步:學(xué)習(xí)計算機網(wǎng)絡(luò)原理   找一本大學(xué)<計算機網(wǎng)絡(luò)>教材,重點看看它的有關(guān)互聯(lián)網(wǎng)的部分,了解一些域名解析和HTTP協(xié)議等知識。這是進行互聯(lián)網(wǎng)開發(fā)的理論基礎(chǔ)。   第四步:學(xué)習(xí)ASP.NET表示層技術(shù),會設(shè)計Web頁面   需要結(jié)合先前打好的面向?qū)ο蠹夹g(shù)的基礎(chǔ),至少掌握以下內(nèi)容:   (1) 各種Web控件的使用方法,   (2) 理解信息在網(wǎng)頁中的傳送方式,比如Cookie,ViewState,Session等的使用。   (3) ASP.NET應(yīng)用程序與網(wǎng)頁的生命周期,以及相關(guān)對象(比如httpcontext,response,request)的用途。   (4) ASP.NET實現(xiàn)事件驅(qū)動的內(nèi)幕   (5) 自定義用戶控件   再次強調(diào)一下,沒有OO基礎(chǔ),很難掌握上述技術(shù),就只能被這些東東牽著鼻子走了,會很被動。   第五步 掌握數(shù)據(jù)庫技術(shù)   具體地說,要學(xué)習(xí)以下內(nèi)容:   (1) 學(xué)會使用SQL Server 2005:不要求精通它的各種工具與管理配置技術(shù),但至少知道如何連接,如何建表,如何創(chuàng)建存儲過程   (2) 學(xué)習(xí)ADO.NET,掌握使用代碼人工訪問數(shù)據(jù)庫(別用VS2005的向?qū)?的方法   (3) 學(xué)習(xí)數(shù)據(jù)綁定控件的使用   第六步 理解多層架構(gòu)   這時,先前在OO學(xué)習(xí)階段涉及到的程序集與應(yīng)用程序域等就派上用場了,現(xiàn)在,網(wǎng)站架構(gòu)大多采用多層架構(gòu):表示層、業(yè)務(wù)邏輯層、數(shù)據(jù)存取層以及數(shù)據(jù)庫本身。   可以先上網(wǎng)找一此多層架構(gòu)的資料看,再找一個現(xiàn)成的比較復(fù)雜的開源ASP.NET項目分析一下其架構(gòu)就差不多了?;旧隙际且粋€套路,到處應(yīng)用。   有的朋友問:學(xué)習(xí)架構(gòu)是不是必須學(xué)習(xí)設(shè)計模式。   我的看法是:不必!當(dāng)然,你如果學(xué)習(xí)過設(shè)計模式,那當(dāng)然更好。但在實際開發(fā)中,如果只想著機械地套用某種模式,反而起不到好的結(jié)果。我的觀點:在學(xué)習(xí)設(shè)計模式時要多思多悟,其思想就會漸漸地融入你的大腦,在真實的設(shè)計實踐中,忘掉所有的寫在書上的模式,一切從實際出發(fā),相信你的直覺,只要達到設(shè)計要求的方案就是可行的方案,事實上,你這樣做了之后,回過頭來再看,會發(fā)現(xiàn)你的設(shè)計往往暗合設(shè)計模式的理論。   第七步 學(xué)習(xí)XML與Web Service   先了解XML的基礎(chǔ)知識,找本講XML的書看一下就差不多了,然后,再學(xué)習(xí)Web Service。Web Service其實可類比為遠程方法調(diào)用(以XML格式表達的調(diào)用信息)。   學(xué) 到了這里,如果你還有興趣,不妨再去看看SOA,不過SOA的資料都是理論與概念,看起來比較郁悶,而且離實際開發(fā)可能比較遠。所以,這是可選項。   第八步 學(xué)習(xí)AJAX   學(xué)習(xí)AJAX的主要目的是創(chuàng)建具有更豐富特性的Web表示層,而經(jīng)過前面七步的學(xué)習(xí),到此再學(xué)習(xí)AJAX已水到渠成,所有的基礎(chǔ)都已具備,不會有太大的問題了。   在基礎(chǔ)未具備的前提下直接學(xué)AJAX,就象“浮沙之上筑高臺”,所以,將AJAX的學(xué)習(xí)次序安排在這里。   第九步 學(xué)習(xí)RIA技術(shù)   RIA:Rich internet application,可看成是將C/S與B/S優(yōu)點合二為一的嘗試。就具體技術(shù)來說,主要指微軟的Silverlight(WPF_E),畢竟前頭一路行來都是微軟路線。   不過目前學(xué)習(xí)它主要是為了技術(shù)儲備。估計此技術(shù)的普及需要2到3年的時間,因為預(yù)裝Vista的機器今年才開始大賣。
            posted @ 2010-01-26 16:53 chaosuper 閱讀(112) | 評論 (0)編輯 收藏

            Editor bluefish vi/vim/gvim gedit kate Compiler gcc/g++ Debugger gdb
            http://blog.chinaunix.net/u3/94284/article.html
            posted @ 2010-01-26 15:42 chaosuper 閱讀(112) | 評論 (0)編輯 收藏

            珍惜大好時間 努力 積極主動的學(xué)習(xí)新的知識 提高實際的能力和知識積累 http://blog.csdn.net/metasearch/category/368809.aspx
            posted @ 2010-01-26 11:10 chaosuper 閱讀(73) | 評論 (0)編輯 收藏

            僅列出標(biāo)題
            共12頁: 1 2 3 4 5 6 7 8 9 Last 
            国产综合成人久久大片91| 久久国产福利免费| 久久精品草草草| 久久久久亚洲AV成人网人人软件| 欧美与黑人午夜性猛交久久久| 无码国内精品久久综合88| 久久久久久亚洲Av无码精品专口| 中文字幕亚洲综合久久2| 一极黄色视频久久网站| 欧洲人妻丰满av无码久久不卡| 91精品国产高清久久久久久国产嫩草 | 久久久久久av无码免费看大片 | 国产精品美女久久久久网| 精品无码人妻久久久久久| 国产亚洲精品久久久久秋霞| 精品久久久久久无码国产| 99久久久精品免费观看国产| 久久国内免费视频| 国产精品熟女福利久久AV| 亚洲伊人久久精品影院| 四虎亚洲国产成人久久精品| 18岁日韩内射颜射午夜久久成人| 亚洲中文字幕无码久久精品1 | 国产精品18久久久久久vr| 久久久久波多野结衣高潮| 性做久久久久久免费观看| 久久播电影网| 91麻豆精品国产91久久久久久| 久久精品黄AA片一区二区三区 | 久久这里只有精品视频99| 99久久国产亚洲高清观看2024 | 久久天天躁夜夜躁狠狠躁2022| 精品无码人妻久久久久久| AAA级久久久精品无码区| 婷婷综合久久狠狠色99h| 国产成人精品久久二区二区| 国产精品一区二区久久国产 | 精品综合久久久久久98| 久久热这里只有精品在线观看| 久久这里都是精品| 亚洲色大成网站WWW久久九九|