android軟件
posted @ 2008-11-20 16:24 LukeW 閱讀(36) | 評論 (0) | 編輯 收藏
Look into it ~present
隨筆 - 32, 文章 - 0, 評論 - 3, 引用 - 0
|
linux設(shè)備模型
Linux
2.6內(nèi)核的一個重要特色是提供了統(tǒng)一的內(nèi)核設(shè)備模型。隨著技術(shù)的不斷進(jìn)步,系統(tǒng)的拓?fù)浣Y(jié)構(gòu)越來越復(fù)雜,對智能電源管理、熱插拔以及plug and
play的支持要求也越來越高,2.4內(nèi)核已經(jīng)難以滿足這些需求。為適應(yīng)這種形勢的需要,2.6內(nèi)核開發(fā)了全新的設(shè)備模型。
1. Sysfs文件系統(tǒng) Sysfs文件系統(tǒng)是一個類似于proc文件系統(tǒng)的特殊文件系統(tǒng),用于將系統(tǒng)中的設(shè)備組織成層次結(jié)構(gòu),并向用戶模式程序提供詳細(xì)的內(nèi)核數(shù)據(jù)結(jié)構(gòu)信息。其頂層目錄主要有: Block目錄:包含所有的塊設(shè)備 Devices目錄:包含系統(tǒng)所有的設(shè)備,并根據(jù)設(shè)備掛接的總線類型組織成層次結(jié)構(gòu) Bus目錄:包含系統(tǒng)中所有的總線類型 Drivers目錄:包括內(nèi)核中所有已注冊的設(shè)備驅(qū)動程序 Class目錄:系統(tǒng)中的設(shè)備類型(如網(wǎng)卡設(shè)備,聲卡設(shè)備等) 2. 內(nèi)核對象機(jī)制關(guān)鍵數(shù)據(jù)結(jié)構(gòu) 2.1 kobject內(nèi)核對象 Kobject 是Linux 2.6引入的新的設(shè)備管理機(jī)制,在內(nèi)核中由struct kobject表示。通過這個數(shù)據(jù)結(jié)構(gòu)使所有設(shè)備在底層都具有統(tǒng)一的接口,kobject提供基本的對象管理,是構(gòu)成Linux 2.6設(shè)備模型的核心結(jié)構(gòu),它與sysfs文件系統(tǒng)緊密關(guān)聯(lián),每個在內(nèi)核中注冊的kobject對象都對應(yīng)于sysfs文件系統(tǒng)中的一個目錄。 Kobject結(jié)構(gòu)定義為: struct kobject {
char * k_name; // 指向設(shè)備名稱的指針 char name[KOBJ_NAME_LEN]; // 設(shè)備名稱 struct kref kref; // 對象引用計(jì)數(shù) struct list_head entry; // 掛接到所在kset中去的單元 struct kobject * parent; // 指向父對象的指針 struct kset * kset; // 所屬kset的指針 struct kobj_type * ktype; // 指向其對象類型描述符的指針 struct dentry * dentry; // sysfs文件系統(tǒng)中與該對象對應(yīng)的文件節(jié)點(diǎn)路徑指針 }; 其中的kref域表示該對象引用的計(jì)數(shù),內(nèi)核通過kref實(shí)現(xiàn)對象引用計(jì)數(shù)管理,內(nèi)核提供兩個函數(shù)kobject_get()、kobject_put()分別用于增加和減少引用計(jì)數(shù),當(dāng)引用計(jì)數(shù)為0時,所有該對象使用的資源將被釋放。 Ktype 域是一個指向kobj_type結(jié)構(gòu)的指針,表示該對象的類型。Kobj_type數(shù)據(jù)結(jié)構(gòu)包含三個域:一個release方法用于釋放kobject占 用的資源;一個sysfs_ops指針指向sysfs操作表和一個sysfs文件系統(tǒng)缺省屬性列表。Sysfs操作表包括兩個函數(shù)store()和 show()。當(dāng)用戶態(tài)讀取屬性時,show()函數(shù)被調(diào)用,該函數(shù)編碼指定屬性值存入buffer中返回給用戶態(tài);而store()函數(shù)用于存儲用戶態(tài) 傳入的屬性值。 2.2 kset內(nèi)核對象集合 Kobject通常通過kset組織成層次化的結(jié)構(gòu),kset是具有相同類型的kobject的集合,在內(nèi)核中用kset數(shù)據(jù)結(jié)構(gòu)表示,定義為: struct kset {
struct subsystem * subsys; // 所在的subsystem的指針 struct kobj_type * ktype; // 指向該kset對象類型描述符的指針 struct list_head list; // 用于連接該kset中所有kobject的鏈表頭 struct kobject kobj; // 嵌入的kobject struct kset_hotplug_ops * hotplug_ops; // 指向熱插拔操作表的指針 }; 包 含在kset中的所有kobject被組織成一個雙向循環(huán)鏈表,list域正是該鏈表的頭。Ktype域指向一個kobj_type結(jié)構(gòu),被該 kset中的所有kobject共享,表示這些對象的類型。Kset數(shù)據(jù)結(jié)構(gòu)還內(nèi)嵌了一個kobject對象(由kobj域表示),所有屬于這個kset 的kobject對象的parent域均指向這個內(nèi)嵌的對象。此外,kset還依賴于kobj維護(hù)引用計(jì)數(shù):kset的引用計(jì)數(shù)實(shí)際上就是內(nèi)嵌的 kobject對象的引用計(jì)數(shù)。 2.3 subsystem內(nèi)核對象子系統(tǒng) Subsystem是一系列kset的集合,描述系統(tǒng)中某一 類設(shè)備子系統(tǒng),如block_subsys表示所有的塊設(shè)備,對應(yīng)于sysfs文件系統(tǒng)中的block目錄。類似的,devices_subsys對應(yīng)于 sysfs中的devices目錄,描述系統(tǒng)中所有的設(shè)備。Subsystem由struct subsystem數(shù)據(jù)結(jié)構(gòu)描述,定義為: struct subsystem {
struct kset kset; // 內(nèi)嵌的kset對象 struct rw_semaphore rwsem; // 互斥訪問信號量 }; 每 個kset必須屬于某個subsystem,通過設(shè)置kset結(jié)構(gòu)中的subsys域指向指定的subsystem可以將一個kset加入到該 subsystem。所有掛接到同一subsystem的kset共享同一個rwsem信號量,用于同步訪問kset中的鏈表。 3. 內(nèi)核對象機(jī)制主要相關(guān)函數(shù) 針對內(nèi)核對象不同層次的數(shù)據(jù)結(jié)構(gòu),linux 2.6內(nèi)核定義了一系列操作函數(shù),定義于lib/kobject.c文件中。 3.1 kobject相關(guān)函數(shù) void kobject_init(struct kobject * kobj);// kobject初始化函數(shù)。設(shè)置kobject引用計(jì)數(shù)為1,entry域指向自身,其所屬kset引用計(jì)數(shù)加1
int kobject_set_name(struct kobject *kobj, const char *format, ![]() void kobject_cleanup(struct kobject * kobj); void kobject_release(struct kref *kref);// kobject清除函數(shù)。當(dāng)其引用計(jì)數(shù)為0時,釋放對象占用的資源。 struct kobject *kobject_get(struct kobject *kobj);// 將kobj 對象的引用計(jì)數(shù)加1,同時返回該對象的指針。 void kobject_put(struct kobject * kobj);// 將kobj對象的引用計(jì)數(shù)減1,如果引用計(jì)數(shù)降為0,則調(diào)用kobject_release()釋放該kobject對象。 int kobject_add(struct kobject * kobj);// 將kobj對象加入Linux設(shè)備層次。掛接該kobject對象到kset的list鏈中,增加父目錄各級kobject的引用計(jì)數(shù),在其parent指向的目錄下創(chuàng)建文件節(jié)點(diǎn),并啟動該類型內(nèi)核對象的hotplug函數(shù)。 int kobject_register(struct kobject * kobj);// kobject注冊函數(shù)。通過調(diào)用kobject_init()初始化kobj,再調(diào)用kobject_add()完成該內(nèi)核對象的注冊。 void kobject_del(struct kobject * kobj);// 從Linux設(shè)備層次(hierarchy)中刪除kobj對象。 void kobject_unregister(struct kobject * kobj);// kobject注銷函數(shù)。與kobject_register()相反,它首先調(diào)用kobject_del從設(shè)備層次中刪除該對象,再調(diào)用kobject_put()減少該對象的引用計(jì)數(shù),如果引用計(jì)數(shù)降為0,則釋放該kobject對象。 3.2 kset相關(guān)函數(shù) 與kobject 相似,kset_init()完成指定kset的初始化,kset_get()和kset_put()分別增加和減少kset對象的引用計(jì)數(shù)。 Kset_add()和kset_del()函數(shù)分別實(shí)現(xiàn)將指定keset對象加入設(shè)備層次和從其中刪除;kset_register()函數(shù)完成 kset的注冊而kset_unregister()函數(shù)則完成kset的注銷。 3.3 subsystem相關(guān)函數(shù) subsystem有一組完成類似的函數(shù),分別是: void subsystem_init(struct subsystem *subsys);
int subsystem_register(struct subsystem *subsys); void subsystem_unregister(struct subsystem *subsys); struct subsystem *subsys_get(struct subsystem *subsys) void subsys_put(struct subsystem *subsys); 4. 設(shè)備模型組件 在上述內(nèi)核對象機(jī)制的基礎(chǔ)上,Linux的設(shè)備模型建立在幾個關(guān)鍵組件的基礎(chǔ)上,下面我們詳細(xì)闡述這些組件。 4.1 devices 系統(tǒng)中的任一設(shè)備在設(shè)備模型中都由一個device對象描述,其對應(yīng)的數(shù)據(jù)結(jié)構(gòu)struct device定義為: struct device {
struct list_head g_list; struct list_head node; struct list_head bus_list; struct list_head driver_list; struct list_head children; struct device *parent; struct kobject kobj; char bus_id[BUS_ID_SIZE]; struct bus_type *bus; struct device_driver *driver; void *driver_data; /* Several fields omitted */ }; g_list 將該device對象掛接到全局設(shè)備鏈表中,所有的device對象都包含在devices_subsys中,并組織成層次結(jié)構(gòu)。Node域?qū)⒃搶ο髵旖? 到其兄弟對象的鏈表中,而bus_list則用于將連接到相同總線上的設(shè)備組織成鏈表,driver_list則將同一驅(qū)動程序管理的所有設(shè)備組織為鏈 表。此外,children域指向該device對象子對象鏈表頭,parent域則指向父對象。Device對象還內(nèi)嵌一個kobject對象,用于引 用計(jì)數(shù)管理并通過它實(shí)現(xiàn)設(shè)備層次結(jié)構(gòu)。Driver域指向管理該設(shè)備的驅(qū)動程序?qū)ο螅鴇river_data則是提供給驅(qū)動程序的數(shù)據(jù)。Bus域描述設(shè) 備所連接的總線類型。 內(nèi)核提供了相應(yīng)的函數(shù)用于操作device對象。其中Device_register()函數(shù)將一個新的device對象插 入設(shè)備模型,并自動在/sys/devices下創(chuàng)建一個對應(yīng)的目錄。Device_unregister()完成相反的操作,注銷設(shè)備對象。 Get_device()和put_device()分別增加與減少設(shè)備對象的引用計(jì)數(shù)。通常device結(jié)構(gòu)不單獨(dú)使用,而是包含在更大的結(jié)構(gòu)中作為一 個子結(jié)構(gòu)使用,比如描述PCI設(shè)備的struct pci_dev,其中的dev域就是一個device對象。 4.2 drivers 系統(tǒng)中的每個驅(qū)動程序由一個device_driver對象描述,對應(yīng)的數(shù)據(jù)結(jié)構(gòu)定義為: struct device_driver {
char *name; // 設(shè)備驅(qū)動程序的名稱 struct bus_type *bus; // 該驅(qū)動所管理的設(shè)備掛接的總線類型 struct kobject kobj; // 內(nèi)嵌kobject對象 struct list_head devices; // 該驅(qū)動所管理的設(shè)備鏈表頭 int (*probe)(struct device *dev); // 指向設(shè)備探測函數(shù),用于探測設(shè)備是否可以被該驅(qū)動程序管理 int (*remove)(struct device *dev); // 用于刪除設(shè)備的函數(shù) /* some fields omitted*/ }; 與device 結(jié)構(gòu)類似,device_driver對象依靠內(nèi)嵌的kobject對象實(shí)現(xiàn)引用計(jì)數(shù)管理和層次結(jié)構(gòu)組織。內(nèi)核提供類似的函數(shù)用于操作 device_driver對象,如get_driver()增加引用計(jì)數(shù),driver_register()用于向設(shè)備模型插入新的driver對 象,同時在sysfs文件系統(tǒng)中創(chuàng)建對應(yīng)的目錄。Device_driver()結(jié)構(gòu)還包括幾個函數(shù),用于處理熱拔插、即插即用和電源管理事件。 4.3 buses 系統(tǒng)中總線由struct bus_type描述,定義為: struct bus_type {
char * name; // 總線類型的名稱 struct subsystem subsys; // 與該總線相關(guān)的subsystem struct kset drivers; // 所有與該總線相關(guān)的驅(qū)動程序集合 struct kset devices; // 所有掛接在該總線上的設(shè)備集合 struct bus_attribute * bus_attrs; // 總線屬性 struct device_attribute * dev_attrs; // 設(shè)備屬性 struct driver_attribute * drv_attrs; // 驅(qū)動程序?qū)傩?/span> int (*match)(struct device * dev, struct device_driver * drv); int (*hotplug) (struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size); int (*suspend)(struct device * dev, u32 state); int (*resume)(struct device * dev); }; 每 個bus_type對象都內(nèi)嵌一個subsystem對象,bus_subsys對象管理系統(tǒng)中所有總線類型的subsystem對象。每個 bus_type對象都對應(yīng)/sys/bus目錄下的一個子目錄,如PCI總線類型對應(yīng)于/sys/bus/pci。在每個這樣的目錄下都存在兩個子目 錄:devices和drivers(分別對應(yīng)于bus_type結(jié)構(gòu)中的devices和drivers域)。其中devices子目錄描述連接在該總 線上的所有設(shè)備,而drivers目錄則描述與該總線關(guān)聯(lián)的所有驅(qū)動程序。與device_driver對象類似,bus_type結(jié)構(gòu)還包含幾個函數(shù) (match()、hotplug()等)處理相應(yīng)的熱插拔、即插即拔和電源管理事件。 4.4 classes 系統(tǒng)中的設(shè)備類由 struct class描述,表示某一類設(shè)備。所有的class對象都屬于class_subsys子系統(tǒng),對應(yīng)于sysfs文件系統(tǒng)中的/sys/class目錄。 每個class對象包括一個class_device鏈表,每個class_device對象表示一個邏輯設(shè)備,并通過struct class_device中的dev域(一個指向struct device的指針)關(guān)聯(lián)一個物理設(shè)備。這樣,一個邏輯設(shè)備總是對應(yīng)于一個物理設(shè)備,但是一個物理設(shè)備卻可能對應(yīng)于多個邏輯設(shè)備。此外,class結(jié)構(gòu)中 還包括用于處理熱插拔、即插即拔和電源管理事件的函數(shù),這與device對象和driver對象相似。 posted @ 2008-11-12 23:14 LukeW 閱讀(189) | 評論 (0) | 編輯 收藏 位運(yùn)算
C中的位運(yùn)算
能夠運(yùn)用到任何整形的數(shù)據(jù)類型上(包括char, int), 無論有沒有short, long, unsigned這樣的限定詞. 位運(yùn)算的應(yīng)用 // 交換指針變量x,y所指向的存儲位置處存放的值
// 優(yōu)勢是不需要第三個位置來臨時存儲另一個值 // 但是這個方法并沒有明顯的性能優(yōu)勢,只是一個智力上的消遣 void inplace_swap(int *x, int *y) { *x = *x ^ *y; *x = *x ^ *y; *x = *x ^ *y; } 位運(yùn)算常見用法: 實(shí)現(xiàn)掩碼運(yùn)算 ----------------------------------- Java中的位運(yùn)算 posted @ 2008-11-12 13:53 LukeW 閱讀(135) | 評論 (0) | 編輯 收藏 大端小端 -- 各系統(tǒng)及機(jī)器的信息表示
因?yàn)楝F(xiàn)行的計(jì)算機(jī)都是以八位一個字節(jié)為存儲單位,那么一個16位的整數(shù),也就是C語言中的short,在內(nèi)存中可能有兩種存儲順序big-
endian和litte-endian.考慮一個short整數(shù)0x3132(0x32是低位,0x31是高位),把它賦值給一個short變量,那么它在內(nèi)存中的存儲可 能有如下兩種情況: 大端字節(jié)(Big-endian): short變量地址 0x1000 0x1001 ___________________________________ | | | 0x31 | 0x32 |________________ | ________________ 高位字節(jié)在低位字節(jié)的前面,也就是高位在內(nèi)存地址低的一端.可以這樣記住(大端->高位->在前->正常的邏輯順序) 小端字節(jié)(little-endian): short變量地址 0x1000 0x1001 _____________________________________ | | | 0x32 | 0x31 |________________ | __________________ 低位字節(jié)在高位字節(jié)的前面,也就是低位在內(nèi)存地址低的一端.可以這樣記住(小端->低位->在前->與正常邏輯順序相反) 可以做個實(shí)驗(yàn) 在windows上下如下程序 #include <stdio.h>
#include <assert.h> void main( void ) { short test; FILE* fp; test = 0x3132; //(31ASIIC碼的’1’,32ASIIC碼的’2’) if ((fp = fopen ("c:""test.txt", "wb")) == NULL) assert(0); fwrite(&test, sizeof(short), 1, fp); fclose(fp); } 然后在C盤下打開test.txt文件,可以看見內(nèi)容是21,而test等于0x3132,可以明顯的看出來x86的字節(jié)順序是低位在前.如果我們 把這段同樣的代碼放到(big-endian)的機(jī)器上執(zhí)行,那么打出來的文件就是12.這在本機(jī)中使用是沒有問題的.但當(dāng)你把這個文件從一 個big- endian機(jī)器復(fù)制到一個little-endian機(jī)器上時就出現(xiàn)問題了. 如上述例子,我們在big-endian的機(jī)器上創(chuàng)建了這個test文件,把其復(fù)制到little-endian的機(jī)器上再用fread讀到一個 short里 面,我們得到的就不再是0x3132而是0x3231了,這樣讀到的數(shù)據(jù)就是錯誤的,所以在兩個字節(jié)順序不一樣的機(jī)器上傳輸數(shù)據(jù)時需要特別 小心字節(jié)順序,理解了字節(jié)順序在可以幫助我們寫出移植行更高的代碼. 正因?yàn)橛凶止?jié)順序的差別,所以在網(wǎng)絡(luò)傳輸?shù)臅r候定義了所有字節(jié)順序相關(guān)的數(shù)據(jù)都使用big-endian,BSD的代碼中定義了四個宏來處 理: #define ntohs(n) //網(wǎng)絡(luò)字節(jié)順序到主機(jī)字節(jié)順序 n代表net, h代表host, s代表short
#define htons(n) //主機(jī)字節(jié)順序到網(wǎng)絡(luò)字節(jié)順序 n代表net, h代表host, s代表short #define ntohl(n) //網(wǎng)絡(luò)字節(jié)順序到主機(jī)字節(jié)順序 n代表net, h代表host, s代表 long #define htonl(n) //主機(jī)字節(jié)順序到網(wǎng)絡(luò)字節(jié)順序 n代表net, h代表host, s代表 long 舉例說明下這其中一個宏的實(shí)現(xiàn): #define sw16(x) "
((short)( " (((short)(x) & (short)0x00ffU) << 8) | " (((short)(x) & (short)0xff00U) >> 8) )) 這里實(shí)現(xiàn)的是一個交換兩個字節(jié)順序.其他幾個宏類似. 我們改寫一下上面的程序 #include <stdio.h>
#include <assert.h> #define sw16(x) " ((short)( " (((short)(x) & (short)0x00ffU) << 8) | " (((short)(x) & (short)0xff00U) >> 8) )) // 因?yàn)閤86下面是低位在前,需要交換一下變成網(wǎng)絡(luò)字節(jié)順序 #define htons(x) sw16(x) void main( void ) { short test; FILE* fp; test = htons(0x3132); //(31ASIIC碼的’1’,32ASIIC碼的’2’) if ((fp = fopen ("c:""test.txt", "wb")) == NULL) assert(0); fwrite(&test, sizeof(short), 1, fp); fclose(fp); } 如果在高字節(jié)在前的機(jī)器上,由于與網(wǎng)絡(luò)字節(jié)順序一致,所以我們什么都不干就可以了,只需要把#define htons(x) sw16(x)宏替 換為 #define htons(x) (x). 一開始我在理解這個問題時,總在想為什么其他數(shù)據(jù)不用交換字節(jié)順序?比如說我們write一塊buffer到文件,最后終于想明白了, 因?yàn)槎际莡nsigned char類型一個字節(jié)一個字節(jié)的寫進(jìn)去,這個順序是固定的,不存在字節(jié)順序的問題. 【用函數(shù)判斷系統(tǒng)是Big Endian還是Little Endian】 bool IsBig_Endian()
//如果字節(jié)序?yàn)閎ig-endian,返回true; //反之為 little-endian,返回false { unsigned short test = 0x1122; if(*( (unsigned char*) &test ) == 0x11) return TRUE; else return FALSE; }//IsBig_Endian() 【打印程序?qū)ο蟮淖止?jié)表示】 // 可在不同平臺與硬件架構(gòu)的機(jī)器中測試運(yùn)行這段代碼,理解大端表示和小端表示的不同.
// 這段代碼使用強(qiáng)制類型轉(zhuǎn)換規(guī)避類型系統(tǒng) #incluede <stdio.h> // 假設(shè)每個字節(jié)都是非負(fù)整數(shù) typedef unsigned char *byte_pointer; void show_bytes(byte_pointer start, int len) { for(int i = 0; i < len; i++) printf(" %.2x", start[i]); printf("\n"); } void show_int(int x) { show_bytes((byte_pointer) &x, sizeof(int)); } void show_float(float x) { show_bytes((byte_pointer) &x, sizeof(float)); } // 在使用相同編碼(如ASCII編碼)的系統(tǒng)中,字符串字節(jié)表示得到的結(jié)果一般是相同的.所以文本數(shù)據(jù)比二進(jìn)制數(shù)據(jù)具有更強(qiáng)的平臺無關(guān)性 void show_string(char *x) { show_bytes((byte_pointer) x, strlen(x)); } void show_pointer(void *x) { show_bytes((byte_pointer) &x, sizeof(void *)); } void test_show_bytes(int val) { int ival = val; float fval = (float)ival; int *pval = &ival; show_int(ival); // 各個機(jī)器因?yàn)榇蠖吮硎竞托《吮硎镜牟煌?從而只是字節(jié)順序不同 show_float(fval); // 各個機(jī)器因?yàn)榇蠖吮硎竞托《吮硎镜牟煌?從而只是字節(jié)順序不同 show_pointer(pval); // 指針值是與機(jī)器相關(guān)的(linux,sun使用4字節(jié)地址, 而alpha使用八字節(jié)地址) } --------------------------------------------- 對于如數(shù)值12345在int型和float型時的編碼表示 posted @ 2008-11-12 11:58 LukeW 閱讀(659) | 評論 (0) | 編輯 收藏 j2me 聯(lián)網(wǎng)技術(shù)分析總結(jié)
基本點(diǎn):
Generic Connections
In the CLDC Generic Connection framework, all connections are created using
the ![]() Figure 1: Connection interface hierarchy
The Connector.open(String);
Here are a few examples: HTTP Connection Connector.open("http://java.sun.com/developer");
Datagram Connection Connector.open("datagram://address:port#");
Communicate with a Port Connector.open("comm:0;baudrate=9600');
Open Files Connector.open("file:/myFile.txt");
The HttpConnection Interface: The HTTP protocol is a request-response application protocol in which the parameters of the request must be set before the request is sent. The connection could be in one of the three following states:
In the setup state the following methods can be invoked:
For example, suppose you have this connection: HttpConnection c = (HttpConnection)
Connector.open("http://java.sun.com/developer");
Then, you can set the request method to be of type c.setRequestMethod(HttpConnection.POST);
And likewise, you can set some of the HTTP properties. For example, you
can set the c.setRequestProperty("User-Agent","Profile/MIDP-1.0 Configuration/CLDC-1.0");
If there is a method that requires data to be sent or received from the server, there is a state transition from Setup to Connected. Examples of methods that cause the transition include: openInputStream
openOutputStream openDataInputStream openDataOutputStream getLength getType getDate getExpiration And while the connection is open, some of these methods that may be invoked: getURL
getProtocol getHost getPort ![]() ------------------------------------------------------------ 要注意的問題: 開發(fā)中遇到個很頭疼的問題, 與服務(wù)器通信write()數(shù)據(jù)時報java.io.IOException: Couldn't write to socket. 但是服務(wù)器抓不到任何包. 一開始懷疑是連建立連接出的問題, 實(shí)際上服務(wù)器抓不到包也有可能是流在沒有close的時候就已經(jīng)報錯了. 如: conn.open("url"); out = conn.openDataOutputStream();//此時將進(jìn)行與服務(wù)器的三次握手; //但是如果在out.close()之前出現(xiàn)異常服務(wù)器是抓不到任何包的 out.write(byte[] bb); 關(guān)于這個的解釋應(yīng)該是流的緩沖機(jī)制. 所以正確的寫法應(yīng)該是捕捉到異常之后在catch塊中把流close掉. 服務(wù)器端開發(fā)人員一般會說收不到包所以連接有問題,會把責(zé)任推給客戶端,抓住這個證據(jù)在跟服務(wù)器端的同事扯皮時將處于有利的位置,嘎嘎. 還有就是要多做小實(shí)驗(yàn), 注意代碼要規(guī)范嚴(yán)格. 發(fā)現(xiàn)的幾個問題: 1. java.io.IOException: Couldn't write to socket 2. java.io.IOException: Couldn't read from socket CMNET聯(lián)網(wǎng)方案: CMWAP聯(lián)網(wǎng)方案: 移動資費(fèi)頁的處理: 一個通用的HTTP連接封裝: posted @ 2008-11-04 16:22 LukeW 閱讀(380) | 評論 (0) | 編輯 收藏 VIM設(shè)置
vim簡介
Vim(Vi Improved) 是一個類似于vi 的文本編輯器,在Vi的基礎(chǔ)上增加了很多新的特性和功能。Vim以其強(qiáng)大的功能和可定制能力 ,成為Linux/Unix環(huán)境下開源的最重要的編輯器之一(另一個是 Emacs),被眾多開發(fā)者所喜愛。筆者此時所用的是最新的7.1版本 。 與大部分其它編輯器不同,進(jìn)入 Vim 后,缺省狀態(tài)下鍵入的字符并不會插入到所編輯的文件之中。Vim 的模式(mode,可以簡單地 理解為“狀態(tài)”)概念非常重要。需要知道,Vim 有以下幾個模式: 1) 正常(normal)模式,缺省的編輯模式;下面如果不加特殊說明,提到的命令都直接在正常模式下輸入;任何其它模式中都 可以通過鍵盤上的 Esc 鍵回到正常模式。 2) 命令(command)模式,用于執(zhí)行較長、較復(fù)雜的命令;在正常模式下輸入“:”(一般命令)、“/”(正向搜索)或“?” (反向搜索)即可進(jìn)入該模式;命令模式下的命令要輸入回車鍵(Enter)才算完成。 3) 插入(insert)模式,輸入文本時使用;在正常模式下鍵入“i”(insert)或“a”(append)即可進(jìn)入插入模式(也有另 外一些命令,如“c”,也可以進(jìn)入插入模式,但這些命令有其它的作用)。 4) 可視(visual)模式,用于選定文本塊;可以在正常模式下輸入“v”(小寫)來按字符選定,輸入“V”(大寫)來按行選 定,或輸入“Ctrl-V”來按方塊選定。 5) 選擇(select)模式,與普通的 Windows 編輯器較為接近的選擇文本塊的方式;在以可視模式和選擇模式之一選定文本塊之 后,可以使用“Ctrl-G”切換到另一模式——該模式很少在 Linux 上使用,本文中就不再介紹了。 ------------------------------------------ 首先 vim ~/.vimrc 打開編輯文件 [轉(zhuǎn)] 1、VI或VIM的配置文件的路徑 發(fā)現(xiàn)/usr/share/vim/vimrc和/etc/vim/vimrc指向是同一個文件,即vimrc,為vi和vim的配置文件,修改這個文件即可。這個路徑在不同的LINUX版本中可能會不同。 2、配置顏色 配軒VI和VIM的顏色顯示,使它能夠高亮度顯示一些特別的單詞,這對編寫程序很有用。后來打開文件發(fā)現(xiàn)里面其實(shí)已經(jīng)有一行了,只是用引號注釋掉了,只需 將syntax on 所在行前面的引號去掉即可。或者另外獨(dú)立添加一行:syntax on 也行,另外編輯/etc/profile 增加一行alias vi="vim"就行了。 3、設(shè)置鼠標(biāo) 使用VI編輯文本時,如果想修文件中改離光標(biāo)較遠(yuǎn)的位置,這時候想用鼠標(biāo)定位,可默認(rèn)情況下,鼠標(biāo)是不可用的。如果你想使用鼠標(biāo),只需另起一行,寫上:set mouse=a 即可 4、設(shè)置自動縮進(jìn) 默認(rèn)情況下,VI和VIM都沒有縮進(jìn)的,每換一行,光標(biāo)均定位在頂格,如果你想自動對齊,請將 set autoindent所在行前面的引號去掉,或者另外添加一行:set autoindent也可。這與配置顏色類似。這樣的設(shè)置的結(jié)果是按回車后新行與上一行自動對齊。 5、設(shè)置tab的縮進(jìn)量 如果用python編寫程序,那么行縮進(jìn)量是一個極其重要的概念,同一個塊的縮進(jìn)量必須相同。你可能喜歡在行前加空格來表示縮進(jìn),但每次必須敲多次空格 鍵,如果你喜歡用按TAB鍵來表示縮進(jìn),你可能覺得寫的文本或程序不太好看,因?yàn)槟J(rèn)情況下,VI和VIM的TAB縮進(jìn)量比較大(至少六,七個字符)。設(shè) 置TAB鍵縮進(jìn)量的方法:set shiftwidth=3 你也可以選一 個你自己喜歡的縮進(jìn)量,比如2,或4. ---------------------------------------------- 首先從視覺方面: 第一個要做的是縮進(jìn),修改你的VIM配置文件_vimrc,在最后加入set cindent,這樣就設(shè)置了c風(fēng)格的縮進(jìn),在這里縮進(jìn)的大小是shiftwidth的值。 第二個要做的是語法高亮,這個是必須的,在中_vimrc加入syntax enable。 第三個要做的字體的設(shè)置,設(shè)置一個舒服的字體可以讓你編程的時候舒服好多,用editplus的時候我就用的Consolas,在vim中我還是用的這種字體,在_vimrc中加入 if has(”gui_running”) 表示運(yùn)行界面vim的時候就用這種字體。 第四,設(shè)置配色方案,可以到點(diǎn)擊這兒下載,然后放到$VIM"vimfiles"colors這個目錄下,然后在中加入如下配置 if has(”gui_running”) colorscheme_name為你需要設(shè)置的配色方案的名稱。 接下來是在運(yùn)行程序中用到的: 第一,使用ctag VIM中已經(jīng)帶了Ctags這個程序。盡管ctags也可以支持其它編輯器,但是它正式支持的只有VIM。Ctags可以幫助程序員很容易地瀏覽源代碼。用下面的命令可以在源代碼的根目錄下創(chuàng)建“tags”文件: [/home/brimmer/src]$ ctags -R “-R”表示遞歸創(chuàng)建,也就包括源代碼根目錄下的所有子目錄下的源程序。“tags”文件中包括這些對象的列表: l 用#define定義的宏 l 枚舉型變量的值 l 函數(shù)的定義、原型和聲明 l 名字空間(namespace) l 類型定義(typedefs) l 變量(包括定義和聲明) l 類(class)、結(jié)構(gòu)(struct)、枚舉類型(enum)和聯(lián)合(union) l 類、結(jié)構(gòu)和聯(lián)合中成員變量或函數(shù) VIM用這個“tags”文件來定位上面這些做了標(biāo)記的對象,下面介紹一下定位這些對象的方法: 1) 用命令行。在運(yùn)行vim的時候加上“-t”參數(shù),例如: [/home/brimmer/src]$ vim -t foo_bar 這個命令將打開定義“foo_bar”(變量或函數(shù)或其它)的文件,并把光標(biāo)定位到這一行。 2) 在vim編輯器內(nèi)用“:ta”命令,例如: :ta foo_bar 3) 最方便的方法是把光標(biāo)移到變量名或函數(shù)名上,然后按下“Ctrl-]”。用“Ctrl-o”退回原來的地方。 注意:運(yùn)行vim的時候,必須在“tags”文件所在的目錄下運(yùn)行。否則,運(yùn)行vim的時候還要用“:set tags=”命令設(shè)定“tags”文件的路徑,這樣vim才能找到“tags”文件。 你還可以選擇使用taglist這個插件,這個插件可以在右側(cè)顯示函數(shù),變量等的列表 第二,改正程序中的錯誤 在VIM編輯器的環(huán)境下用“:make”(make工具的使用已經(jīng)在我昨天的文章中 提到的云風(fēng)的幾篇文章中詳細(xì)介紹到)就可以編譯程序,當(dāng)然其前提是在當(dāng)前目錄下有Makefile文件。運(yùn)行完“:make”之后,如果程序中有錯誤,就 會顯示出來。這時候,光標(biāo)會自動指向第一個出現(xiàn)錯誤的地方,而且你還可以看到錯誤的提示。然后,你就可以改正錯誤,而不用手工找到出錯的那一行。記住下面 幾個有用的命令: l “:cl”列出錯誤 l “:cn”讓光標(biāo)指向下一個錯誤 l “:cp”讓光標(biāo)指向上一個錯誤 l “:cnew”從頭開始 你甚至可以讓VIM識別出其它編譯器而不是gcc的錯誤提示。這對一些開發(fā)嵌入式系統(tǒng)的程序員這很有用,因?yàn)樗麄兒芸赡苡玫牟皇莋cc而是其它編譯器。通過設(shè)置“errorformat”的值,可以讓VIM識別出編譯器的出錯提示。因?yàn)椴煌木幾g器的出錯提示是不同的,所以如果用的不是gcc就要重新設(shè)置。 “errorformat”的值是一個字符串,它的格式和C語言的scanf的字符串格式相識。 gcc的“errorformat”的值為:%f:%l:"%m。其中“%f”表示文件名,“%l”表示行號,“%m”表示出錯信息。 用“:h errorformat”查看詳細(xì)的幫助信息。 用“:h quickfix”、“:h make”、“:h makeprg”、“:h errorfile”查看其它的信息。 第三,使用快捷鍵 下面的這些快捷鍵對程序員很有幫助: [[ 轉(zhuǎn)到上一個位于第一列的“{” ]] 轉(zhuǎn)到下一個位于第一列的“{” { 轉(zhuǎn)到上一個空行 } 轉(zhuǎn)到下一個空行 gd 轉(zhuǎn)到當(dāng)前光標(biāo)所指的局部變量的定義 * 轉(zhuǎn)到當(dāng)前光標(biāo)所指的單詞下一次出現(xiàn)的地方 # 轉(zhuǎn)到當(dāng)前光標(biāo)所指的單詞上一次出現(xiàn)的地方 % 用來進(jìn)行小括號、中括號和大括號的匹配。這要看當(dāng)前光標(biāo)指向的是什么符號了。 ---------------------------------------------- 一個ubuntu 下的vimrc配置例子: """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" 一般設(shè)定 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " 設(shè)定默認(rèn)解碼 set fenc=utf-8 set fencs=utf-8,usc-bom,euc-jp,gb18030,gbk,gb2312,cp936 "設(shè)定搜索是的高亮顯示 set hlsearch " 不要使用vi的鍵盤模式,而是vim自己的 set nocompatible " history文件中需要記錄的行數(shù) set history=100 " 在處理未保存或只讀文件的時候,彈出確認(rèn) set confirm " 與windows共享剪貼板 set clipboard+=unnamed " 偵測文件類型 filetype on " 載入文件類型插件 filetype plugin on " 為特定文件類型載入相關(guān)縮進(jìn)文件 filetype indent on " 保存全局變量 set viminfo+=! " 帶有如下符號的單詞不要被換行分割 set iskeyword+=_,$,@,%,#,- " 語法高亮 syntax on " 高亮字符,讓其不受100列限制 :highlight OverLength ctermbg=red ctermfg=white guibg=red guifg=white ":match OverLength '"%101v.*' " 狀態(tài)行顏色 highlight StatusLine guifg=SlateBlue guibg=Yellow highlight StatusLineNC guifg=Gray guibg=White "高亮當(dāng)前行 set cursorline """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " 文件設(shè)置 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " 不要備份文件(根據(jù)自己需要取舍) set nobackup " 不要生成swap文件,當(dāng)buffer被丟棄的時候隱藏它 setlocal noswapfile set bufhidden=hide " 字符間插入的像素行數(shù)目 set linespace=0 " 增強(qiáng)模式中的命令行自動完成操作 set wildmenu " 在狀態(tài)行上顯示光標(biāo)所在位置的行號和列號 set ruler set rulerformat=%20(%2*%<%f%=" %m%r" %3l" %c" %p%%%) " 命令行(在狀態(tài)行下)的高度,默認(rèn)為1,這里是2 set cmdheight=2 " 使回格鍵(backspace)正常處理indent, eol, start等 set backspace=2 " 允許backspace和光標(biāo)鍵跨越行邊界 set whichwrap+=<,>,h,l " 可以在buffer的任何地方使用鼠標(biāo)(類似office中在工作區(qū)雙擊鼠標(biāo)定位) set mouse=a set selection=exclusive set selectmode=mouse,key " 啟動的時候不顯示那個援助索馬里兒童的提示 set shortmess=atI " 通過使用: commands命令,告訴我們文件的哪一行被改變過 set report=0 " 不讓vim發(fā)出討厭的滴滴聲 set noerrorbells " 在被分割的窗口間顯示空白,便于閱讀 set fillchars=vert:" ,stl:" ,stlnc:" """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " 搜索和匹配 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " 高亮顯示匹配的括號 set showmatch " 匹配括號高亮的時間(單位是十分之一秒) set matchtime=5 " 在搜索的時候不忽略大小寫 set noignorecase " 不要高亮被搜索的句子(phrases) "set nohlsearch " 在搜索時,輸入的詞句的逐字符高亮(類似firefox的搜索) set incsearch " 輸入:set list命令是應(yīng)該顯示些啥? set listchars=tab:"|" ,trail:.,extends:>,precedes:<,eol:$ " 光標(biāo)移動到buffer的頂部和底部時保持3行距離 set scrolloff=3 " 不要閃爍 set novisualbell " 我的狀態(tài)行顯示的內(nèi)容(包括文件類型和解碼) set statusline=%F%m%r%h%w" [FORMAT=%{&ff}]" [TYPE=%Y]" [POS=%l,%v][%p%%]" %{strftime(""%d/%m/%y" -" %H:%M"")} " 總是顯示狀態(tài)行 set laststatus=2 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " 文本格式和排版 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " 自動格式化 set formatoptions=tcrqn " 繼承前一行的縮進(jìn)方式,特別適用于多行注釋 set autoindent " 為C程序提供自動縮進(jìn) set smartindent " 使用C樣式的縮進(jìn) set cindent " 制表符為4 set tabstop=4 " 統(tǒng)一縮進(jìn)為4 set softtabstop=4 set shiftwidth=4 " 不要用空格代替制表符 set noexpandtab " 不要換行 "set nowrap "設(shè)置每行80個字符自動換行 set textwidth=80 " 在行和段開始處使用制表符 set smarttab """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " CTags的設(shè)定 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " 按照名稱排序 let Tlist_Sort_Type = "name" " 在右側(cè)顯示窗口 let Tlist_Use_Right_Window = 1 " 壓縮方式 let Tlist_Compart_Format = 1 " 如果只有一個buffer,kill窗口也kill掉buffer let Tlist_Exist_OnlyWindow = 1 " 不要關(guān)閉其他文件的tags let Tlist_File_Fold_Auto_Close = 0 " 不要顯示折疊樹 let Tlist_Enable_Fold_Column = 1 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " Autocommands """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " 只在下列文件類型被偵測到的時候顯示行號,普通文本文件不顯示 if has("autocmd") autocmd FileType xml,html,c,cs,java,perl,shell,bash,cpp,python,vim,php,ruby set number autocmd FileType xml,html vmap <C-o> <ESC>'<i<!--<ESC>o<ESC>'>o--> autocmd FileType java,c,cpp,cs vmap <C-o> <ESC>'<o/*<ESC>'>o*/ autocmd FileType html,text,php,vim,c,java,xml,bash,shell,perl,python setlocal textwidth=80 autocmd Filetype html,xml,xsl source $VIMRUNTIME/plugin/closetag.vim autocmd BufReadPost * " if line("'""") > 0 && line("'""") <= line("$") | " exe "normal g`""" | " endif endif " has("autocmd") " C/C++的編譯和運(yùn)行 map <F5> :call CompileRunGcc()<CR> func! CompileRunGcc() exec "w" exec "!make" exec "! ./%<" endfunc " shell script運(yùn)行 map <F6> :call CompileRunSH()<CR> func! CompileRunSH() exec "w" exec "!chmod a+x %" exec "!./%" endfunc " python運(yùn)行 map <F7> :call CompileRunPyhton()<CR> func! CompileRunPyhton() exec "w" exec "!chmod a+x %" exec "!./%" endfunc " 能夠漂亮地顯示.NFO文件 set encoding=utf-8 function! SetFileEncodings(encodings) let b:myfileencodingsbak=&fileencodings let &fileencodings=a:encodings endfunction function! RestoreFileEncodings() let &fileencodings=b:myfileencodingsbak unlet b:myfileencodingsbak endfunction au BufReadPre *.nfo call SetFileEncodings('cp437')|set ambiwidth=single au BufReadPost *.nfo call RestoreFileEncodings() " 高亮顯示普通txt文件(需要txt.vim腳本) au BufRead,BufNewFile * setfiletype txt " 用空格鍵來開關(guān)折疊 set foldenable set foldlevel=0 set foldmethod=indent nnoremap <space> @=((foldclosed(line('.')) < 0) ? 'zc' : 'zo')<CR> " minibufexpl插件的一般設(shè)置 let g:miniBufExplMapWindowNavVim = 1 let g:miniBufExplMapWindowNavArrows = 1 let g:miniBufExplMapCTabSwitchBufs = 1 let g:miniBufExplModSelTarget = 1 ---------------------- 一個相關(guān)帖子 http://forum.ubuntu.org.cn/viewtopic.php?f=68&t=138212&st=0&sk=t&sd=a
posted @ 2008-11-03 13:02 LukeW 閱讀(1636) | 評論 (0) | 編輯 收藏 |
|