Rise的自留地

记录生活中的点滴,分享编程技术和游戏开发经验。

0%

曾几何时,服务里面弹出一个窗口到桌面上不再是那么地容易了:以前只要把服务设置为允许和桌面交互就可以直接在服务启动的时候,把一个窗口弹给用户。但是现在在vista(其它的OS 下没有测试,未知)下要弹出这样的窗体,首先会弹出一个提示框提示是否接否一个服务弹出来的消息,点接受后,才会在一个全灰的桌面里面弹出这个窗口。不用想,这样的用户体验,肯定是会被直接PASS。原因很简单,因为不同的用户间的桌面是不一样的,服务用的是System的权限,在vista里面是Session0,而用户的帐户不是这个(肯定大于0)。

看来,想弹出一个窗体,需要另一个程序来作辅助了。解决方案有两种:

  1. 开发一个程序A在启动的时候,随系统启动,并监控指定文件M,服务S有消息的时候,放在文件M里,A 感受了文件变化了,就去读这个文件里的内容,根据规则来作对应的动作。坏处很明显,当用户为了让系统跑得快的时候,这种自启动文件很容易被砍掉,导致了有些功能莫名奇妙地不可用。
  2. 同样地,也是开发一个程序A,用CreateProcessAsUser这个API来创建这个A ,并且发送到用户的桌面上去。好处是可以把这个A和服务S 放在同一个程序文件里面,根据不同的参数来启动不同的功能。这样用户除非是删除整个服务,否则不会有部分功能能用,又有部分功能不能用的问题。

现在来看看第二种方案,要想用CreateProcessAsUser这个API ,有这样几个步骤:

1.取得用户的令牌(Token)

2.指定好虚拟桌面

3.调用API创建这个用户进程。

在取得用户令牌的时候,又有几个方法:

1.从用户的进程上去剥

2.先用WTSGetActiveConsoleSessionId得到用户会话ID,再用WTSQueryUserToken这个API去取。

不过在vista下面,服务里面的WTSGetActiveConsoleSessionId这个API得到的总是0,也就是Session0,用这个创建出来的进程,还是属于一个服务进程。(而且这个API是XP以及以后的系统才会提供的,在早点的系统上就会调用失败)所以我们只好从用户的进程上去找,用户登录的时候,一定会有的进程就是:explorer.exe,这样可以遍历所有的进程去找到这个(如果是多人同时登录这个系统里,我也不知道该怎么办了,不知道有没有高人指点一下)。

这样创建出来的用户进程,在进程列表里面可以看到是活动用户的。但是如果在这里面使用一下文件选择框,或是去取一些系统目录,比如说用户的桌面,用户的收藏夹等,都会得到空。这时候因为没有指定用户环境造成的。使用CreateEnvironmentBlock这个API就可以搞定了。

**//// <summary>
/// 转全角的函数(SBC case)
/// </summary>
/// <param name="input">任意字符串</param>
/// <returns>全角字符串</returns>
///<remarks>
///全角空格为12288,半角空格为32
///其他字符半角(33-126)与全角(65281-65374)的对应关系是:均相差65248
///</remarks>
public string ToSBC(string input)
{
//半角转全角:
char[] c=input.ToCharArray();
for (int i = 0; i < c.Length; i++)
{
if (c[i]==32)
{
                     c[i]=(char)12288;
continue;
                 }
if (c[i]<127)
                     c[i]=(char)(c[i]+65248);
             }
return new string(c);               
         }


/**//// <summary>
/// 转半角的函数(DBC case)
/// </summary>
/// <param name="input">任意字符串</param>
/// <returns>半角字符串</returns>
///<remarks>
///全角空格为12288,半角空格为32
///其他字符半角(33-126)与全角(65281-65374)的对应关系是:均相差65248
///</remarks>
public string ToDBC(string input)
{   
char[] c=input.ToCharArray();
for (int i = 0; i < c.Length; i++)
{
if (c[i]==12288)
{
                     c[i]= (char)32;
continue;
                 }
if (c[i]>65280 && c[i]<65375)
                     c[i]=(char)(c[i]-65248);
             }
return new string(c);
         }

今天刚开始调试windows核心编程中的例程就感觉十分难懂,原因是自己的c++基本功力实在太弱了,首先在windows编程的过程中大量的使用宏的问题。
#pragma 的用法 在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。#pragma指令对每个编译器给出了一个方法,在保持与C和C ++语言完全兼容的情况下,给出主机或操作系统专有的特征。依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的。其格式一般为: #Pragma Para 其中Para 为参数,下面来看一些常用的参数。 (1)message 参数。 Message 参数是我最喜欢的一个参数,它能够在编译信息输出窗口中输出相应的信息,这对于源代码信息的控制是非常重要的。其使用方法为: #Pragma message(“消息文本”) 当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。当我们在程序中定义了许多宏来控制源代码版本的时候,我们自己有可能都会忘记有没有正确的设置这些宏,此时我们可以用这条指令在编译的时候就进行检查。假设我们希望判断自己有没有在源代码的什么地方定义了_X86这个宏可以用下面的方法

//#include "javacall.h"
#include "applet1.h"

//JNIEXPORT jint JNICALL Java_javacall_GetDES (JNIEnv *, jclass, jint p,jint k,jint z)
JNIEXPORT jint JNICALL Java_Applet1_GetDES(JNIEnv *, jclass, jint p,jint k,jint z)
{
int res=GetDES(p,k,z);
      return res;
}

jstring convertANSIToUNI(JNIEnv *env,char* cStr)

{       

                    int slen = strlen(cStr);

                    if(!env||slen==0)

                             return NULL;

                    jchar* buffer = new jchar[slen];

                    int len = MultiByteToWideChar(CP_ACP,0,cStr,strlen(cStr),(LPWSTR)buffer,slen);

                    if(len>0 && len < slen)

                             buffer[len]='\0';

                    jstring js = env->NewString(buffer,len);

                    delete [] buffer;

                    return js;    

}
void convertUniToANSI(JNIEnv *env,jstring oldStr,char* newStr)

{

                     int desc_len=256*2;

                     int len;

                     if(oldStr==NULL||newStr==NULL)

                              return ;

                     wchar_t *w_buffer = new wchar_t[256];

                     wcscpy(w_buffer,(LPWSTR)env->GetStringChars(oldStr,0));

                     env->ReleaseStringChars(oldStr,(jchar *)w_buffer);

                     len = WideCharToMultiByte(CP_ACP,0,w_buffer,1024,newStr,desc_len,NULL,NULL);

                     if(len>0 && len<desc_len)

                     {

                              newStr[len]='\0';

                     }

                     delete[] w_buffer;

}

JNIEXPORT jstring    JNICALL Java_Applet1_ReadIC(JNIEnv * env,jclass,jint l,jint k,jint m)
{
jstring js;
CString CSjs;
CSjs="12345678";
CSjs=ReadICrCS(l,k,m);
      AfxMessageBox(CSjs);
      char *cCSjs;
cCSjs=CSjs.GetBuffer();
      js=convertANSIToUNI(env,cCSjs);

return js;
}

JNIEXPORT jint JNICALL Java_Applet1_WriteIC(JNIEnv *env,jclass,jint l,jint k,jstring iw,jint m)
{
      char chContext[3000];
      convertUniToANSI(env,iw,chContext);
CString iwCS;
iwCS.Format(_T("%s"),chContext);
AfxMessageBox(iwCS);
int res=WriteICrCS(l,k,iwCS,m);
return res;
}

看一下这两个指令是如何影响变量在内存的存储的。

1、pack pragma

pack pragma设置了struct、union或class中各成员的对齐方式,结构成员对齐指的是成员相对于起始地址的偏移量。该指令基本用法如下:
#pragma pack(n) 它指定了结构成员按n(1,2,4,8,16)字节对齐,如果未指定n,则恢复成默认值。需要注意的是,它并不是指结构体中的每个成员都要按n对齐,而是按照每个成员的大小和n相比较小的值对齐。下面引用MSDN中C++ Preprocessor Reference部分关于pack指令的说明:

我们截获函数执行最直接的目的就是为函数增添功能,修改返回值,或者为调试以及性能测试加入附加的代码,或者截获函数的输入输出作研究,破解使用。通过访 问源代码,我们可以轻而易举的使用重建(Rebuilding)操作系统或者应用程序的方法在它们中间插入新的功能或者做功能扩展。然而,在今天这个商业 化的开发世界里,以及在只有二进制代码发布的系统中,研究人员几乎没有机会可以得到源代码。本文主要讨论Detour在Windows二进制PE文件基础 上的API截获技术。对于Linux平台,作这件事情将会非常的简单,由于最初的操作系统设计者引入了LD_PRELOAD。如果你设置  LD_PRELOAD=mylib.so ,那么应用程序在载入 dll时,会先查看mylib.so的符号表,在relocation 的时候会优先 使用mylib.so 里的 symbol 。假如你在mylib.so里有个printf() ,那么这个printf就会替代libc的 printf。 而在mylib.so里的这个printf可以直接访问 libc.so里的printf函数指针来获得真正的 printf的入口地 址。 这样,所有的dll的API HOOK在loader加载dll的时候就已经完成,非常自然,和平台相关的部分全部交给loader去处理。
一、  Detour开发库:
  简介
Detours是一个在x86平台上截获任意Win32函数调用的工具库。中断代码可以在运行时动态加载。Detours使用一个无条件转移指令来替换目 标函数的最初几条指令,将控制流转移到一个用户提供的截获函数。而目标函数中的一些指令被保存在一个被称为“trampoline” (译注:英文意为蹦 床,杂技)的函数中,在这里我觉得翻译成目标函数的部分克隆/拷贝比较贴切。这些指令包括目标函数中被替换的代码以及一个重新跳转到目标函数的无条件分 支。而截获函数可以替换目标函数,或者通过执行“trampoline”函数的时候将目标函数作为子程序来调用的办法来扩展功能。
Detours是执行时被插入的。内存中的目标函数的代码不是在硬盘上被修改的,因而可以在一个很好的粒度上使得截获二进制函数的执行变得更容易。例如, 一个应用程序执行时加载的DLL中的函数过程可以被插入一段截获代码(detoured),与此同时,这个DLL还可以被其他应用程序按正常情况执行(译 注:也就是按照不被截获的方式执行,因为DLL二进制文件没有被修改,所以发生截获时不会影响其他进程空间加载这个DLL)。不同于DLL的重新链接或者 静态重定向,Detours库中使用的这种中断技术确保不会影响到应用程序中的方法或者系统代码对目标函数的定位。
如果其他人为了调试或者在内部使用其他系统检测手段而试图修改二进制代码,Detours将是一个可以普遍使用的开发包。据我所知,Detours是第一 个可以在任意平台上将未修改的目标代码作为一个可以通过“trampoline”调用的子程序来保留的开发包。而以前的系统在逻辑上预先将截获代码放到目 标代码中,而不是将原始的目标代码做为一个普通的子程序来调用。我们独特的“trampoline”设计对于扩展现有的软件的二进制代码是至关重要的。
出于使用基本的函数截获功能的目的,Detours同样提供了编辑任何DLL导入表的功能,达到向存在的二进制代码中添加任意数据节表的目的,向一个新进 程或者一个已经运行着的进程中注入一个DLL。一旦向一个进程注入了DLL,这个动态库就可以截获任何Win32函数,不论它是在应用程序中或者在系统库 中。
  基本原理
1.  WIN32进程的内存管理
众所周知,WINDOWS NT实现了虚拟存储器,每一WIN32进程拥有4GB的虚存空间, 关于WIN32进程的虚存结构及其操作的具体细节请参阅WIN32 API手册, 以下仅指出与Detours相关的几点:
(1) 进程要执行的指令也放在虚存空间中
(2) 可以使用QueryProtectEx函数把存放指令的页面的权限更改为可读可写可执行,再改写其内容,从而修改正在运行的程序
(3) 可以使用VirtualAllocEx从一个进程为另一正运行的进程分配虚存,再使用 QueryProtectEx函数把页面的权限更改为可读可写可执行,并把要执行的指令以二进制机器码的形式写入,从而为一个正在运行的进程注入任意的代码 。
2. 拦截WIN32 API的原理
Detours定义了三个概念:
    (1) Target函数:要拦截的函数,通常为Windows的API。
(2) Trampoline函数:Target函数的部分复制品。因为Detours将会改写Target函数,所以先把Target函数的前5个字节复制保存好,一方面仍然保存Target函数的过程调用语义,另一方面便于以后的恢复。
(3) Detour 函数:用来替代Target函数的函数。
Detours在Target函数的开头加入JMP Address_of_ Detour_ Function指令(共5个字节)把对Target函数 的调用引导到自己的Detour函数, 把Target函数的开头的5个字节加上JMP Address_of_ Target _ Function+ 5共10个字节作为Trampoline函数。请参考下面的图1和图2。
(图1:Detour函数的过程)
crack_01
(图2: Detour函数的调用过程)
crack_02
说明:
  目标函数:
目标函数的函数体(二进制)至少有5个字节以上。按照微软的说明文档Trampoline函数的函数体是拷贝前5个字节加一个无条件跳转指令的话(如果没 有特殊处理不可分割指令的话),那么前5个字节必须是完整指令,也就是不能第5个字节和第6个字节是一条不可分割的指令,否则会造成Trampoline 函数执行错误,一条完整的指令被硬性分割开来,造成程序崩溃。对于第5字节和第6个字节是不可分割指令需要调整拷贝到杂技函数(Trampoline)的 字节个数,这个值可以查看目标函数的汇编代码得到。此函数是目标函数的修改版本,不能在Detour函数中直接调用,需要通过对Trampoline函数 的调用来达到间接调用。
  Trampoline函数:
此函数默认分配了32个字节,函数的内容就是拷贝的目标函数的前5个字节,加上一个JMP Address_of_ Target _ Function+5指令,共10个字节。
此函数仅供您的Detour函数调用,执行完前5个字节的指令后再绝对跳转到目标函数的第6个字节继续执行原功能函数。
  Detour函数:
此函数是用户需要的截获API的一个模拟版本,调用方式,参数个数必须和目标函数相一致。如目标函数是__stdcall,则Detour函数声明也必须 是__stdcall,参数个数和类型也必须相同,否则会造成程序崩溃。此函数在程序调用目标函数的第一条指令的时候就会被调用(无条件跳转过来的),如 果在此函数中想继续调用目标函数,必须调用Trampoline函数(Trampoline函数在执行完目标函数的前5个字节的指令后会无条件跳转到目标 函数的5个字节后继续执行),不能再直接调用目标函数,否则将进入无穷递归(目标函数跳转到Detour函数,Detour函数又跳转到目标函数的递归, 因为目标函数在内存中的前5个字节已经被修改成绝对跳转)。通过对Trampoline函数的调用后可以获取目标函数的执行结果,此特性对分析目标函数非 常有用,而且可以将目标函数的输出结果进行修改后再传回给应用程序。
Detour提供了向运行中的应用程序注入Detour函数和在二进制文件基础上注入Detour函数两种方式。本章主要讨论第二种工作方式。通过 Detours提供的开发包可以在二进制EXE文件中添加一个名称为Detour的节表,如下图3所示,主要目的是实现PE加载器加载应用程序的时候会自 动加载您编写的Detours DLL,在Detours Dll中的DLLMain中完成对目标函数的Detour。
(图3)
crack_03
二、  Detours提供的截获API的相关接口
Detours的提供的API 接口可以作为一个共享DLL给外部程序调用,也可以作为一个静态Lib链接到您的程序内部。
Trampoline函数可以动态或者静态的创建,如果目标函数本身是一个链接符号,使用静态的trampoline函数将非常简单。如果目标函数不能在链接时可见,那么可以使用动态trampoline函数。
  要使用静态的trampoline函数来截获目标函数,应用程序生成trampoline的时候必须使用
DETOUR_TRAMPOLINE宏。DETOUR_TRAMPOLINE有两个输入参数:trampoline的原型和目标函数的名字。
注意,对于正确的截获模型,包括目标函数,trampoline函数,以及截获函数都必须是完全一致的调用形式,包括参数格式和调用约定。当通过 trampoline函数调用目标函数的时候拷贝正确参数是截获函数的责任。由于目标函数仅仅是截获函数的一个可调用分支(截获函数可以调用 trampoline函数也可以不调用),这种责任几乎就是一种下意识的行为。
使用相同的调用约定可以确保寄存器中的值被正确的保存,并且保证调用堆栈在截获函数调用目标函数的时候能正确的建立和销毁。
可以使用DetourFunctionWithTrampoline函数来截获目标函数。这个函数有两个参数:trampoline函数以及截获函数的指针。因为目标函数已经被加到trampoline函数中,所有不需要在参数中特别指定。
  我们可以使用DetourFunction函数来创建一个动态的trampoline函数,它包括两个参数:一个指向目标函数的指针和一个截获函数的指针。DetourFunction分配一个新的trampoline函数并将适当的截获代码插入到目标函数中去。
当目标函数不是很容易使用的时候,DetourFindFunction函数可以找到那个函数,不管它是DLL中导出的函数,或者是可以通过二进制目标函数的调试符号找到。
DetourFindFunction接受两个参数:库的名字和函数的名字。如果DetourFindFunction函数找到了指定的函数,返回该函数 的指针,否则将返回一个NULL指针。DetourFindFunction会首先使用Win32函数LoadLibrary 和 GetProcAddress来定位函数,如果函数没有在DLL的导出表中找到,DetourFindFunction将使用ImageHlp库来搜索有 效的调试符号(译注:这里的调试符号是指Windows本身提供的调试符号,需要单独安装,具体信息请参考Windows的用户诊断支持信息)。 DetourFindFunction返回的函数指针可以用来传递给DetourFunction以生成一个动态的trampoline函数。
我们可以调用DetourRemoveTrampoline来去掉对一个目标函数的截获。
注意,因为Detours中的函数会修改应用程序的地址空间,请确保当加入截获函数或者去掉截获函数的时候没有其他线程在进程空间中执行,这是程序员的责任。一个简单的方法保证这个时候是单线程执行就是在加载Detours库的时候在DllMain中呼叫函数。
三、  使用Detours实现对API的截获的两种方法
建立一个MFC对话框工程,在对话框的OK按钮的单击事件中加入对MessageBoxA函数的调用,编译后的程序名称MessageBoxApp,效果如图。
crack_04
(图4)
  静态方法
建立一个Dll工程,名称为ApiHook,这里以Visual C++6.0开发环境,以截获ASCII版本的MessageBoxA函数来说明。在Dll的工程加入:
DETOUR_TRAMPOLINE(int WINAPI Real_Messagebox(HWND hWnd ,
    LPCSTR lpText,
    LPCSTR lpCaption,
UINT uType), ::MessageBoxA);
生成一个静态的MessageBoxA的Trampoline函数,在Dll工程中加入目标函数的Detour函数:
int WINAPI MessageBox_Mine( HWND hWnd ,
    LPCSTR lpText,
    LPCSTR lpCaption,
    UINT uType)
{
  CString tmp= lpText;
  tmp+=” 被Detour截获”;
  return Real_Messagebox(hWnd,tmp,lpCaption,uType);
//  return ::MessageBoxA(hWnd,tmp,lpCaption,uType);  //Error
}
在Dll入口函数中的加载Dll事件中加入:
DetourFunctionWithTrampoline((PBYTE)Real_Messagebox, (PBYTE)MessageBox_Mine);
在Dll入口函数中的卸载Dll事件中加入:
DetourRemove((PBYTE)Real_Messagebox, (PBYTE)MessageBox_Mine);
  动态方法
建立一个Dll工程,名称为ApiHook,这里以Visual C++6.0开发环境,以截获ASCII版本的MessageBoxA函数来说明。在Dll的工程加入:
//声明MessageBoxA一样的函数原型
typedef int  (WINAPI * MessageBoxSys)( HWND hWnd ,
    LPCSTR lpText,
    LPCSTR lpCaption,
    UINT uType);
//目标函数指针
MessageBoxSys SystemMessageBox=NULL;
//Trampoline函数指针
MessageBoxSys Real_MessageBox=NULL;
在Dll工程中加入目标函数的Detour函数:
int WINAPI MessageBox_Mine( HWND hWnd ,
    LPCSTR lpText,
    LPCSTR lpCaption,
    UINT uType)
{
  CString tmp= lpText;
  tmp+=” 被Detour截获”;
  return Real_Messagebox(hWnd,tmp,lpCaption,uType);
//  return ::MessageBoxA(hWnd,tmp,lpCaption,uType);  //Error
}
在Dll入口函数中的加载Dll事件中加入:
  SystemMessageBox=(MessageBoxSys)DetourFindFunction("user32.dll","MessageBoxA");
  if(SystemMessageBox==NULL)
  {
    return FASLE;
  }
  Real_MessageBox=(MessageBoxSys)DetourFunction((PBYTE)SystemMessageBox, (PBYTE)MessageBox_Mine);
在Dll入口函数中的卸载Dll事件中加入:
DetourRemove((PBYTE)Real_Messagebox, (PBYTE)MessageBox_Mine);
  重写二进制可执行文件
使用Detours自带的SetDll.exe重写二进制可执行文件,可以在需要截获的程序中加入一个新的Detours的PE节表。对于本文就是新建一个批处理文件调用SetDll.exe。
@echo off
if not exist MessageBoxApp.exe (
echo 请将文件解压到MessageBoxApp.exe的安装目录, 然后执行补丁程序
) else (
setdll /d:ApiHook.dll MessageBoxApp.exe
)
Pause
调用后使用depends.exe(微软VC6.0开发包的工具之一)观察MessageBoxApp.exe前后变化, 可以看到Setdll已经重写MessageBoxApp.exe
成功,加入了对ApiHook.dll的依赖关系。
crack_05
      (执行SetDll.exe前)                                                       (执行SetDll.exe后)
执行SetDll.exe重写后的MessageBoxApp.exe,点击确定后可以看到结果如下:
至此,MessageBoxApp.exe对MessageBoxA函数的调用已经被截获,弹出的对话框内容已经明显说明这一点。
crack_06

(1)CPU篇
很多人认为CPU主频越高越强,这条件只存在于同等架构的CPU下对比才能成立。例如3G的奔腾D915能比2.6G的5000+强吗?2.6G的5000+能比2.33G的E6550强吗?不可能,因为架构根本不同,没得比,只能从实测性能去评估。某些人说“Intel的CPU稳定,AMD的玩游戏快,不过就是不稳定,而且兼容性也不够”,真的是那样吗?首先是否稳定是取决于电源供电率是否能保持稳定,还有主板滤波,系统也优化占有很大程度。至于兼容,有人敢说CPU也有兼容性问题的就可以无视了,明显不是小白就是忽悠人,只要没有硬伤,主板芯片和供电也是支持的话兼容是绝对没问题的。而且当时说AMD玩游戏好并不是指AMD的CPU游戏性能就是比Intel高,只是达到同等游戏性能的话用AMD平台花费得更少。而整机性能是否强悍并不是只取决于CPU,还要考虑内存,512M内存+E6550也不见得比PE2180+1G内存流畅,玩游戏的更要把显卡也考虑进去。玩高配置游戏游戏的时候,如果你用QX6600+8600GT,效果比E6550+8800GT差也更加正常,希望大家购机时不要只看CPU,还得根据自己的实际用途和整体性能均衡去考虑。我帮人配机的时候就遇到N个人说什么CPU要强点的,有限预算内把CPU加强就等于要降低其它的性能,根本是破坏整体均衡性能,反而得不偿失。你跑个系统看得出E6550和PE2180这相差700元的CPU的性能差别吗?你玩玩大型游戏的话,差距700元的显卡就足以让你体验什么是游戏性能。
(2)主板篇

大部分JS都说华硕主板好,大品牌的话能差吗?(能说出这话的人就可以证明他没有能耐,只能信品牌。)我可以告诉你们,如果大品牌真的全部都这么好,为什么其他品牌还能有活路?难道消费者全部都是不懂吗?主板的好坏在于主板的布局设计,用料,散热等方面,很大程度上影响主板的寿命。再好的大厂也有垃圾板,再弱的小厂也会有好板,500元在大厂买低端板和在小厂买高端板,这大厂的板能比得上吗?有些人还说“大厂的主板就是稳定”难道二三线厂的主板就不稳定吗?开几个QQ就死机?品牌观啊!难道布局有点不同就非要说这是大厂增加稳定性的设计?简直开玩笑,要是立场对调,不知道那种人还怎么看。现时很多人说什么主板是全固态电容的,全固就一定好吗?那只是一个卖点。日常使用,无论固态还是电解电容都是一样的用,不要被所谓的全固蒙蔽了眼睛,一个固态电容能值几个钱?难道打仗的时候,金铸的大炮就会比铜铸的大炮要好?高性能主板能提升性能?性能取决于CPU,内存,显卡,硬盘这些,主板起作支架作用。平台的主板就像一个人的身体那样,一个身体很壮的人,但手脚不灵活,脑筋也不发达,能多干活吗?主板需求的是稳定,耐用,有些人还强调需要超频。至于高性能,我说:“什么叫高性能的主板?能让CPU和显卡发挥超越设定的性能吗?一派胡言!”最近很多人喜欢做SLI,说双显卡性能高,但必须主板支持。我想问问,是否真的有做SLI的必要?首先SLI就是加大电源和CPU的负荷,退一步说让你8600GT做SLI,还不如买张8800GT或者HD3850,2张8800GT做SLI还不如直接买8800Ultra。假如你做SLI的话,那需要什么用的CPU?这个价位组建的平台还得用那普通的SLI主板吗?早就用那些2000多块的主板了,什么时候才轮得到它?我帮人配机极少用太高端主板,基本是做工用料设计布局都行的就没问题,最紧要的就是稳定耐用。太高端的板也不见得稳定性能高到哪,还不如用多出来的预算在电源,CPU,显卡,内存方面加强,这样才配出同等价位更高性能的配置。
(3)内存篇

内存容量当然越多越好,现在1G内存已经普及了。只要你不是超频发烧友,基本都没必要专门挑选特别好的内存,个人习惯是用宇瞻,金士顿(正货),威刚(红色威红),金邦(白金)这些。黑金刚悍将版的内存也很能超,那是采用D9GMH颗粒的内存条,耐压度强比较适合超频用,不过D9颗粒的内存存在一个致命的弱点,就是兼容性比较差,现在的D9超频条也普遍存在较早夭折的问题。所以不建议普通用户使用,大型游戏时DDR667和DDR800的性能差异也只在2%-3%的差距,可以感觉出实际差别吗?我让你超到DDR1000以上,性能明显不?而且这对散热,内存颗粒,主板支持度有很大关系,搞不好的话使硬件过早老化,系统不稳定等问题。我自己的机子也只是小超玩一把,要记住:性能和寿命往往成反比,看看那些超频发烧友的机子用了多久?有连续3年保持极限超频的机子去用?我也并不是说叫大家绝对不要超频,但超频是必须建立在系统稳定和散热良好的情况下进行,往往会增加不少额外的预算,所以说只要内存能兼容就可以了没有必要太追求过高带宽,反而会为自己的金钱和正常使用带来麻烦。
(4)显卡篇
不少商家卖显卡都说什么512M的独立显卡,那显卡算高性能吗?显存再高也是忽悠人的,你究竟买张什么样的显卡你知道吗?8500GT 512M(DDR2显存)在游戏上的性能连7300GT 256M(DDR3显存)也比不上,就连8800GT这级别的显卡512M与256M性能差异也只在数个百分点之间,其它的低端显卡还比得出性能差别?显卡性能取决于芯片性能,芯片频率,显存频率,至于其稳定性和耐用度也得看显卡布局设计,用料,散热装置。有些主板商说xx主板集成显卡相当于独立显卡的性能,那简直是一派胡言。现在的显卡都得上散热片+风冷,难道你比得上独立显卡性能的就可以不上风冷?如果有这样的技术早就在独立显卡上应用了,显卡厂商就早用来降低散热系统的成本了。就算同样的显示芯片,也永远不可能达到同等芯片频率和显存频率,而且共享内存的延迟远远大于独立显存的延迟,所以指望集成显卡能比得上独立显卡的人,你想都别想,除非是比N年前的MX440这些还可以。
(5)电源篇
一般人总会忽略电源稳定性问题,只认为电源功率够用就可以了,殊不知电源的供电稳定性直接影响硬件(特别是主板)的寿命。例如曾经有个服务器的电源,测试的时候,供电是只是短时间在12.47-12.52V徘徊,=_=!稳定得令人心寒。功率问题还得多说一句,一般电源的额定功率(就是指保证稳定的功率)是占峰值功率的70-80%之间(简称转换率),JS经常说300W电源一般都是指峰值300W电源,其实际功率一般都是220W,如果有独立显卡的话,令人担忧。如果是有独立显卡的用户,要买就买额定300W的电源,而且电源我一般都不用杂牌的。要想系统稳定就得先要电源功率稳定,个人习惯用TT,航嘉,先马,全汉,康舒,海韵等电源。大陆市场似乎很多人用长城,个人随机抽一个长城电源测试,电压是在11.87-12.47V徘徊,功率真的不那么稳定,被誉为:硬件杀手!其它杂牌的就更不用说了。要想系统稳定就先得挑好电源,为何服务器专用电源会这么贵?这不用多说吧?因为一个供电稳定的电源是保证一台机子稳定的重要开端。

一,默认的工作频率
目前
事实上,大多数用户只是把电脑当作一个工具,工作或娱乐的工具,对超频并不感兴趣,应用中也不需要超频。如果因为某个配件据称“包超XXMhz”,因此而选购,就很容易陷入超频的误区。事实上,超频并不是某个设备OC一下就可以实现的事,围绕超频,应该是一系列硬件协调配合的结果,比如CPU能超,那就需要主板适合超频,bios关于超频的内容非常丰富,主板上的供电回路、电容、MOS等相应地就需要提高一个档次,同时,系统的散热和供电就得加强。。。哇,突然间,你是不是发现主板、风扇、电源一下子就贵了好多?如果实践一下,又会发现DDRII667成了OC的瓶颈,是不是又得更换成DDRII800?
原来你预想4K的开销,突然间就跃升到5K或更多,那么事实上你是否需要把电脑超频起来使用呢?更郁闷的是,你超频起来使用,性能未必就能超越不超频的5K配置。
这里并不是说抛弃超频,超频对于部分人来说是一种乐趣、一种成就感,但于大多数人来说,未必有意思。换句话说,你把一只X2 3800+超到5000+,还不如直接选购一只X2 4000+或更高主频的CPU.显卡的超频也类似,需要扎实的基板、强化的散热系统,但还是容易导致花屏和贴图出错。
在默认频率的条件下,硬件是最稳定的,也会是最长寿的。而稳定、长寿,带来的是愉快的心情,同时减少相当多无谓的开销。与心情和经济均有利的事,何乐而不为呢?
二,扎实的主板
因为CPU、内存的寿命和稳定性都是非常统一的,因此,焦点就在于主板。一块做工优良、用料扎实的主板就成为重中之中。好多人在主板上省钱,这是不太明智的。关于主板的选购,牵涉到太多的技术细节,本文就不在此详细展开(有机会详谈)。就个人观点而言,请注意以下二点:
1,ATX标准版型。标准的PCB基板,意味着厂家尽善的电路设计和合格的电气性能。通常而言6层基
板,可以达到公版的设计要求。
2,标准的三相或四相供电回路设计。对于非超频系统,三相供电可以满足应用要求。每一项通常由一个电感线圈、二片MOS、一颗电容构成。此时要注意线圈、MOS的品质,电容的品质和数量。其中电容比较直观,而且主板的稳定与否也与此有关。英特尔对于电容的总容量也有相应的要求。简单地说,6颗以上日系电容意味着稳定。如果采用了固态电容,会意味着更强的稳定性和寿命。固态电容不光不容易暴浆,还带来更低的ESR值。
三,优质的电源。
这个问题好多人都忽略了,当看到机箱上带有电源时,就听从JS的说法,一块儿买了下来。
事实上,机箱上自带的电源,为OEM版电源,与DIY市场上的零售版,在实足的额定功率,电路的设计和用料上都有很大的差别。以全汉为例,技嘉机箱上经常带有全汉OEM的电源,但机箱电源的功率往往虚标(实际功率偏低),电路简化,二级滤波通常不完善。
我们知道,电脑硬件需要的直流工作电流,如果由交流转为直流处理得不够纯净,当电压波动时,会对硬件造成一定的冲击,就会对硬件的寿命生产影响。另一方面,从节省能源的角度说,我们更需要主动PFC电路的电源,转换因子会更高,也就是更省电,但OEM版通常不会有主动PFC的。
这类OEM电源的问题,在金河田、大水牛等著名机箱上也很常见,通常的原则就是一律放弃。
第四,强化散热系统
这也是大家容易忽视的问题。通常大家根据攒机单选购标配设备,JS装机完成后,就满足地回家了。
事实上,机箱内部局部的温室效应将致使硬件处于高温工作环境下,稳定性和寿命都会大打折扣。特别是在夏天,即使低TDP的K8、酷睿也会处于明显的高温之中,更别说显卡GPU、硬盘的温度了。
高温是硬件的杀手,高温也是导致重要电子元器件PN结击穿的罪魁,类似于电子元件PN结击穿的现象,在电容器上的表现就是热击穿,就是俗话中的“电容暴浆”。网上有非常多电容暴浆的惨图,此时系统会变得非常不稳定,容易死机,显卡容易花屏,甚至无法点亮桌面。如果注意了散热,电容暴浆及其它半导体器件损坏的机率就会直线下线,各类电子元件也就可以达到应有的理论寿命。
对于机箱内部的散热,主要是建立合理的风道。比如前置风扇与后置风扇,形成一进一出的风道,同时尽量做到风扇数量少而精,口径大而转速低,避免在加强散热的同时却导致噪音大增。机箱内部宽敞的空间对于散热也是非常有帮助的。
你在攒机时,是否考虑过上述问题呢?如果你能,那么恭喜你,你的攒机技术已经比较成熟了 DIY[font=宋体]市场竞争剧烈,厂商们纷纷在概念上动足脑筋,比如超频、动态对比度、廉价。其中超频卖点非常吸引眼球。