0. Software basics
0.1 bytes alayment 要点
1. cpu 读的时候图方便。
1. C++ basics
1.1 Fuction and parameter.
函数中不得修改指针参数的地址,否则请使用指针的指针!
1.2 虚函数通常将最顶端的基类的析构函数申明为虚,通过基类的指针删除子类的对象时,没有基类的虚析构函数的话,就不知道怎么删了。
构造函数是绝对不能为虚构函数~`因为构造函数是由系统在对象分配空间之前都调用的,而虚构函数需要是创建了对象之后才能够调用
静态函数不能是虚函数,因为只初始化一次,没有多态的概念!
1.3 malloc/free & new/delete?
(1)操作对象有所不同。
malloc与free是C++/C 语言的标准库函数,new/delete 是C++的运算符。对于非内部数据类的对象而言,光用maloc/free 无法满足动态对象的要求。对象在创建的同时要自动执行构造函数, 对象消亡之前要自动执行析构函数。由于malloc/free 是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加malloc/free。
2. OS
2.1 进程/线程
2.1
页和分段系统有许多相似之处,但在概念上两者完全不同,
1、页是信息的物理单位,分页是为实现离散分配方式,
段是信息的逻辑单位,它含有一组其意义相对完整的信息。
2、页的大小固定且由系统确定,
段的长度却不固定,决定于用户所编写的程序,
3、分页的作业地址空间是唯一的,即单一的线性空间,
分段的作业地址空间是二维的,程序员在标识一个地址时,
程序通过分段(segmentation)划分为多个模块,如代码段、数据段、共享段。其优点是: 可以分别编写和编译。 可以针对不同类型的段采取不同的保护。 可以按段为单位来进行共享,包括通过动态链接进行代码共享。
3. Linux
3.1 IPC
In computing, Inter-process communication (IPC) is a set of methods for the exchange of data among multiple threads in one or more processes. Processes may be running on one or more computers connected by a network. IPC methods are divided into methods for message passing, synchronization, shared memory, and remote procedure calls (RPC). The method of IPC used may vary based on the bandwidth and latency of communication between the threads, and the type of data being communicated.
There are several reasons for providing an environment that allows process cooperation:
- Information sharing
- Speedup
- Modularity
- Convenience
- Privilege separation
IPC may also be referred to as inter-thread communication and inter-application communication.
The combination of IPC with the address space concept is the foundation for address space independence/isolation.
Main IPC methods
Method | Provided by (operating systems or other environments) |
---|---|
File | Most operating systems |
Signal | Most operating systems; some systems, such as Windows, implement signals in only the C run-time library and provide no support for their use as an IPC method |
Socket | Most operating systems |
Message queue | Most operating systems |
Pipe | All POSIX systems, Windows |
Named pipe | All POSIX systems, Windows |
Semaphore | All POSIX systems, Windows |
Shared memory | All POSIX systems, Windows |
Message passing (shared nothing) | Used in MPI paradigm, Java RMI, CORBA, MSMQ, MailSlots, others |
Memory-mapped file | All POSIX systems, Windows; this method may carry race condition risk if a temporary file is used |
[edit]Implementations
There are several APIs which may be used for IPC. A number of platform independent APIs include the following:
- Anonymous pipes and named pipes
- Common Object Request Broker Architecture (CORBA)
- Freedesktop.org's D-Bus
- Distributed Computing Environment (DCE)
- Message Bus (Mbus) (specified in RFC 3259)
- MCAPI Multicore Communications API
- Lightweight Communications and Marshalling (LCM)
- ONC RPC
- Unix domain sockets
- XML XML-RPC or SOAP
- JSON JSON-RPC
- Thrift
- TIPC
- ZeroC's Internet Communications Engine (ICE)
The following are platform or programming language specific APIs:
- Apple Computer's Apple events (previously known as Interapplication Communications (IAC)).
- Enea's LINX for Linux (open source) and various DSP and general purpose processors under OSE
- IPC implementation from CMU.
- Java's Remote Method Invocation (RMI)
- KDE's Desktop Communications Protocol (DCOP)
- Libt2n for C++ under Linux only, handles complex objects and exceptions
- The Mach kernel's Mach Ports
- Microsoft's ActiveX, Component Object Model (COM), Microsoft Transaction Server (COM+), Distributed Component Object Model (DCOM), Dynamic Data Exchange (DDE), Object Linking and Embedding (OLE), anonymous pipes, named pipes, Local Procedure Call, Message loop, MSRPC, .NET Remoting, and Windows Communication Foundation (WCF)
- Novell's SPX
- PHP's sessions
- POSIX mmap, message queues, semaphores, and Shared memory
- RISC OS's messages
- Solaris Doors
- System V's message queues, semaphores, and shared memory
- Distributed Ruby
- DIPC Distributed Inter-Process Communication
- OpenBinder Open binder
- IPC Shared Memory Messaging from Solace Systems
Usually, read and write requests are blocking operations, which means that the execution of the source process, upon writing, is suspended until all data could be written to the destination process, and, likewise, the execution of the destination process, upon reading, is suspended until at least some of the requested data could be obtained from the source process. Obviously, this cannot lead to a deadlock, where both processes would wait indefinitely for each other to respond, since at least one of the two processes will soon thereafter have its request serviced by the operating system, and continue to run.
For performance, most operating systems implementing pipes use pipe buffers, which allow the source process to provide more data than the destination process is currently able or willing to receive. Under most Unices and Unix-like operating systems, a special command is also available which implements a pipe buffer of potentially much larger and configurable size, typically called "buffer". This command can be useful if the destination process is significantly slower than the source process, but it is anyway desired that the source process can complete its task as soon as possible. E.g., if the source process consists of a command which reads an audio track from a CD and the destination process consists of a command which compresses the waveform audio data to a format like MP3. In this case, buffering the entire track in a pipe buffer would allow the CD drive to spin down more quickly, and enable the user to remove the CD from the drive before the encoding process has finished.
命名管道
命名管道具有以下几个特征:
(1)命名管道是双向的,所以两个进程可以通过同一管道进行交互。
(2)命名管道不但可以面向字节流,还可以面向消息,所以读取进程可以读取写进程发送的不同长度的消息。
(3)多个独立的管道实例可以用一个名称来命名。例如几个客户端可以使用名称相同的管道与同一个服务器进行并发通信。
(4)命名管道可以用于网络间两个进程的通信,而其实现的过程与本地进程通信完全一致。
各种通信方法的优缺点
几种通信方法总结综上所述.进程之间的多种通信方法各自有各自的优点和缺点:如果用户传递的信息较少.或是需要通过信号来触发某些行为.前文提到的软中断信号机制不失为一种简捷有效的进程间通信方式.但若是进程间要求传递的信息量比较大或者进程间存在交换数据的要求,那就需要考虑别的通信方式了。
无名管道简单方便.但局限于单向通信的工作方式.并且只能在创建它的进程及其子孙进程之间实现管道的共享:
有名管道虽然可以提供给任意关系的进程使用.但是由于其长期存在于系统之中,使用不当容易出错.所以普通用户一般不建议使用。
消息缓冲可以不再局限于父子进程.而允许任意进程通过共享消息队列来实现进程间通信.并由系统调用函数来实现消息发送和接收之间的同步.从而使得用户在使用消息缓冲进行通信时不再需要考虑同步问题.使用方便,但是信息的复制需要额外消耗CPU的时间.不适宜于信息量大或操作频繁的场合。
共享内存针对消息缓冲的缺点改而利用内存缓冲区直接交换信息,无须复制,快捷、信息量大是其优点。但是共享内存的通信方式是通过将共享的内存缓冲区直接附加到进程的虚拟地址空间中来实现的.因此,这些进程之间的读写操作的同步问题操作系统无法实现。必须由各进程利用其他同步工具解决。另外,由于内存实体存在于计算机系统中.所以只能由处于同一个计算机系统中的诸进程共享。不方便网络通信。
不同的进程通信方式有不同的优点和缺点.因此.对于不同的应用问题,要根据问题本身的情况来选择进程间的通信方式。
4. Windows
4.1 Windows消息机制要点
1. 窗口过程
每个窗口会有一个称为窗口过程的回调函数(WndProc),它带有四个参数,分别为:窗口句柄(Window Handle),消息ID(Message ID),和两个消息参数(wParam, lParam), 当窗口收到消息时系统就会调用此窗口过程来处理消息。(所以叫回调函数)
2 消息类型
1) 系统定义消息(System-Defined Messages)
在SDK中事先定义好的消息,非用户定义的,其范围在[0x0000, 0x03ff]之间, 可以分为以下三类:
1>窗口消息(Windows Message)
与窗口的内部运作有关,如创建窗口,绘制窗口,销毁窗口等。可以是一般的窗口,也可以是Dialog,控件等。
如:WM_CREATE, WM_PAINT, WM_MOUSEMOVE, WM_CTLCOLOR, WM_HSCROLL...
2>命令消息(Command Message)
与处理用户请求有关, 如单击菜单项或工具栏或控件时, 就会产生命令消息。
WM_COMMAND, LOWORD(wParam)表示菜单项,工具栏按钮或控件的ID。如果是控件, HIWORD(wParam)表示控件消息类型
3> 控件通知(Notify Message)
控件通知消息, 这是最灵活的消息格式, 其Message, wParam, lParam分别为:WM_NOTIFY, 控件ID,指向NMHDR的指针。NMHDR包含控件通知的内容, 可以任意扩展。
2) 程序定义消息(Application-Defined Messages)
用户自定义的消息, 对于其范围有如下规定:
WM_USER: 0x0400-0x7FFF (ex. WM_USER+10)
WM_APP(winver>4.0): 0x8000-0xBFFF (ex.WM_APP+4)
RegisterWindowMessage: 0xC000-0xFFFF
3 消息队列(Message Queues)
Windows中有两种类型的消息队列
1) 系统消息队列(System Message Queue)
这是一个系统唯一的Queue,设备驱动(mouse, keyboard)会把操作输入转化成消息存在系统队列中,然后系统会把此消息放到目标窗口所在的线程的消息队列(thread-specific message queue)中等待处理
2) 线程消息队列(Thread-specific Message Queue)
每一个GUI线程都会维护这样一个线程消息队列。(这个队列只有在线程调用GDI函数时才会创建,默认不创建)。然后线程消息队列中的消息会被送到相应的窗口过程(WndProc)处理.
注意: 线程消息队列中WM_PAINT,WM_TIMER只有在Queue中没有其他消息的时候才会被处理,WM_PAINT消息还会被合并以提高效率。其他所有消息以先进先出(FIFO)的方式被处理。
4 队列消息(Queued Messages)和非队列消息(Non-Queued Messages)
1)队列消息(Queued Messages)
消息会先保存在消息队列中,消息循环会从此队列中取消息并分发到各窗口处理
如鼠标,键盘消息。
2) 非队列消息(NonQueued Messages)
消息会绕过系统消息队列和线程消息队列直接发送到窗口过程被处理
如: WM_ACTIVATE, WM_SETFOCUS, WM_SETCURSOR, WM_WINDOWPOSCHANGED
注意: postMessage发送的消息是队列消息,它会把消息Post到消息队列中; SendMessage发送的消息是非队列消息, 被直接送到窗口过程处理
5 PostMessage(PostThreadMessage), SendMessage
PostMessage:把消息放到指定窗口所在的线程消息队列中后立即返回。 PostThreadMessage:把消息放到指定线程的消息队列中后立即返回。
SendMessage:直接把消息送到窗口过程处理, 处理完了才返回。
6 GetMessage, PeekMessage
PeekMessage会立即返回 可以保留消息
GetMessage在有消息时返回 会删除消息
7 TranslateMessage, TranslateAccelerator
TranslateMessage: 把一个virtual-key消息转化成字符消息(character message),并放到当前线程的消息队列中,消息循环下一次取出处理。
TranslateAccelerator: 将快捷键对应到相应的菜单命令。它会把WM_KEYDOWN 或 WM_SYSKEYDOWN转化成快捷键表中相应的WM_COMMAND 或WM_SYSCOMMAND消息, 然后把转化后的 WM_COMMAND或WM_SYSCOMMAND直接发送到窗口过程处理, 处理完后才会返回。
8(消息死锁( Message Deadlocks)
假设有线程A和B, 现在有以下下步骤
1) 线程A SendMessage给线程B, A等待消息在线程B中处理后返回
2) 线程B收到了线程A发来的消息,并进行处理, 在处理过程中,B也向线程A SendMessgae,然后等待从A返回。
因为此时, 线程A正等待从线程B返回, 无法处理B发来的消息, 从而导致了线程A,B相互等待, 形成死锁。多个线程也可以形成环形死锁。
可以使用 SendNotifyMessage或SendMessageTimeout来避免出现死锁。
9 BroadcastSystemMessage
我们一般所接触到的消息都是发送给窗口的, 其实, 消息的接收者可以是多种多样的,它可以是应用程序(applications), 可安装驱动(installable drivers), 网络设备(network drivers), 系统级设备驱动(system-level device drivers)等,
BroadcastSystemMessage这个API可以对以上系统组件发送消息。
SendMessage()与PostMessage()之间的区别是什么?
它们两者是用于向应用程序发送消息的。PostMessagex()将消息直接加入到应用程序的消息队列中,不等程序返回就退出;而SendMessage()则刚好相反,应用程序处理完此消息后,它才返回。我想下图能够比较好的体现这两个函数的关系:
1、DOS与Windows驱动机制的区别
1)DOS是过程驱动的。
传统的MS-DOS程序主要采用顺序的。关联的、过程驱动的程序设计方法。一个过程是一系列预先定义好的操作序列的组合,它具有一定的开头、中间过程和结束。程序直接控制程序事件和过程的顺序。这样的程序设计方法是面向程序而不是面向用户的,交互性差,用户界面不够友好,因为它强迫用户按照某种不可更改的模式进行工作。它的基本模型如图1.1所示。
2)Windows是事件(消息)驱动
事件驱动程序设计是一种全新的程序设计方法,它不是由事件的顺序来控制,而是由事件的发生来控制,而这种事件的发生是随机的、不确定的,并没有预定的顺序,这样就允许程序的的用户用各种合理的顺序来安排程序的流程。对于需要用户交互的应用程序来说,事件驱动的程序设计有着过程驱动方法无法替代的优点。它是一种面向用户的程序设计方法,它在程序设计过程中除了完成所需功能之外,更多的考虑了用户可能的各种输入,并针对性的设计相应的处理程序。它是一种“被动”式程序设计方法,程序开始运行时,处于等待用户输入事件状态,然后取得事件并作出相应反应,处理完毕又返回并处于等待事件状态。它的框图如图1.2所示
《windows核心编程》之精华
学习《 windows 核心编程》
--如果发现有什么理解的不正确的,欢迎指出,共同学习,共同进步哦!
u 字符集,一切软件的基础,单字集(用 1 个字节表示一个字符),双字节字符集( DBCS, 并不是用 2 个字节表示一个字符哦,而是用 1 个, 2 个,或多个字节的混合来表示字符),宽字节字符集( unicode 用 2 个字节来表示一个字符)。对windows 操作系统来说, windows 98 内核用 ANSI , windows ME 用 unicode , windows 2000 以后的版本也用unicode ,对于我们在 windows 上开发, windows2000 以后的版本,我们即可以开发 ANSI 版本,也可以开发 unicode 版本,他们都能够很好的运行,但是重效率和软件的国际化来看的化,最后使用 unicode 进行编码。
u 内核对象,被系统和应用程序用来管理各种资源,我们可以使用 API 来管理和使用内核对象,但是不能直接修改内核对象的数据结构,内核对象由内核所拥有,内核知道某个内核对象有没有被使用等,内核对象被广泛的使用在进程,线程。。。中用来管理。(内核即操作系统的本质,核心所在,进行系统的管理)
u 进程,包含用来管理进程的内核对象和用来加载 exe 和数据等的地址空间。当一个 exe 开始运行时,它即对应一个进程, exe的 main ()也即是进程入口函数,但是在进入 main ()之前还有 c , c ++运行库的初始化。当创建一个进程时,就产生了一个唯一的实例句柄,它就是 winmain ()函数中要传入的实例句柄,另外在主进程(可没有非主进程的啊,但也可以认为主进程的子进程是非主进程,因为系统不保存父子进程的关系,他们可以看作是相互独立的)中可以创建它的子进程,用来对多个需要共同管理的线程进行管理。
u 作业,作业是进程的容器,可以统一地对一组进程增加一些额外的限制。有时候建立单个进程的作业也是有意义的,因为可以对单一进程施加一些进程本身所没有的属性。
u 线程,线程在进程中被创建,在创建进程时,默认的主线程即被创建。操作系统是用线程来完成任务的,因为进程不直接获得操作系统的时间,线程可以认为是操作系统的最小的处理单位。在多线程编程中,首先要注意的就是线程的同步问题,还有线程池的使用。且最好不要使用全局或静态变量。
u 纤程,比线程更小的单位,纤程是用户对线程进行分割,然后自定义算法实行对纤程的调用,系统的内核并不知道线程。
u Windows 内存结构,每个进程都有它自己的虚拟内存, 32 位机,虚拟内存位 4G ,但是这 4G 并不都可以被用户使用,它包含 NULL 指针, dos 兼容区,文件映射区,系统核心区,能被用户使用的只有 2G 。当然现在 64 位的机子可不是 2G 哦。
u 虚拟内存, windows 进行内存管理的方法之一,最适合用来管理大型对象和结构数组,也即相当于 RAM (即物理内存)的二级缓存,系统先到 RAM 找,如找不到就到虚拟内存(页文件)找,找到了就加载到 RAM 中,然后执行。
u 内存映射文件, windows 的第二中内存管理方法,最适合用来管理大型数据流和单机上的数据共享。 与虚拟内存一样,内存映射文件可以用来保留一个地址空间的区域,并将物理存储器提交给该区域。它们之间的差别是,物理存储器来自一个已经位于磁盘上的文件,而不是系统的页文件。一旦该文件被映射,就可以访问它,就像整个文件已经加载内存一样。系统还使用内存映射文件,以便加载和执行 . e x e 和 D L L 文件。
u 堆栈, windows 的第三中内存管理方法,最适合管理大量的小对象,例如链表等,线程,进程都有自己的堆栈,默认的大小位1M ,也可以修改。
algorithemn
bubble:
void BubbleSort(elemtype x[],int n)
{
int i,j;
elemtype temp;
for(i=1;i<n;i++)
for(j=0;j<n-i;j++)
{
if(x[j].key>x[j+1].key)
{
temp=x[j];
x[j]=x[j+1];
x[j+1]=temp;
}
}
}
1. C++ basics
message mechanism
1. C++ basics
message mechanism