Look into it ~

          present
          隨筆 - 32, 文章 - 0, 評論 - 3, 引用 - 0
          數(shù)據(jù)加載中……

          2008年11月3日

          android軟件

              只有注冊用戶登錄后才能閱讀該文。閱讀全文

          posted @ 2008-11-20 16:24 LukeW 閱讀(36) | 評論 (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, );// 設(shè)置指定kobject的名稱。

          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)
          {
           
          *= *^ *y;
           
          *= *^ *y;
           
          *= *^ *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)編輯 收藏

          點(diǎn)子

              只有注冊用戶登錄后才能閱讀該文。閱讀全文

          posted @ 2008-11-06 18:17 LukeW 閱讀(44) | 評論 (0)編輯 收藏

          j2me 聯(lián)網(wǎng)技術(shù)分析總結(jié)

          基本點(diǎn):

          Generic Connections

          In the CLDC Generic Connection framework, all connections are created using the open static method from the Connector class. If successful, this method returns an object that implements one of the generic connection interfaces. Figure 1 shows how these interfaces form an is-a hierarchy. The Connection interface is the base interface such that StreamConnectionNotifier is a Connection and InputConnection is a Connection too.

          fig1.gif
          Figure 1: Connection interface hierarchy
          • The Connection interface is the most basic connection type. It can only be opened and closed.
          • The InputConnection interface represents a device from which data can be read. Its openInputStream method returns an input stream for the connection.
          • The OuputConnection interface represents a device to which data can be written. Its openOutputStream method returns an output stream for the connection.
          • The StreamConnection interface combines the input and output connections.
          • The ContentConnection is a subinterface of StreamConnection. It provides access to some of the basic meta data information provided by HTTP connections.
          • The StreamConnectionNotified waits for a connection to be established. It returns a StreamConnection on which a communication link has ben established.
          • The DatagramConnection represents a datagram endpoint.

          The open method of the Connector class has the following syntax, where the String parameter has the format "protocol:address;parameters".

          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:
          • Setup: No connection yet
          • Connected: Connection has been made, the request has been sent, and some response is expected
          • Closed: Connection is closed

          In the setup state the following methods can be invoked:

          • setRequestMethod
          • setRequestProperty

          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 POST as follows:

          c.setRequestMethod(HttpConnection.POST);

          And likewise, you can set some of the HTTP properties. For example, you can set the User-Agent as follows:

          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),修改你的配置文件_vimrc,在最后加入set cindent,這樣就設(shè)置了c風(fēng)格的縮進(jìn),在這里縮進(jìn)的大小是shiftwidth的值。

          第二個要做的是語法高亮,這個是必須的,在中_vimrc加入syntax enable

          第三個要做的字體的設(shè)置,設(shè)置一個舒服的字體可以讓你編程的時候舒服好多,用editplus的時候我就用的Consolas,在中我還是用的這種字體,在_vimrc中加入

          if has(”gui_running”)
          set guifont=Consolas:h9
          endif

          表示運(yùn)行界面的時候就用這種字體。

          第四,設(shè)置配色方案,可以到點(diǎn)擊這兒下載,然后放到$"vimfiles"colors這個目錄下,然后在中加入如下配置

          if has(”gui_running”)
          set guifont=Consolas:h9
          ” set color schema
          colorscheme
          colorscheme_name
          endif

          colorscheme_name為你需要設(shè)置的配色方案的名稱。

          接下來是在運(yùn)行程序中用到的:

          第一,使用ctag

          中已經(jīng)帶了Ctags這個程序。盡管ctags也可以支持其它編輯器,但是它正式支持的只有。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ù)

          用這個“tags”文件來定位上面這些做了標(biāo)記的對象,下面介紹一下定位這些對象的方法:

          1)        用命令行。在運(yùn)行的時候加上“-t”參數(shù),例如:

          [/home/brimmer/src]$   -t  foo_bar

          這個命令將打開定義“foo_bar”(變量或函數(shù)或其它)的文件,并把光標(biāo)定位到這一行。

          2)        在編輯器內(nèi)用“:ta”命令,例如:

          :ta foo_bar

          3)        最方便的方法是把光標(biāo)移到變量名或函數(shù)名上,然后按下“Ctrl-]”。用“Ctrl-o”退回原來的地方。

          注意:運(yùn)行的時候,必須在“tags”文件所在的目錄下運(yùn)行。否則,運(yùn)行的時候還要用“:set tags=”命令設(shè)定“tags”文件的路徑,這樣才能找到“tags”文件。

          你還可以選擇使用taglist這個插件,這個插件可以在右側(cè)顯示函數(shù),變量等的列表

          第二,改正程序中的錯誤

          編輯器的環(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”從頭開始

          你甚至可以讓識別出其它編譯器而不是gcc的錯誤提示。這對一些開發(fā)嵌入式系統(tǒng)的程序員這很有用,因?yàn)樗麄兒芸赡苡玫牟皇莋cc而是其它編譯器。通過設(shè)置“errorformat”的值,可以讓識別出編譯器的出錯提示。因?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”查看其它的信息。

          第三,使用快捷鍵

          下面的這些快捷鍵對程序員很有幫助:
          在函數(shù)中移動光標(biāo)

          [[  轉(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+%"
          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)編輯 收藏

          主站蜘蛛池模板: 马边| 龙川县| 天柱县| 揭阳市| 高淳县| 兴化市| 砚山县| 柘城县| 寿光市| 田东县| 安多县| 民和| 四会市| 宁陕县| 丹江口市| 全州县| 增城市| 马关县| 县级市| 申扎县| 汉源县| 镇雄县| 彭州市| 武冈市| 如皋市| 平谷区| 南开区| 祁阳县| 正镶白旗| 彰武县| 甘洛县| 樟树市| 温泉县| 三台县| 巴里| 九龙城区| 邵阳市| 文昌市| 美姑县| 连南| 西乌|