- 博客(47)
- 收藏
- 关注
原创 TCP/IP协议族(2)-封装和分用
封装上层协议是如何使用下层协议提供的服务?其实这是通过封装(encapsulation)实现的。应用程序数据在发送到物理网络之前,将沿着协议栈从上往下依次传递。每层协议都将在上层数据的基础上加上自己的头部信息(有时还包括发问信息),以实现该层的功能,这个过程就称为封装。经过TCP封装后的数据称为TCP报文段(TCP message segment),或者简称TCP段。TCP协议
2013-09-20 20:57:39 630
原创 TCP/IP协议族(1)——体系结构
TCP/IP协议族是一个四层协议系统,自底而上分别是数据数据链路层、网络层、传输层和应用层。每一层完成不同的功能,且通过若干协议来实现,上层协议使用下层协议提供的服务。1 数据链路层数据链路层实现了网卡接口的网络驱动程序,以处理处理数据在物理媒介(比如以太网、令牌环等)上的传输。不同的物理网络具有不同的电气特性,网络驱动程序隐藏了这些细节,为上层协议提供了一个统一的接口。数据链
2013-09-17 23:08:57 673
原创 windows向linux发送文件的小程序
windows下的程序:#include "stdafx.h"#include #include #include #include #pragma comment( lib, "WS2_32.lib" ) #define BUF_SIZE 64 // 缓冲区大小 int _tmain( int argc, _TCHAR* argv[
2013-09-16 21:49:55 534
原创 编码优化
同深层次的设计问题相比,性能方面的编码问题更容易解决,这些问题的规模通常较小,在其解决方法中,所包含的代码量都很小。1 缓存缓存主要用来存储使用频繁而且代价高昂的计算结果,这样就可以避免对这些结果的重复计算。for(...; !done; ...){ done = patternMatch( pat1, pat2, isCaseSensitive() );}由于isCase
2013-08-29 22:17:39 718
原创 深入解析Windows操作系统(二)系统结构(1)
线上面的方框代表了用户的进程,线下面的组件是内核模式的操作系统。用户模式的线程在一个受保护的进程地址空间中执行,因此系统支持进程、服务进程、用户应用程序和环境子系统都有它们各自的私有进程地址空间。1)系统支持进程(system support processes),比如登录(logon)进程和会话管理器(session manager),它们并不是WINDOWS的服务(不是由服务控制器来启动的
2013-08-28 22:35:47 799
原创 为何不能过多的使用内联(为何有时内联无法提升性能)?
内联带来的性能提升?1、避免开销大的方法调用。2、调用间优化。某一方法的调用过程,基于对上下文场景更加全面的理解,使得编译器在源代码层面及机器代码层面对方法进行优化。为啥不能内联全部方法?1、内联所带来的代码膨胀有时是无法接受的。2、单个内联方法拥有多个实例,每个实例都要有自身的地址空间,因此它们消耗的缓存也相互独立,这样将减少有效的缓存空间而造成命中率下降。而且,内联
2013-08-24 21:37:39 620
原创 UNIX基础知识
shellshell是一个命令行解释器,它读取用户输入,然后执行命令,用户通常用终端,有时用文件(称为shell脚本)向shell进行输入。文件系统UNIX文件系统是目录和文件的一种层次安排,目录的起点是根(root),名字是字符/。目录(directory)是一个包含目录项的文件,逻辑上,可以认为每个目录项都包含一个文件名,同时还包含说明该文件属性的信息。文件名目录中的各
2013-08-20 19:37:49 406
转载 一个简单的makefile示例及其注释
原文:http://www.cnblogs.com/sld666666/archive/2010/04/08/1707789.html下面是一个极其简单的例子:现在我要编译一个Hello world,需要如下三个文件: 1. print.h #include void printhello(); 2. print.c #in
2013-08-06 15:57:20 646
原创 Windows核心编程(十)
第十九章 DLL基础动态链接库(dynamic-link library,DLL)一直以来都是Windows操作系统的基石。Windows应用程序编程接口(application programming inferface,API)提供的所有函数都包含在DLL中。其中三个最重要的DLL分别是:Kernel32.dll,包含的函数用来管理内存、进程及线程;User32.dll,包含的函数用来执行
2013-07-15 09:38:11 775
原创 Windows核心编程(九)
第十八章 堆堆的优点是它能让我们专心解决手头上的问题,而不必理会分配粒度和页面边界这类事情。它的缺点是分配和释放内存块的速度比其它方式慢,而且了却无法物理存储器的调拨和撤销调拨进行直接控制。在系统内部,堆是一块预订的地址空间区域。刚开始,区域内的大部分页面都没有调拨物理存储器。随着我们不断从堆中分配内存,堆管理器会给堆调拨越来越多的物理存储器。这些物理存储器始终是从页交换文件中分配的。释放
2013-07-13 20:48:32 530
原创 Windows核心编程(八)
第十七章 内存映射文件与虚拟内存相似,内存映射文件允许开发人员预订一块地址空间区域并给区域调拨物理存储器。不同之处在于,内存映射文件的物理存储器来自磁盘上已有的文件,而不是来自系统的页交换文件。内存映射文件主要用于以下三种情况:1)系统使用内存映射文件载入并运行.exe和动态链接库(DLL)文件。这大量节省了页交换文件的空间以及应用程序启动的时间。2)开发人员可以用内存映射文件来访
2013-07-09 23:20:58 737 1
原创 Windows核心编程(七)
十五、在应用程序中使用虚拟内存Microsoft Windows提花了以下三种机制来对内存进行操控。1)虚拟内存 最适合用来管理大型对象数组或大型结构数组。2)内存映射文件 最适合用来管理大型数据流(通常是文件),以及在同一机器上运行的多个进程之间共享数据。3)堆 最适合用来管理大量的小型对象。Windows提供了一些用来操控虚拟内存的函数,我们可以通过这些函数直接预订地址空
2013-07-09 23:19:33 660
原创 Windows核心编程(六)
十三、Windows内存体系结构每个进程都有自己的虚拟地址空间,对32位进程来说,这个地址空间大小为4GB = 2^32。对于64位地址来说,大小为16EB=2^64。每个进程的虚拟地址空间被划分为许多分区,Windows内核不同分区略有变化,以X86 32位Windows为例,0x00000000~0x0000FFFF为空指针赋值分区;0x00010000~0x7FFFFFFFF
2013-07-09 21:44:03 584
原创 Windows核心编程(五)
十一、Windows线程池Windows提供了一个(与I/O完成端口相配套的)线程池机制来简化线程的创建、销毁以及日常管理。这个通用的线程池可能并不适用于所有的情况,但很多情况下能够满足需要并节省大量的开发时间。这些新的线程池函数允许我们做以下这些事情:1、以异步的方式来调用一个函数2、每隔一段时间调用一个函数3、当内核对象触发的时候调用一个函数4、当异步I/O请求完成的时
2013-07-05 21:30:47 527
原创 Windows核心编程(四)
十、同步设备I/O与异步设备I/OHANDLE WINAPI CreateFile( __in LPCTSTR lpFileName, __in DWORD dwDesiredAccess, __in DWORD dwShareMode, __in LPSECURITY_ATTRIBUTES lpSec
2013-07-03 22:21:41 608
原创 Windows核心编程(三)
六、线程基础进程有两个组成部分:一个进程内核对象和一个地址空间。类似地,线程也有两个组成部分:1)一个是线程的内核对象,操作系统用它管理线程。系统还用内核对象来存放线程统计信息的地方。2)一个线程栈,用于维护线程执行时所需的所有函数参数和局部变量。一个进程中的所有线程共享同一个地址空间,共享同一个句柄表。
2013-07-03 13:10:18 651
原创 Windows核心编程(二)
4 进程进程通常被定义为一个正在运行的实例,由两部分组成:系统用来管理这个进程的内核对象、地址空间(包括所有可执行模块或DLL模块的数据和代码)。应用程序进入点32位系统中,HINSTANCE和HMODULE是完全相同的对象,它表示可执行文件或DLL文件加载到进程空间时所用的基地址。可以用下面的函数得到一个模块的句柄/基地址:
2013-07-01 14:24:54 494
原创 Windows核心编程(一)
一、对程序错误的处理调用Windows函数时,为是查看函数是否调用成功,通常查看函数的返回值来确定是否成功,还可以使用GetLastError()来确定是什么具体问题。Windows函数运行失败时,应立即调用GetLastError(),否则可能被别的函数修改。在VS中调试时,在watch窗口输入"@err,hr",就能查看到当前的错误代码和错误详细描述。使用FormatMessage
2013-06-26 14:41:02 631
原创 深入解析Windows操作系统(一)概念和工具
1 关于Windows NT和Windows 95Windows NT:Microsoft Windows NT(New Technology)是Microsoft在1993年推出的面向工作站、网络服务器和大型计算机的网络操作系统,也可做PC操作系统。它与通信服务紧密集成,基于OS/2 NT基础编制。OS/2由微软和IBM联合研制,分为微软的Microsoft OS/2 NT与IBM的IBM
2013-06-23 16:11:27 1375
原创 走向linux
看《程序员的职业素养》,里面相当篇幅说的是linux下的内容,跑马观花的看了这部分,比较懵懂,windows方面看得比较详细,毕竟一直接触的是windows下的编程。手里有某本操作系统的书,也是大量的讲了unix,对于这个未知的领域,实在有些忍不了了,决定了解一下linux以及linux下的代码开发。网上搜了些资料,据说流行版本的linux内核一致,然后某些网上推荐ubuntu,于是就下了ub
2013-06-14 23:10:04 510
原创 MSVC启动过程
VC9的默认入口函数源码:__declspec(noinline)int__tmainCRTStartup( void ){ int initret; int mainret=0; int managedapp;#ifdef _WINMAIN_ _TUCHAR *lpszCommandL
2013-06-09 15:29:59 650
原创 PE文件格式
1 PE文件结构2 文件头PE 文件头是一个 IMAGE_NT_HEADERS 类型的结构,它在WINNT.H文件中定义。typedef struct _IMAGE_NT_HEADERS { DWORD Signature; IMAGE_FILE_HEADER FileHeader; IMAGE_OPTIONAL_HEADER Optional
2013-05-28 21:23:36 839
原创 初识Java—Java的特点
简单的1、风格类似于C++,因此C++程序员容易掌握Java。2、抛弃了C++中容易引发错误的特性,比如指针、结构、枚举以及内存管理等。3、提供了丰富的类库,方便开发使用。面对对象的Java是完全面向对象的,它支持继承、重载、多态等面向对象的技术。它不支持C语言那样的面向过程的程序设计技术。健壮的Java致力于检查程序在编译和运行时的错误。Java也是一
2013-05-25 12:39:01 489
原创 纯虚类的析构函数的问题
class IA{public: virtual void Test() = 0; virtual void Release() = 0;};Review同事代码的时候,看到声明了接口类的析构函数,然后后面是一个空实现:class IA{public: virtual void Test() = 0; virtual ~IA(){}};觉得有点别扭,按道理
2013-05-23 16:23:03 748
原创 XAML初学
整理自某下载的PPT《XAML基础教程》1 XML与XAML1.XML指可扩展标记语言(EXtensible Markup Language)XML 是一种标记语言,很类似HTML标记语言XML 的设计宗旨是传输数据,而非显示数据XML 标签没有被预定义,需要自行定义标签示例:GeorgeJohnReminderDon't forget the meeting!
2013-05-16 13:28:39 740
原创 《Thinking in C++, 2nd Edition》笔记-第十九章(Run-time type identification)
只有一个基类指针或引用的时候,可以通过运行时类型识别(RTTI)来确定这个对象的准确类型。在C++中加入异常处理功能时,它的实现要求在虚函数表中加入一些运行时类型信息。RTTI与异常一样,依赖于虚函数表中的类型信息,因此,没有虚函数表的类上用RTTI,会得到不可预知的结果。RTTI的两种使用方法使用RTTI有两种不同的方法。第一种就像sizeof(),它看上就像一个函数,但实际上它是由
2013-04-17 10:14:15 518
原创 《Thinking in C++, 2nd Edition》笔记-第十八章(Exception handling)
C语言中,出错信息通常通过函数的返回值来获得,或者通过设置全局的错误判断标志(标准C语言中的errno()和perror()),对每个函数的返回值进行错误检查会使程序变得繁琐,程序设计者可能简单的忽略这些出错信息。而C++的异常处理,1) 出错处理程序的编写不再繁琐,也不需要将出错处理程序与正常代码紧密结合。在错误有可能出现的地方写一些代码,并在后面的语句中加入出错处理程序。如果程序中多次调用
2013-04-16 16:26:21 562
原创 《Thinking in C++, 2nd Edition》笔记-第十七章(Multiple inheritance)
多重继承MI(multiple inheritance):通过继承多个基类来生成一个新类。只要继承图简单,MI应该也不复杂。但是MI会引入许多二义性和奇怪的现象。子对象重复派生类从基类继承时,派生类中就获得了基类所有数据成员的副本,该副本称为子对象。假若对类d1和类d2进行多重继承而形成类mi,类mi会包含d1的子对象和d2的子对象,所以mi对象看上去如下面左图所示。
2013-04-15 21:09:25 720
原创 《Thinking in C++, 2nd Edition》笔记-第十六章(Introduction to Templates)
模板的引入继承和组合提供了重用对象代码的方法,而模块提供重用源代码的方法。一个容器是可以容纳其它对象的对象。它允许向它存储对象,而后可以取出使用的高速、智能的暂存存储器。容器类是解决不同类型的代码重用问题的另一种方法。#include using namespace std; class IntStack { enum { ssize = 100 }; int stac
2013-04-15 10:44:03 660
原创 《Thinking in C++, 2nd Edition》笔记-第十五章(Polymophism & Virtual Functions)
函数调用绑定如果一个子类指针向上转型为基类指针,然后用这个基类指针调用某个函数,那么调用的将会是基类版本的函数,但是其实它是一个子类类型,理应调用子类版本的函数应该更合理。这是因为编译器在只有一个基类指针的时候并不知道调用正确的函数,它是早绑定。将函数调用连接到函数体叫做绑定。在程序运行之前由编译器执行的绑定叫做早绑定。基于对象的类型,在运行时执行的绑定叫做晚绑定,也叫动态绑定或运行时绑定
2013-04-14 13:40:41 760
原创 《Thinking in C++, 2nd Edition》笔记-第十四章(Inheritance & Composition)
什么是继承和组合组合:一个类中将另一个类的对象作为成员,是has-a关系class X { int i;};class Y{ int i; X x;};继承,is-a关系class X { int i;};class Y : public X { int i;};实际上Y继承自X,意味着Y
2013-04-13 13:50:22 735
原创 《Thinking in C++, 2nd Edition》笔记-第十三章(Dynamic Object Creation)
对象创建C提供了动态内存分配函数malloc()和free(),在运行时从堆中分配存储单元,但是在C++中作用有限:对象不能初始化,而对象的构造函数又不允许向它传递内存函数来初始化它。因此,C++通过new和delete运算符来使我们能够完成动态内存分配及初始化,清理及释放内存。当一个C++对象被创建时:1)为对象分配内存。2)调用构造函数来初始化内存。对于2)未初始化的对象是
2013-04-13 08:39:50 755
原创 《Thinking in C++, 2nd Edition》笔记-第十二章(Operator Overloading)
运算符重载只是一种“语法修饰”,本质上也是函数,只不过它的参数不出现在括号之内,而是出现在运算符附近。因此除非重载运算符使程序变得易写,尤其是更易读,否则就不必去重载运算符。比如说,不能像重载 1重载运算符就像定义一个函数,函数名字为operator@,其中@代表运算符。运算符参数表中的参数取决于:(1)运算符是一元(一个参数)还是二元(两个参数);(2)运算符是全局(对于一元是一个参数,对于
2013-04-12 11:34:05 767
原创 《Thinking in C++, 2nd Edition》笔记-第十一章(References & the Copy-Constructor)
C++中的指针C++是一种更强类型的语言,比如void*,C中不允许一种类型指针赋值给另一种类型指针,但是可以通过void*来实现:bird* b; rock* r; void* v; v = r; b = v;而在C++中这种转换必须用显示的类型转换才行。C++中的引用引用就像是能被编译器自动解引用的指针。1)引用在创建时必须被初始化。(指针可以在任何时候
2013-04-10 22:18:33 676
原创 《Thinking in C++, 2nd Edition》笔记-第十章(Name Control)
static关键字有时控制存储分配,而有时控制一个名字的可见性和连接。它的含义因此经常是相互冲突的:(1)在静态数据区上创建对象,而不是每次函数调用时在堆栈上产生。这也是静态存储的概念。如果想在两次函数调用之间保留一个变量的值,我们可以通过定义一个全局变量来实现这点,但这样一来,这个变量就不仅仅受这个函数的控制,还受其它函数影响。C和C++都允许在函数内部创建一个static对象,这个对象
2013-04-10 14:52:38 612
原创 《Thinking in C++, 2nd Edition》笔记-第九章(Inline Functions)
在C中,宏可以用来提高效率,宏的实现是用预处理器而不是编译器。预处理器直接用宏代码代替调用,所以就没有了参数压栈、生成汇编语言的CALL、返回参数、执行汇编语言的RETURN的时间花费。所有的工作由预处理器完成,因此,不用花费什么就具有了程序调用的便利和可读性。C++中,使用预处理器宏存在两个问题。第一个问题在C中也存在:宏看起来像一个函数用,但并不总是这样。这就隐藏了难以发现的错误。第二个问题是
2013-04-09 21:12:02 530
原创 《Thinking in C++, 2nd Edition》笔记-第八章(Constants)
值替换const的最初动机是消除使用预处理器#define对常量的替换。#define只是对文本进行替换并且没有类型检查,因此会产生一个隐藏的问题,而这些用const可以避免。例如:const int bufsize = 100; 可以在任何需要知道这个值(100)的地方使用bufsize,编译器会进行常量折叠(常量折叠是在编译时间简单化常量表达的一个过程。简单来说就是将常量表达式计
2013-04-08 19:44:14 463
原创 《Thinking in C++, 2nd Edition》笔记-第七章(Function Overloading & Default Arguments)
为什么需要函数重载。大多数编程语言要求我们为每个函数设定一个唯一的标识符。如果我们想打印三种不同类型的数据:整型、字符型和实型,我们通常不得不用三个不同的函数名,如print _ int( )、print _ char( )和print _ float( ) ,这些既增加了我们的编程工作量,也给读者理解程序增加了困难。在C++中,还有一个重要原因需要我们对函数重载:构造函数。因为构造函数的名字
2013-04-08 19:43:26 566
原创 《Thinking in C++, 2nd Edition》笔记-第六章(Initialization & clean up)
在C++中,初始化和清理的概念是简化类库使用的关键,并可以减少那些由于用户忘记这些操作而引起的许多细微错误。用构造函数保证初始化,析构函数保证清除如果一个类有构造函数,编译器在创建对象时就自动调用这一函数。对用户来说,是否调用构造函数并不是可选的,它是由编译器在对象定义时完成的。构造函数的名字?最容易也最合乎逻辑的是:构造函数的名字与类的名字一样。这使得这样的函数在初始化时自动被调用。
2013-04-08 19:38:00 540
原创 《Thinking in C++, 2nd Edition》笔记-第五章(Hiding the Implementation)
C++的存取控制public:在其后声明的所有成员对所有的人都可以存取private:除了该类型的创建者和类的内部成员函数之外,任何人都不能存取这些成员。protected: protected与private基本相似,只有一点不同:继承的结构可以访问protected成员,但不能访问p r ivat e成员。 友元如果程序员想允许不属于当前结构的一个成员函数存取结构中的数
2013-04-08 19:36:57 567
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人