Look into it ~

present
随笔 - 32, 文章 - 0, 评论 - 3, 引用 - 0
数据加载中……

2008年11月3日

android软件

    只有注册用户登录后才能阅读该文。阅读全文

posted @ 2008-11-20 16:24 LukeW 阅读(33) | 评论 (0)编辑 收藏

linux设备模型

Linux 2.6内核的一个重要特色是提供了统一的内核设备模型。随着技术的不断进步,系统的拓扑结构越来越复杂,对智能电源管理、热插拔以及plug and play的支持要求也越来越高,2.4内核已经难以满足这些需求。为适应这种形势的需要,2.6内核开发了全新的设备模型。
1. Sysfs文件系统
Sysfs文件系统是一个类似于proc文件系统的特殊文件系统,用于将系统中的设备组织成层次结构,并向用户模式程序提供详细的内核数据结构信息。其顶层目录主要有:
Block目录:包含所有的块设备
Devices目录:包含系统所有的设备,并根据设备挂接的总线类型组织成层次结构
Bus目录:包含系统中所有的总线类型
Drivers目录:包括内核中所有已注册的设备驱动程序
Class目录:系统中的设备类型(如网卡设备,声卡设备等)
2. 内核对象机制关键数据结构
2.1 kobject内核对象
Kobject 是Linux 2.6引入的新的设备管理机制,在内核中由struct kobject表示。通过这个数据结构使所有设备在底层都具有统一的接口,kobject提供基本的对象管理,是构成Linux 2.6设备模型的核心结构,它与sysfs文件系统紧密关联,每个在内核中注册的kobject对象都对应于sysfs文件系统中的一个目录。
Kobject结构定义为:
struct kobject {
char * k_name;    // 指向设备名称的指针
char name[KOBJ_NAME_LEN];   // 设备名称
struct kref kref;    // 对象引用计数
struct list_head entry;   // 挂接到所在kset中去的单元
struct kobject * parent; // 指向父对象的指针
struct kset * kset;    // 所属kset的指针
struct kobj_type * ktype;   // 指向其对象类型描述符的指针
struct dentry * dentry; // sysfs文件系统中与该对象对应的文件节点路径指针
};

其中的kref域表示该对象引用的计数,内核通过kref实现对象引用计数管理,内核提供两个函数kobject_get()、kobject_put()分别用于增加和减少引用计数,当引用计数为0时,所有该对象使用的资源将被释放。
Ktype 域是一个指向kobj_type结构的指针,表示该对象的类型。Kobj_type数据结构包含三个域:一个release方法用于释放kobject占 用的资源;一个sysfs_ops指针指向sysfs操作表和一个sysfs文件系统缺省属性列表。Sysfs操作表包括两个函数store()和 show()。当用户态读取属性时,show()函数被调用,该函数编码指定属性值存入buffer中返回给用户态;而store()函数用于存储用户态 传入的属性值。
2.2 kset内核对象集合
Kobject通常通过kset组织成层次化的结构,kset是具有相同类型的kobject的集合,在内核中用kset数据结构表示,定义为:
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被组织成一个双向循环链表,list域正是该链表的头。Ktype域指向一个kobj_type结构,被该 kset中的所有kobject共享,表示这些对象的类型。Kset数据结构还内嵌了一个kobject对象(由kobj域表示),所有属于这个kset 的kobject对象的parent域均指向这个内嵌的对象。此外,kset还依赖于kobj维护引用计数:kset的引用计数实际上就是内嵌的 kobject对象的引用计数。
2.3 subsystem内核对象子系统
Subsystem是一系列kset的集合,描述系统中某一 类设备子系统,如block_subsys表示所有的块设备,对应于sysfs文件系统中的block目录。类似的,devices_subsys对应于 sysfs中的devices目录,描述系统中所有的设备。Subsystem由struct subsystem数据结构描述,定义为:
struct subsystem {
struct kset kset;       // 内嵌的kset对象
struct rw_semaphore rwsem; // 互斥访问信号量
};

每 个kset必须属于某个subsystem,通过设置kset结构中的subsys域指向指定的subsystem可以将一个kset加入到该 subsystem。所有挂接到同一subsystem的kset共享同一个rwsem信号量,用于同步访问kset中的链表。

3. 内核对象机制主要相关函数
针对内核对象不同层次的数据结构,linux 2.6内核定义了一系列操作函数,定义于lib/kobject.c文件中。
3.1 kobject相关函数
void kobject_init(struct kobject * kobj);// kobject初始化函数。设置kobject引用计数为1,entry域指向自身,其所属kset引用计数加1

int kobject_set_name(struct kobject *kobj, const char *format, );// 设置指定kobject的名称。

void kobject_cleanup(struct kobject * kobj);
void kobject_release(struct kref *kref);// kobject清除函数。当其引用计数为0时,释放对象占用的资源。

struct kobject *kobject_get(struct kobject *kobj);// 将kobj 对象的引用计数加1,同时返回该对象的指针。

void kobject_put(struct kobject * kobj);// 将kobj对象的引用计数减1,如果引用计数降为0,则调用kobject_release()释放该kobject对象。

int kobject_add(struct kobject * kobj);// 将kobj对象加入Linux设备层次。挂接该kobject对象到kset的list链中,增加父目录各级kobject的引用计数,在其parent指向的目录下创建文件节点,并启动该类型内核对象的hotplug函数。

int kobject_register(struct kobject * kobj);// kobject注册函数。通过调用kobject_init()初始化kobj,再调用kobject_add()完成该内核对象的注册。

void kobject_del(struct kobject * kobj);// 从Linux设备层次(hierarchy)中删除kobj对象。

void kobject_unregister(struct kobject * kobj);// kobject注销函数。与kobject_register()相反,它首先调用kobject_del从设备层次中删除该对象,再调用kobject_put()减少该对象的引用计数,如果引用计数降为0,则释放该kobject对象。

3.2 kset相关函数
与kobject 相似,kset_init()完成指定kset的初始化,kset_get()和kset_put()分别增加和减少kset对象的引用计数。 Kset_add()和kset_del()函数分别实现将指定keset对象加入设备层次和从其中删除;kset_register()函数完成 kset的注册而kset_unregister()函数则完成kset的注销。
3.3 subsystem相关函数
subsystem有一组完成类似的函数,分别是:
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. 设备模型组件
在上述内核对象机制的基础上,Linux的设备模型建立在几个关键组件的基础上,下面我们详细阐述这些组件。
4.1 devices
系统中的任一设备在设备模型中都由一个device对象描述,其对应的数据结构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对象挂接到全局设备链表中,所有的device对象都包含在devices_subsys中,并组织成层次结构。Node域将该对象挂接 到其兄弟对象的链表中,而bus_list则用于将连接到相同总线上的设备组织成链表,driver_list则将同一驱动程序管理的所有设备组织为链 表。此外,children域指向该device对象子对象链表头,parent域则指向父对象。Device对象还内嵌一个kobject对象,用于引 用计数管理并通过它实现设备层次结构。Driver域指向管理该设备的驱动程序对象,而driver_data则是提供给驱动程序的数据。Bus域描述设 备所连接的总线类型。
内核提供了相应的函数用于操作device对象。其中Device_register()函数将一个新的device对象插 入设备模型,并自动在/sys/devices下创建一个对应的目录。Device_unregister()完成相反的操作,注销设备对象。 Get_device()和put_device()分别增加与减少设备对象的引用计数。通常device结构不单独使用,而是包含在更大的结构中作为一 个子结构使用,比如描述PCI设备的struct pci_dev,其中的dev域就是一个device对象。
4.2 drivers
系统中的每个驱动程序由一个device_driver对象描述,对应的数据结构定义为:
struct device_driver {
    
char *name;   // 设备驱动程序的名称
    struct bus_type *bus; // 该驱动所管理的设备挂接的总线类型
    struct kobject kobj;    // 内嵌kobject对象
    struct list_head devices;  // 该驱动所管理的设备链表头
    int (*probe)(struct device *dev); // 指向设备探测函数,用于探测设备是否可以被该驱动程序管理
int (*remove)(struct device *dev); // 用于删除设备的函数
/*
 some fields omitted*/
};

与device 结构类似,device_driver对象依靠内嵌的kobject对象实现引用计数管理和层次结构组织。内核提供类似的函数用于操作 device_driver对象,如get_driver()增加引用计数,driver_register()用于向设备模型插入新的driver对 象,同时在sysfs文件系统中创建对应的目录。Device_driver()结构还包括几个函数,用于处理热拔插、即插即用和电源管理事件。
4.3   buses
系统中总线由struct bus_type描述,定义为:
struct bus_type {
char   * name; // 总线类型的名称
struct subsystem subsys; // 与该总线相关的subsystem
struct kset drivers; // 所有与该总线相关的驱动程序集合
struct kset devices; // 所有挂接在该总线上的设备集合
struct bus_attribute * bus_attrs; // 总线属性
struct device_attribute * dev_attrs; // 设备属性
struct driver_attribute * drv_attrs;   // 驱动程序属性
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对象都内嵌一个subsystem对象,bus_subsys对象管理系统中所有总线类型的subsystem对象。每个 bus_type对象都对应/sys/bus目录下的一个子目录,如PCI总线类型对应于/sys/bus/pci。在每个这样的目录下都存在两个子目 录:devices和drivers(分别对应于bus_type结构中的devices和drivers域)。其中devices子目录描述连接在该总 线上的所有设备,而drivers目录则描述与该总线关联的所有驱动程序。与device_driver对象类似,bus_type结构还包含几个函数 (match()、hotplug()等)处理相应的热插拔、即插即拔和电源管理事件。
4.4 classes
系统中的设备类由 struct class描述,表示某一类设备。所有的class对象都属于class_subsys子系统,对应于sysfs文件系统中的/sys/class目录。 每个class对象包括一个class_device链表,每个class_device对象表示一个逻辑设备,并通过struct class_device中的dev域(一个指向struct device的指针)关联一个物理设备。这样,一个逻辑设备总是对应于一个物理设备,但是一个物理设备却可能对应于多个逻辑设备。此外,class结构中 还包括用于处理热插拔、即插即拔和电源管理事件的函数,这与device对象和driver对象相似。

posted @ 2008-11-12 23:14 LukeW 阅读(177) | 评论 (0)编辑 收藏

位运算

C中的位运算
能够运用到任何整形的数据类型上(包括char, int), 无论有没有short, long, unsigned这样的限定词.


位运算的应用
// 交换指针变量x,y所指向的存储位置处存放的值
// 优势是不需要第三个位置来临时存储另一个值
// 但是这个方法并没有明显的性能优势,只是一个智力上的消遣
void inplace_swap(int *x, int *y)
{
 
*= *^ *y;
 
*= *^ *y;
 
*= *^ *y;
}

位运算常见用法:
实现掩码运算



-----------------------------------
Java中的位运算


posted @ 2008-11-12 13:53 LukeW 阅读(122) | 评论 (0)编辑 收藏

大端小端 -- 各系统及机器的信息表示

因为现行的计算机都是以八位一个字节为存储单位,那么一个16位的整数,也就是C语言中的short,在内存中可能有两种存储顺序big-

endian和litte-endian.考虑一个short整数0x3132(0x32是低位,0x31是高位),把它赋值给一个short变量,那么它在内存中的存储可

能有如下两种情况:
大端字节(Big-endian):

short变量地址
       0x1000                  0x1001
___________________________________
|                 |
|         0x31    |       0x32
|________________ | ________________
高位字节在低位字节的前面,也就是高位在内存地址低的一端.可以这样记住(大端->高位->在前->正常的逻辑顺序)
 
小端字节(little-endian):

short变量地址
       0x1000                  0x1001
_____________________________________
|                 |
|         0x32    |       0x31
|________________ | __________________
低位字节在高位字节的前面,也就是低位在内存地址低的一端.可以这样记住(小端->低位->在前->与正常逻辑顺序相反)
 
可以做个实验
在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文件,可以看见内容是21,而test等于0x3132,可以明显的看出来x86的字节顺序是低位在前.如果我们
把这段同样的代码放到(big-endian)的机器上执行,那么打出来的文件就是12.这在本机中使用是没有问题的.但当你把这个文件从一
个big- endian机器复制到一个little-endian机器上时就出现问题了.

    如上述例子,我们在big-endian的机器上创建了这个test文件,把其复制到little-endian的机器上再用fread读到一个 short里
面,我们得到的就不再是0x3132而是0x3231了,这样读到的数据就是错误的,所以在两个字节顺序不一样的机器上传输数据时需要特别
小心字节顺序,理解了字节顺序在可以帮助我们写出移植行更高的代码.

正因为有字节顺序的差别,所以在网络传输的时候定义了所有字节顺序相关的数据都使用big-endian,BSD的代码中定义了四个宏来处
理:
#define ntohs(n)     //网络字节顺序到主机字节顺序 n代表net, h代表host, s代表short
#define htons(n)     //主机字节顺序到网络字节顺序 n代表net, h代表host, s代表short
#define ntohl(n)      //网络字节顺序到主机字节顺序 n代表net, h代表host, s代表 long
#define htonl(n)      //主机字节顺序到网络字节顺序 n代表net, h代表host, s代表 long

举例说明下这其中一个宏的实现:
 #define sw16(x) "
    ((
short)( "
        (((short)(x) & (short)0x00ffU<< 8| "
        (((short)(x) & (short)0xff00U>> 8) ))

这里实现的是一个交换两个字节顺序.其他几个宏类似.

我们改写一下上面的程序
#include <stdio.h>
#include 
<assert.h>

#define sw16(x) "
    ((
short)( "
        (((short)(x) & (short)0x00ffU<< 8| "
        (((short)(x) & (short)0xff00U>> 8) ))

// 因为x86下面是低位在前,需要交换一下变成网络字节顺序
#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);
}

 
    如果在高字节在前的机器上,由于与网络字节顺序一致,所以我们什么都不干就可以了,只需要把#define htons(x) sw16(x)宏替

换为 #define htons(x) (x).
    一开始我在理解这个问题时,总在想为什么其他数据不用交换字节顺序?比如说我们write一块buffer到文件,最后终于想明白了,

因为都是unsigned char类型一个字节一个字节的写进去,这个顺序是固定的,不存在字节顺序的问题.

【用函数判断系统是Big Endian还是Little Endian】


bool IsBig_Endian()
//如果字节序为big-endian,返回true;
//反之为   little-endian,返回false
{
    unsigned 
short test = 0x1122;
    
if(*( (unsigned char*&test ) == 0x11)
       
return TRUE;
else
    
return FALSE;

}
//IsBig_Endian()

【打印程序对象的字节表示】
// 可在不同平台与硬件架构的机器中测试运行这段代码,理解大端表示和小端表示的不同.
// 这段代码使用强制类型转换规避类型系统
#incluede <stdio.h>

// 假设每个字节都是非负整数
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编码)的系统中,字符串字节表示得到的结果一般是相同的.所以文本数据比二进制数据具有更强的平台无关性
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); 
// 各个机器因为大端表示和小端表示的不同,从而只是字节顺序不同
 show_float(fval); // 各个机器因为大端表示和小端表示的不同,从而只是字节顺序不同
 show_pointer(pval); // 指针值是与机器相关的(linux,sun使用4字节地址, 而alpha使用八字节地址)
}

---------------------------------------------
对于如数值12345在int型和float型时的编码表示

posted @ 2008-11-12 11:58 LukeW 阅读(647) | 评论 (0)编辑 收藏

点子

    只有注册用户登录后才能阅读该文。阅读全文

posted @ 2008-11-06 18:17 LukeW 阅读(41) | 评论 (0)编辑 收藏

j2me 联网技术分析总结

基本点:

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


------------------------------------------------------------
要注意的问题:
开发中遇到个很头疼的问题, 与服务器通信write()数据时报java.io.IOException: Couldn't write to socket.
但是服务器抓不到任何包. 一开始怀疑是连建立连接出的问题, 实际上服务器抓不到包也有可能是流在没有close的时候就已经报错了.
如:
conn.open("url");
out = conn.openDataOutputStream();//此时将进行与服务器的三次握手;
                                  //但是如果在out.close()之前出现异常服务器是抓不到任何包的
out.write(byte[] bb);

关于这个的解释应该是流的缓冲机制.
所以正确的写法应该是捕捉到异常之后在catch块中把流close掉.
服务器端开发人员一般会说收不到包所以连接有问题,会把责任推给客户端,抓住这个证据在跟服务器端的同事扯皮时将处于有利的位置,嘎嘎.
还有就是要多做小实验, 注意代码要规范严格.

发现的几个问题:

1. java.io.IOException: Couldn't write to socket

2. java.io.IOException: Couldn't read from socket

CMNET联网方案:

CMWAP联网方案:

移动资费页的处理:

一个通用的HTTP连接封装:

posted @ 2008-11-04 16:22 LukeW 阅读(371) | 评论 (0)编辑 收藏

VIM设置

vim简介
 
Vim(Vi Improved) 是一个类似于vi 的文本编辑器,在Vi的基础上增加了很多新的特性和功能。Vim以其强大的功能和可定制能力

,成为Linux/Unix环境下开源的最重要的编辑器之一(另一个是 Emacs),被众多开发者所喜爱。笔者此时所用的是最新的7.1版本


与大部分其它编辑器不同,进入 Vim 后,缺省状态下键入的字符并不会插入到所编辑的文件之中。Vim 的模式(mode,可以简单地

理解为“状态”)概念非常重要。需要知道,Vim 有以下几个模式:
1)   正常(normal)模式,缺省的编辑模式;下面如果不加特殊说明,提到的命令都直接在正常模式下输入;任何其它模式中都

可以通过键盘上的 Esc 键回到正常模式。
2)   命令(command)模式,用于执行较长、较复杂的命令;在正常模式下输入“:”(一般命令)、“/”(正向搜索)或“?”

(反向搜索)即可进入该模式;命令模式下的命令要输入回车键(Enter)才算完成。
3)   插入(insert)模式,输入文本时使用;在正常模式下键入“i”(insert)或“a”(append)即可进入插入模式(也有另

外一些命令,如“c”,也可以进入插入模式,但这些命令有其它的作用)。
4)   可视(visual)模式,用于选定文本块;可以在正常模式下输入“v”(小写)来按字符选定,输入“V”(大写)来按行选

定,或输入“Ctrl-V”来按方块选定。
5)   选择(select)模式,与普通的 Windows 编辑器较为接近的选择文本块的方式;在以可视模式和选择模式之一选定文本块之

后,可以使用“Ctrl-G”切换到另一模式——该模式很少在 Linux 上使用,本文中就不再介绍了。
------------------------------------------
首先 vim ~/.vimrc 打开编辑文件

[转]
   1、VI或VIM的配置文件的路径

    发现/usr/share/vim/vimrc和/etc/vim/vimrc指向是同一个文件,即vimrc,为vi和vim的配置文件,修改这个文件即可。这个路径在不同的LINUX版本中可能会不同。

    2、配置颜色

    配轩VI和VIM的颜色显示,使它能够高亮度显示一些特别的单词,这对编写程序很有用。后来打开文件发现里面其实已经有一行了,只是用引号注释掉了,只需 将syntax on 所在行前面的引号去掉即可。或者另外独立添加一行:syntax on 也行,另外编辑/etc/profile 增加一行alias vi="vim"就行了。

    3、设置鼠标

    使用VI编辑文本时,如果想修文件中改离光标较远的位置,这时候想用鼠标定位,可默认情况下,鼠标是不可用的。如果你想使用鼠标,只需另起一行,写上:set mouse=a 即可

    4、设置自动缩进

    默认情况下,VI和VIM都没有缩进的,每换一行,光标均定位在顶格,如果你想自动对齐,请将 set autoindent所在行前面的引号去掉,或者另外添加一行:set autoindent也可。这与配置颜色类似。这样的设置的结果是按回车后新行与上一行自动对齐。

    5、设置tab的缩进量

    如果用python编写程序,那么行缩进量是一个极其重要的概念,同一个块的缩进量必须相同。你可能喜欢在行前加空格来表示缩进,但每次必须敲多次空格 键,如果你喜欢用按TAB键来表示缩进,你可能觉得写的文本或程序不太好看,因为默认情况下,VI和VIM的TAB缩进量比较大(至少六,七个字符)。设 置TAB键缩进量的方法:set shiftwidth=3 你也可以选一 个你自己喜欢的缩进量,比如2,或4.

----------------------------------------------

首先从视觉方面:

第一个要做的是缩进,修改你的配置文件_vimrc,在最后加入set cindent,这样就设置了c风格的缩进,在这里缩进的大小是shiftwidth的值。

第二个要做的是语法高亮,这个是必须的,在中_vimrc加入syntax enable

第三个要做的字体的设置,设置一个舒服的字体可以让你编程的时候舒服好多,用editplus的时候我就用的Consolas,在中我还是用的这种字体,在_vimrc中加入

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

表示运行界面的时候就用这种字体。

第四,设置配色方案,可以到点击这儿下载,然后放到$"vimfiles"colors这个目录下,然后在中加入如下配置

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

colorscheme_name为你需要设置的配色方案的名称。

接下来是在运行程序中用到的:

第一,使用ctag

中已经带了Ctags这个程序。尽管ctags也可以支持其它编辑器,但是它正式支持的只有。Ctags可以帮助程序员很容易地浏览源代码。用下面的命令可以在源代码的根目录下创建“tags”文件:

[/home/brimmer/src]$ ctags -R

“-R”表示递归创建,也就包括源代码根目录下的所有子目录下的源程序。“tags”文件中包括这些对象的列表:

l        用#define定义的宏

l        枚举型变量的值

l        函数的定义、原型和声明

l        名字空间(namespace)

l        类型定义(typedefs)

l        变量(包括定义和声明)

l        类(class)、结构(struct)、枚举类型(enum)和联合(union)

l        类、结构和联合中成员变量或函数

用这个“tags”文件来定位上面这些做了标记的对象,下面介绍一下定位这些对象的方法:

1)        用命令行。在运行的时候加上“-t”参数,例如:

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

这个命令将打开定义“foo_bar”(变量或函数或其它)的文件,并把光标定位到这一行。

2)        在编辑器内用“:ta”命令,例如:

:ta foo_bar

3)        最方便的方法是把光标移到变量名或函数名上,然后按下“Ctrl-]”。用“Ctrl-o”退回原来的地方。

注意:运行的时候,必须在“tags”文件所在的目录下运行。否则,运行的时候还要用“:set tags=”命令设定“tags”文件的路径,这样才能找到“tags”文件。

你还可以选择使用taglist这个插件,这个插件可以在右侧显示函数,变量等的列表

第二,改正程序中的错误

编辑器的环境下用“:make”(make工具的使用已经在我昨天的文章中 提到的云风的几篇文章中详细介绍到)就可以编译程序,当然其前提是在当前目录下有Makefile文件。运行完“:make”之后,如果程序中有错误,就 会显示出来。这时候,光标会自动指向第一个出现错误的地方,而且你还可以看到错误的提示。然后,你就可以改正错误,而不用手工找到出错的那一行。记住下面 几个有用的命令:

l        “:cl”列出错误

l        “:cn”让光标指向下一个错误

l        “:cp”让光标指向上一个错误

l        “:cnew”从头开始

你甚至可以让识别出其它编译器而不是gcc的错误提示。这对一些开发嵌入式系统的程序员这很有用,因为他们很可能用的不是gcc而是其它编译器。通过设置“errorformat”的值,可以让识别出编译器的出错提示。因为不同的编译器的出错提示是不同的,所以如果用的不是gcc就要重新设置。

errorformat”的值是一个字符串,它的格式和C语言的scanf的字符串格式相识。

gcc的“errorformat”的值为:%f:%l:"%m。其中“%f”表示文件名,“%l”表示行号,“%m”表示出错信息。

用“:h errorformat”查看详细的帮助信息。

“:h quickfix”、“:h make”、“:h makeprg”、“:h errorfile”查看其它的信息。

第三,使用快捷键

下面的这些快捷键对程序员很有帮助:
在函数中移动光标

[[  转到上一个位于第一列的“{”

]]  转到下一个位于第一列的“{”

{   转到上一个空行

}   转到下一个空行

gd  转到当前光标所指的局部变量的定义

*   转到当前光标所指的单词下一次出现的地方

#   转到当前光标所指的单词上一次出现的地方
括号的匹配

%   用来进行小括号、中括号和大括号的匹配。这要看当前光标指向的是什么符号了。

----------------------------------------------

一个ubuntu 下的vimrc配置例子:

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" 一般设定
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" 设定默认解码
set fenc
=utf-8
set fencs
=utf-8,usc-bom,euc-jp,gb18030,gbk,gb2312,cp936

"设定搜索是的高亮显示
set hlsearch

" 不要使用vi的键盘模式,而是vim自己的
set nocompatible

" history文件中需要记录的行数
set history=100

" 在处理未保存或只读文件的时候,弹出确认
set confirm

" 与windows共享剪贴板
set clipboard+=unnamed

" 侦测文件类型
filetype on

" 载入文件类型插件
filetype plugin on

" 为特定文件类型载入相关缩进文件
filetype indent on

" 保存全局变量
set viminfo+=!

" 带有如下符号的单词不要被换行分割
set iskeyword
+=_,$,@,%,#,-

" 语法高亮
syntax on

" 高亮字符,让其不受100列限制
:highlight OverLength ctermbg
=red ctermfg=white guibg=red guifg=white
":match OverLength '"%101v.*'

" 状态行颜色
highlight StatusLine guifg=SlateBlue guibg=Yellow
highlight StatusLineNC guifg=Gray guibg=White

"高亮当前行
set cursorline

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" 文件设置
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" 不要备份文件(根据自己需要取舍)
set nobackup

" 不要生成swap文件,当buffer被丢弃的时候隐藏它
setlocal noswapfile
set bufhidden=hide

" 字符间插入的像素行数目
set linespace
=0

" 增强模式中的命令行自动完成操作
set wildmenu

" 在状态行上显示光标所在位置的行号和列号
set ruler
set rulerformat
=%20(%2*%<%f%=" %m%r" %3l" %c" %p%%%)

" 命令行(在状态行下)的高度,默认为1,这里是2
set cmdheight=2

" 使回格键(backspace)正常处理indent, eol, start等
set backspace
=2

" 允许backspace和光标键跨越行边界
set whichwrap+=<,>,h,l

" 可以在buffer的任何地方使用鼠标(类似office中在工作区双击鼠标定位)
set mouse
=a
set selection
=exclusive
set selectmode
=mouse,key

" 启动的时候不显示那个援助索马里儿童的提示
set shortmess=atI

" 通过使用: commands命令,告诉我们文件的哪一行被改变过
set report
=0

" 不让vim发出讨厌的滴滴声
set noerrorbells

" 在被分割的窗口间显示空白,便于阅读
set fillchars
=vert:" ,stl:" ,stlnc:"

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" 搜索和匹配
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" 高亮显示匹配的括号
set showmatch

" 匹配括号高亮的时间(单位是十分之一秒)
set matchtime
=5

" 在搜索的时候不忽略大小写
set noignorecase

" 不要高亮被搜索的句子(phrases)
"set nohlsearch

" 在搜索时,输入的词句的逐字符高亮(类似firefox的搜索)
set incsearch

" 输入:set list命令是应该显示些啥?
set listchars=tab:
"|" ,trail:.,extends:>,precedes:<,eol:$

" 光标移动到buffer的顶部和底部时保持3行距离
set scrolloff
=3

" 不要闪烁
set novisualbell

" 我的状态行显示的内容(包括文件类型和解码)
set statusline
=%F%m%r%h%w" [FORMAT=%{&ff}]" [TYPE=%Y]" [POS=%l,%v][%p%%]" %{strftime(""%d/%m/%y" -" %H:%M"")}

" 总是显示状态行
set laststatus=2

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" 文本格式和排版
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" 自动格式化
set formatoptions=tcrqn

" 继承前一行的缩进方式,特别适用于多行注释
set autoindent

" 为C程序提供自动缩进
set smartindent

" 使用C样式的缩进
set cindent

" 制表符为4
set tabstop=4

" 统一缩进为4
set softtabstop
=4
set shiftwidth
=4

" 不要用空格代替制表符
set noexpandtab

" 不要换行
"set nowrap

"设置每行80个字符自动换行
set textwidth
=80

" 在行和段开始处使用制表符
set smarttab

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" CTags的设定
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" 按照名称排序
let Tlist_Sort_Type = 
"name"

" 在右侧显示窗口
let Tlist_Use_Right_Window 
= 1

" 压缩方式
let Tlist_Compart_Format = 1

" 如果只有一个buffer,kill窗口也kill掉buffer
let Tlist_Exist_OnlyWindow 
= 1

" 不要关闭其他文件的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++的编译和运行
map <F5> :call CompileRunGcc()<CR>
func! CompileRunGcc()
exec 
"w"
exec 
"!make"
exec 
"! ./%<"
endfunc

" shell script运行
map 
<F6> :call CompileRunSH()<CR>
func
! CompileRunSH()
exec 
"w"
exec 
"!chmod a+x %"
exec 
"!./%"
endfunc

" python运行
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

" 用空格键来开关折叠
set foldenable
set foldlevel
=0
set foldmethod
=indent
nnoremap 
<space> @=((foldclosed(line('.')) < 0? 'zc' : 'zo')<CR>

" minibufexpl插件的一般设置
let g:miniBufExplMapWindowNavVim = 1
let g:miniBufExplMapWindowNavArrows = 1
let g:miniBufExplMapCTabSwitchBufs = 1
let g:miniBufExplModSelTarget = 1

----------------------
一个相关帖子
http://forum.ubuntu.org.cn/viewtopic.php?f=68&t=138212&st=0&sk=t&sd=a

 

posted @ 2008-11-03 13:02 LukeW 阅读(1619) | 评论 (0)编辑 收藏