按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
#0016 fFibo。Open (〃FIBO。DAT〃; CFile::modeWrite |
#0017 CFile::modeCreate | CFile::typeText);
#0018
#0019 str。Format (〃%sn〃; 〃Fibonacci sequencee; less than 100 :〃);
#0020 printf(〃%s〃; (LPCTSTR) str);
#0021 fFibo。WriteString (str);
#0022
#0023 lo = hi = 1;
#0024
#0025 str。Format (〃%dn〃; lo);
#0026 printf(〃%s〃; (LPCTSTR) str);
#0027 fFibo。WriteString (str);
#0028
#0029 while (hi 《 100)
#0030 {
#0031 str。Format (〃%dn〃; hi);
#0032 printf(〃%s〃; (LPCTSTR) str);
#0033 fFibo。WriteString (str);
#0034 hi = lo + hi;
#0035 lo = hi lo;
#0036 }
#0037
#0038 fFibo。Close ();
#0039 return 0;
#0040 }
以下是执行结果(在 console 窗口和 FIBO。DAT 档案中,结果都一样):
36
…………………………………………………………Page 99……………………………………………………………
Fibonacci sequencee; less than 100 :
1 1 2 3 5 8
13
21
34
55
89
这么简单的例子中,我们看到MFC Console 程序的几个重点:
1。 程序进入点仍为main
2。 需包含所使用之类别的头文件(本例为AFX。H )
3。 可直接使用与GUI 无关的MFC 类别(本例为CStdioFile 和CString )
4。 编辑时需指定/MT,表示使用多执行线程版本的C runtime 函数库。
第4点需要多做说明。在MFC console 程序中一定要指定多线程版的C runtime 函数库,
所以必须使用/MT 选项。如果不做这项设定,会出现这样的联结错误:
Microsoft (R) 32…Bit Incremental Linker Version 5。00。7022
Copyright (C) Microsoft Corp 1992…1997。 All rights reserved。
/out:mfccon。exe
mfccon。obj
nafxcw。lib (thrdcore。obj) : error LNK2001: unresolved external symbol __endthreadex
nafxcw。lib (thrdcore。obj) : error LNK2001: unresolved external symbol __beginthreadex
mfccon。exe : fatal error LNK1120: 2 unresolved externals
表示它找不到__beginthreadex 和__endthreadex 。怪了,我们的程序有调用它们吗?没
有,但是MFC 有!这两个函数将在稍后与执行线程有关的小节中讨论。
MFCCON 的源代码与可执行文件放在书附盘片的mfccon。01 子目录中。
37
…………………………………………………………Page 100……………………………………………………………
什么是C Runtime 函数库的多线程版本
当C runtime 函数库于1970s 年代产生出来时,PC 的内存容量还很小,多任务是
个新奇观念,更别提什么多执行线程了。因此以当时产品为基础所演化的C runtime 函
数库在多线程(multithreaded)的表现上有严重问题,无法被多线程程序使用。
利用各种同步机制( )如 、 、 、
synchronous mechanism critical section mutex semaphore
,可以重新开发一套支持多执行线程的 函数库。问题是,加上这样的能
event runtime
力,可能导至程序代码大小和执行效率都遭受不良波及 即使你只激活了一个执行
…
线程。
Visual C++ 的折衷方案是提供两种版本的C runtime 函数库。一种版本给单线程程序
使用,一种版本给多线程程序使用。多线程版本的重大改变是,第一,变量如errno 者
现在变成每个执行线程各拥有一个。第二,多线程版中的数据结构以同步机制加以保护。
Visual C++ 一共有六个C runtime 函数库产品供你选择:
◆ ( )
Single…Threaded static libc。lib 898;826
( )
Multithreaded static libcmt。lib 951;142
◆
Multithreaded DLL msvcrt。lib 5;510;000
◆
( )
Debug Single…Threaded static libcd。lib 2;374;542
◆
( )
Debug Multithreaded static libcmtd。lib 2;949;190
◆
◆ Debug Multithreaded DLL msvcrtd。lib 803;418
Visual C++ 编译器提供下列选项,让我们决定使用哪一个C runtime 函数库:
◆ ( )
/ML Single…Threaded static
◆ ( )
/MT Multithreaded static
( )
/MD Multithreaded DLL dynamic import library
◆
( )
/MLd Debug Single…Threaded static
◆
( )
/MTd Debug Multithreaded static
◆
◆ ( )
/MDd Debug Multithreaded DLL dynamic import library
38
…………………………………………………………Page 101……………………………………………………………
进程与执行线程 ( )
Process and Thread
OS/2 Windows NT Windows 95 PC
、 以及 都支持多执行线程,这带给 程序员一股令人兴
奋的气氛。然而它带来的不全然是利多,如果不谨慎小心地处理执行线程的同步问题,程
序的错误以及除错所花的时间可能使你发誓再也不碰「执行线程」这种东西。
我们习惯以进程(process )表示一个执行中的程序,并且以为它是CPU 排程单位。事
实上执行线程才是排程单位。
核心对象
首先让我解释什么叫作「核心对象」(kernel object )。「GDI 对象」是大家比较熟悉的
GDI Pen Brush GDI
东西,我们利用 函数所产生的一支笔( )或一支刷( )都是所谓的「
对象」。但什么又是「核心对象」呢?
你可以说核心对象是系统的一种资源(噢,这说法对GDI 对象也适用),系统对象一
旦产生,任何应用程序都可以开启并使用该对象。系统给予核心对象一个计数值(usage
count )做为管理之用。核心对象包括下列数种:
核心对象 产生方法
event CreateEvent
mutex CreateMutex
semaphore CreateSemaphore
file CreateFile
file…mapping CreateFileMapping
process CreateProcess
thread CreateThread
前三者用于执行线程的同步化:file…mapping 对象用于内存映射文件(memory mapping
file process thread
), 和 对象则是本节的主角。这些核心对象的产生方式(也就是我们
39
…………………………………………………………Page 102……………………………………………………………
API handle
所使用的 )不同,但都会获得一个 做为识别;每被使用一次,其对应的计
1 CloseHandle
数值就加 。核心对象的结束方式相当一致,调用 即可。
process
「 对象」究竟做什么用呢?它并不如你想象中用来「执进程序代码」;不,程序代码
的执行是执行线程的工作,「process 对象」只是一个数据结构,系统用它来管理进程。
一个进程的诞生与死亡
执行一个程序,必然就产生一个进程(process )。最直接的程序执行方式就是在shell (如
Win95 的文件总管或Windows 3。x 的文件管理员)中以鼠标双击某一个可执行文件图标
App。exe App shell CreateProcess
(假设其为 ),执行起来的 进程其实是 调用 激活的。
让我们看看整个流程:
1。 shell 调用CreateProcess 激活App。exe 。
1
2。 系统产生一个「进程核心对