AMD笔试题准备

AMD GPU Driver Software Engineer_2008-11-02.

1.        已知数列3、10、13、23、36、……。请问第208个数除以5余数为多少?(8’)

2.        求过点(2,-3,0)且以n={1,-2,3}为法线向量的平面方程。(10’)

3.        1/(1*2)+1/(2*3)+……+1/(n*(n+1))+……。判断无穷级数收敛性。(10’)

4.        Expand out what the acronymsstand for in ISR,APC, and DPC in a MS windows environments. Give a brief descriptionof what each term means. (8’)

5.        Explain what the OS does whilecreating a process in windows or Linux? (6’)

6.        Programming. Function: convertan integer to a string in n-radix using ANSIC.Void*xtoa( int x, int radix, char *out){} (15’)

7.        Programming: Using C programsthe function ‘memcpy’. Taking performance into consideration.Void *memcpy( void *dst, const void *src, unsigned int size). (10’)

8.        Given two trees, return true ifthey are structurally identical.int sameTree( structnode *a, struct node *b). (10’)

9.        What is the meaning of thekeyword of ‘violatile’ in C++? (8’)

10.    英文题目,写篇信,大概内容:你对一个六个月的实习机会感兴趣,你想申请,但需要一位教授的推荐信。Write him to ask for the reference letter. (15’)

 



1.ISR, APC, DPC

http://hjnudt.spaces.live.com/blog/cns!ca093c112896ea44!110.entry 
 
当驱动程序处理IRP的时候,它可能立刻完成,也可能在中断里才能完成,比如说,往硬件设备发出一个请求(通常可以是写I/O port),当设备完成操作的时候会触发一个中断,然后在中断处理函数里得到操作结果。Windows有两类中断,硬件设备的中断和软中断,分成若干个不同的优先级(IRQL)。软中断主要有两种:DPC(Delayed Procedure Call)和APC(Asynchronous Procedure Call),都处于较低的优先级。驱动程序可以为硬件中断注册ISR(Interrupt Service Routine),一般就是修改IDT某个条目的入口。同样,操作系统也会为DPC和APC注册适当的中断处理例程(也是在IDT中)。值得指出的是,DPC是跟处理器相关的,每个处理器会有一个DPC队列,而APC是跟线程相关的,每个线程会有它的APC队列(实际上包括一个Kernel APC队列和User APC队列,它们的调度策略有所区别),可以想象,APC并不算严格意义上的中断,因为中断可能发生在任何一个线程的上下文中,它被称为中断,主要是因为IRQL的提升(从PASSIVE到APC),APC的调度一般在线程切换等等情形下进行。当中断发生的时候,操作系统会调用中断处理例程,对于硬件设备的ISR,一般处理是关设备中断,发出一个DPC请求,然后返回。不在设备的中断处理中使用太多的CPU时间,主要考虑是否则可能丢失别的中断。由于硬件设备中断的IRQL比DPC中断的高,所以在ISR里面DPC会阻塞,直到ISR返回IRQL回到较低的水平,才会触发DPC中断,在DPC中断里执行从硬件设备读取数据以及重新请求、开中断等操作。ISR或者DPC可能在任何被中断的线程上下文(arbitrary thread context)执行,事实上线程的上下文是不可见的,可以认为是系统借用一下时间片而已。
总的来说,Windows的异步I/O架构中,主要有两种动力,一是发起请求的线程,一部分内核代码会在这个线程上下文执行,二是ISR和DPC,这部分内核代码会在中断里完成,可能使用任何一个线程的上下文。而调度常见使用回调和事件(KEVENT),比如说在往下一层的驱动程序发出请求的时候,可以指定一个完成例程Completion Routine,当下层的驱动完成这个请求的时候会调用这个例程,而往往在这个例程里,就是简单的触发一下一个事件。
另外可以顺便提一下Linux。Linux 2.6也有类似的中断机制,它有更多的软中断优先级,即不同优先级的softirq,而类似于DPC,Linux也提供了专门的软中断,对应DPC的就是tasklet。Linux没有一个像windows这么一致的层次驱动程序架构,所以它的异步I/O稍微粗糙一些,主要是通过以前的一些阻塞点,现在直接返回-EIOCBRETRY,而让调用者在合适的时机继续重试。在这个方法中,可以认为整个操作由一个函数完成,每次操作有进展时,都把这个函数从头执行一遍,当然已经完成的部分就不会再有实际的I/O。这样的最大好处是原有的文件系统和驱动程序不用完全重写。而对于同步调用,只要阻塞就可以了,这样对系统的修改较小。这时候,要提供POSIX aio的语义,就可能需要提供一些用户线程来完成重试的过程了(回想Windows可以通过中断和DPC完成的)。而对于Solaris,也是类似的处理,如果设备支持异步I/O,那就通过中断可以完成,否则就使用内部的LWP来模拟。
ISR是中断服务例程,中断产生时,调用此例程处理。一般在中断服务例程中,要关中断。所以处理时间不能太长,中断服务例程只处理最关键的事情。大部分的事情交给后面的延迟过程调用DPC。所以dpc和isr的内容一般不能调换。如果要强行调换,除去isr中的中断处理部分,其它可以调换。


2.Intel的CPU和AMD的CPU的区别

一:在浮点运算能力来看,INTEL的处理器一般只有两个浮点执行单元,而AMD的处理器一般设计了三个并行的浮点执行单元,所以在同档次的处理器当中,AMD处理器的浮点运算能力比INTEL的处理器的要好一些。浮点运算能力强,对于游戏应用、三维处理应用方面比较有优势。另外,多媒体指令方面,INTEL开发了SSE指令集,到现在已经发展到SSE3了,而AMD也开发了相应的,跟SSE兼容的增强3D NOW!指令集。相比之下,INTEL的处理器比AMD的在多媒体指令方面稍胜一筹,而且有不少软件都针对SSE进行了优化,因此在多媒体软件及平面处理软件中,相比同档次AMD处理器,INTEL的CPU显得更有优势。另外,选择什么样的CPU,价格更是比较关键的因素,在性能上,同档次的INTEL处理器整体来说可能比AMD的处理器要有优势一点,不过在价格方面,AMD的处理器绝对占优。打个比方:INTEL的P4 2.4B的价格大概是1200左右,而性能差不多的AMD的BARTON 2500+售价不过是600左右,想比之下,AMD的CPU的性价比更高。

最终是选择AMD还是INTE的CPU呢?由上面可以了解到,AMD的CPU在三维制作、游戏应用、视频处理等方面相比同档次的INTEL的处理器有优势,而INTEL的CPU则在商业应用、多媒体应用、平面设计方面有优势。除了用途方面,更要综合考虑到性价比这个问题。这样大家根据实际用途、资金预算可以按需选择到最合适自己的CPU。

二:目前INTEL和AMD的CPU的区别之处,以及由于区别之处所带来的性能和效率的差异有以下简要几点,仅供参考:
1。从单晶硅工艺上:INTEL:0。09(降低成本,加大晶体管数量),AMD:0。13(成本比0。09的高),所以导致在都降低相同比例的价格后,INTEL还是挣钱,而AMD最起码不会挣太多的钱啦,搞不好还会陪钱(亏损),虽然市场占有率有所提高,尽而导致最近的AMD诉讼案的发生
2。从流水线上:INTEL:31级(可以提升到更高的主频,但带来更大的发热量:例如P4-670超到7。4G,但得用液氮来散热,而且容易造成指令执行效率低下,所以搞出个超线程来弥补);AMD:20级(指令执行的效率比31级强,但频率提升有限而发热量相对要低,效率和频率是2个不同的发展方向,主要看使用者的选择了)
3。缓存:INTEL:1级16K,2级1M-2M(整数运算以及游戏性能没有AMD的快(还有一个主要原因在起作用,后面再讲),但对于网络和多媒体(浮点运算)的应用比对手强
AMD:1级128K,2级:512K(整数运算快,游戏性能好,但对于多媒体的应用稍微逊色)
4。内存管理架够:INTEL的内存管理架够还是采用传统的由主板上的南北桥方式来管理(造成CPU与内存之间的数据传输延时大,对于游戏执行效果没有AMD的好,但对于日后升级成本有所降低)AMD是CPU内部集成内存控制器(减少了CPU与内存数据传输的延时,(对于游戏性能的提升有相当大的作用,也是前面所说的主要原因,同时也弥补了2级只有512K的所对多媒体应用的不足,但加大了对日后升级的成本的增加:要升级的话您只好把CPU和内存以及主板全都换掉)
5。指令集 INTEL:MMX,SSE,SSE2,SSE3,EM64T
(大多数游戏以及软件基于INTEL的指令,对于INTEL有所优化,但64位指令对于现在新的64位系统有兼容性的缺点,所以最近不得不兼容于AMD的X86-64指令,CPU的步进值也从E0变到G1)AMD:3DNOW+,MMX,SSE,SSE2,SSE3,X86-64(在所支持的SSE3中少了2条指令,但问题不大,因为那2条是专门针对INTEL超线程技术的,没有也罢,反正AMD也不支持超线程技术,由于AMD的64位技术源于DEC公司的Alpha技术(64位技术之一),再加上AMD自己的2次开发,所以导致64位技术快速的在民用市场的出现,微软64位系统也不得不基于AMD的X86-64位开发(谁叫AMD先推出民用的64位呢),为了尽快消除对于64位的WINDOWS兼容性的问题,INTEL也被迫开始兼容AMD的64位指令(不是INTEL没有技术开发64位,是由于它的市场策略导致其非常被动,错过了推出64位的最佳时机,让AMD就64位而言站了上风,谁让这2家公司最终还得看微软的脸色呢,从这点上讲,他们还没完全达到市场垄断的地位---硬件厂商还得看软件巨头的脸色,真悲哀!)

综上所诉:现在谁的性价比更高是要看使用者的应用范围(也必然由应用范围来决定),而并不是简单的由价格来决定的,我更不同意所谓的穷人才用AMD的说法(我哥们现在的个人资产有500多万,算是有点钱的吧?!可他装的电脑用的AMD的3000+,为什么呢,因为他不是电脑发烧友,对电脑的知识也不是太懂,他个人认为够用就好,但也得跟的上点潮流,如果他是个发烧友的话去买INTEL的XEON或者AMD的OpteronCPU也很难说的哦,由于INTEL感觉来自AMD的压力所以公司在发展战略上做出了重大的决策的改变(从一味追求频率到追求性能的转变,也不得不放弃由INTEL公司自己创造出来的摩尔定律这个神话,全面转向CPU性能的提升,CPU在3。8G这个频率上画上了个小小的句号,让10G的目标成为了泡影;具可靠的消息:INTEL以后的CPU架够将是基于现在移动CPU的技术上,并且提出了性耗比的概念(而非性价比)并且近期已经成功研发出样品,就性能而言将是现在P4的3倍--5倍,而功耗从笔记本的CPU的5W到台式机CPU的35W到服务器CPU的65W,核心将是双核心或者是4核心,前端总线为:533MHZ,667MHZ,800MHZ,1066MHZ;不再有超线程技术(因为没有必要了,超线程技术的出现主要是来弥补由于流水线过长而导致的效率低下,新的INTEL的CPU不会再用31级流水线,可能只有不到20级或者更底),频率不会超过现有的频率(这意味着3。8G将是INTEL现在乃至以后最高频率)在即将到来的2007年的大较量(INTEL和AMD)中将一决高下,到时候谁胜谁负,谁好谁坏,谁的性价比或者性毫比更高将一目了然,说实话有点为AMD担心(AMD近期曾表示不会对现有的CPU架够改变)但更为咱们中国人自己的龙芯着急!我还是相信那句话:时间会说明一切的!谁将是消费者最应该期待的产品呢?相信在不远的时间里将会出现!
三:对AMD来说,其最受人欢迎的地方,就是它良好的超频性能和低廉的价格,这是它目前占有处理器市场份额的根本原因,也是它的优势。在我们选择时,如果是DIY高手,那选择AMD是肯定没错,能花较少的钱获得更好的性能,价格上同主频的AMD与Intel,前者价格只是后者的一半左右,而且现在AMD的处理器的主板大多数都有傻瓜超频的软件,虽然不能把超频发挥到极限,但也能过一下超频的瘾。而AMD的发热问题一直是大家最关心的问题,其实不然,现在AMD的处理器多加入了过热保护的芯片,所以发热问题已经基本上得到了解决,不必顾虑。
在购买AMD的产品时要注意,由于它良好的超频性能,使一些奸商们开始出售低频版本超频后再打磨的产品,如何识别是不是打磨过的产品,最简单的办法就是看处理器的L2和L3金桥有没有人为切割或焊接的痕迹。如果仍不放心,那么盒装三年质保的AMD产品也是不错的选择。其次就是风扇的选择,AMD处理器超频后的发热问题(注:超频后发热与不超频时发热不同),一直是DIYer们最关心的,所以选择一个好的风扇也是至关重要的。
Intel则向来以稳定著称,对多媒体有较好的指令支持,比较适合一些多媒体爱好者、办公室装机、以及一些不太懂电脑的家庭装机。从超频上来看,由于所有Intel处理器都是锁倍频的,所以在超频上显不出多大优势来,虽然锁了倍频,但也还是能超,只是超频的范围较小,笔者在不改电压的情况下,将一块P4 2.4 BG的超到了3.0G,且在一些3D游戏中如FIFA 2004时能稳定运行,所以Intel的稳定性还是值得我们信耐的。价格上来说,Intel的处理器比起AMD来说可算是高高在上,虽然IT行业里一分钱一分货,但也不乏有一定的垄断因素在里面,但是它优异稳定的性能,使得不少电脑爱好者在装机时,仍然将其设为首选。也正是因为它的稳定,所以许多品牌电脑大多采用了Intel的处理器,可见Intel的稳定性非同一般。这样,在一个不太懂电脑的家庭装机和商用装机机,Intel的处理器有着不可代替的地位。够买Intel的处理器时,由于都锁了倍频,无论是散装还是盒装都可以放心购买,不会出现像AMD那样的打磨产品。但要特别注意的就是在购买盒装产品时,一些奸商往往用散装处理器配上假冒Intel风扇,重新包装后来当盒装产品销售,鉴别的方法单从外观上很难辨别,主要就是看里面的硬塑料包装是否有拆开过的痕迹,再看说明书是印刷品还是复印的,假冒的一般都是复印品。还有就是可以看盒装产品里面赠送的小徽标(就是品牌机外面都贴着印有的Intel Inside的小贴片),真品的小徽标厚而硬,外面有一层较硬的塑料,假货则比较薄,用手指也能把上面的图案刮下来,有的假货甚至没有小徽标。现在散装的Intel处理器与盒装的价格相差不到几十块,而且盒装产品还赠送一个原装风扇,不必在单独购买风扇,所以购买盒装产品是个不错的选择。

四:INTEL的赛杨系列属于底端,价格便宜,性价比高,一般游戏或者办公都可以满足,奔腾系列则更加适合应用在专业设计领域,当然各方面都比赛杨高出不少,价格方面由于广告费用,所以只能加在消费者头上了

AMD底端是闪龙,高端是速龙,在游戏方面有出色表现,底端对抗赛杨,高端对抗奔腾,在DIY市场很多消费者都是游戏爱好者,所以占有率也是非常可观的


3. windows下创建进程的步骤  
     进程(Process)是具有一定独立功能的程序关于某个数据集合上的一次运行活动,是系统进行资源分配和调度的一个独立单位。程序只是一组指令的有序集合,它本身没有任何运行的含义,只是一个静态实体。而进程则不同,它是程序在某个数据集上的执行,是一个动态实体。它因创建而产生,因调度而运行,因等待资源或事件而被处于等待状态,因完成任务而被撤消,反映了一个程序在一定的数据集上运行的全部动态过程。
  线程(Thread)是进程的一个实体,是CPU调度和分派的基本单位。线程不能够独立执行,必须依存在进程中,由进程提供多个线程执行控制。从内核角度讲线程是活动体对象,而进程只是一组静态的对象集,进程必须至少拥有一个活动线程才能维持运转。


当某个应用程序调用一个创建进程的函数比如CreateProcess或者用户执行某一个程序(其实windows下用户执行一般普通程序是由explorer.exe调用CreateProcess来完成),操作系统把这个过程分成以下步骤来完成:
1.打开将要在该进程中执行的映像文件。
2.创建Windows执行体进程对象。
3.创建初始线程(栈、堆执行环境初始化及执行线程体对象)。
4.通知Windows子系统新进程创建了(子系统是操作系统的一部分它是一个协助操作系统内核管理用户态/客户方的一个子系统具体的进程为Csrss.exe)。
5.开始执行初始线程(如果创建时候指定了线程的CREATE_SUSPENDED状态则线程暂时挂起不执行)。
6.在新进程和线程环境中完成地址空间的初始化(比如加载必须的DLL和库),然后开始到进程入口执行。
到这里操作系统完成一个新进程的创建过程。下面来看下具体每一步操作系统所做的工作:
1.打开将要在该进程中执行的映像文件。
首先操作系统找到执行的Windows映像然后创建一个内存区对象,以便后面将它映射到新的进程地址空间中。


2.创建Windows执行体进程对象。
接下来操作系统调用内部的系统函数NtCreateProcess来创建一个Windwos执行体进程对象。具体步骤是:
(1)建立EPROCESS
*分配并初始化EPROCESS结构块
*从父进程处继承得到进程的亲和性掩码
*分配进程的最大最小工作集尺(由两个参数决定PsMinimumWorkingSet PsMaximumWorkingSet)
*降新进程的配额块设置为父进程配额块地址,并递增父进程配额块的引用计数
*继承Windows的设备名字空间
*将父进程进程ID保存在新进程对象的InheritedFormUniqueProcessId中
*创建该进程的主访问令牌
*初始化进程句柄表
*将新进程的退出状态设置为STATUS_PENDING


(2)创建初始的进程地址空间
*在适当的页表中创建页表项,以映射初始页面
*从MmresidentAvailablePage算出进程工作集大小
*系统空间的非换页部分和系统缓存的页表被映射到进程


(3)初始化内核进程块KPROCESS
(4)结束进程地址空间的创建过程
(5)建立PEB
(6)完成执行体进程对象的创建过程


3.创建初始线程(栈、堆执行环境初始化及执行线程体对象)。
这时候Windows执行体进程对象已经完全建立完成,但它还没有线程所以无法执行,接下来系统调用NtCreateThread来创建一个挂起的新线程它就是进程的主线程体。


4.通知Windows子系统新进程创建了(子系统是操作系统的一部分它是一个协助操作系统内核管理用户态/客户方的一个子系统具体的进程为Csrss.exe)。接下来操作系统通过客户态(Kernel32.dll)给Windows子系统(Csrss)发送一个新进程线程创建的数据消息,让子系统建立自己的进程线程管理块。当Csrss接收到该消息时候执行下面的处理:
*复制一份该进程和线程句柄
*设置进程优先级
*分配Csrss进程块
*把新进程的异常处理端口绑定到Csrss中,这样当该进程发生异常时,Csrss将会接收到异常消息
*分配和初始化Csrss线程块
*把线程插入到进程的线程列表中
*把进程插入到Csrss的线程列表中
*显示进程启动光标


5.开始执行初始线程(如果创建时候指定了线程的CREATE_SUSPENDED状态则线程暂时挂起不执行)。到这里进程环境已经建立完毕进程中开始创建的主线程到这里获得执行权开始执行线程。


6.在新进程和线程环境中完成地址空间的初始化(比如加载必须的DLL和库),然后开始到进程入口执行。
到这步实质是调用ldrInitializeThunk来初始化加载器,堆管理器NLS表TLS数组以及临界区结构,并且加载任何必须要的DLL并且用


DLL_PROCESS_ATTACH功能代码来调用各DLL入口点,最后当加载器初始化例程返回到用户模式APC分发器时进程映像开始在用户模式下执行,然后它调用线程启动函数开始执行。


到这里操作系统完成了所有的创建工作,我们写的程序就这样被操作系统调用运行起来了。


4.http://www.cnblogs.com/yc_sunniwell/archive/2010/07/14/1777432.html

 1. 为什么用volatile?

    C/C++ 中的 volatile 关键字和 const 对应,用来修饰变量,通常用于建立语言级别的 memory barrier。这是 BS 在 "The C++ Programming Language" 对 volatile 修饰词的说明:

A volatile specifier is a hint to a compiler that an object may change its value in ways not specified by the language so that aggressive optimizations must be avoided.

      volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。声明时语法:int volatile vInt; 当要求使用 volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被保存。例如:

1 volatile int i=10;
2 int a = i;
3 ...
4 // 其他代码,并未明确告诉编译器,对 i 进行过操作
5 int b = i;

    volatile 指出 i 是随时可能发生变化的,每次使用它的时候必须从 i的地址中读取,因而编译器生成的汇编代码会重新从i的地址读取数据放在 b 中。而优化做法是,由于编译器发现两次从 i读数据的代码之间的代码没有对 i 进行过操作,它会自动把上次读的数据放在 b 中。而不是重新从 i 里面读。这样以来,如果 i是一个寄存器变量或者表示一个端口数据就容易出错,所以说 volatile 可以保证对特殊地址的稳定访问。注意,在 VC 6 中,一般调试模式没有进行代码优化,所以这个关键字的作用看不出来。下面通过插入汇编代码,测试有无 volatile 关键字,对程序最终代码的影响:

输入下面的代码:

01 #include <stdio.h>
02  
03 void main()
04 {
05     int i = 10;
06     int a = i;
07  
08     printf("i = %d", a);
09  
10     // 下面汇编语句的作用就是改变内存中 i 的值
11     // 但是又不让编译器知道
12     __asm {
13         mov dword ptr [ebp-4], 20h
14     }
15  
16     int b = i;
17     printf("i = %d", b);
18 }

    然后,在 Debug 版本模式运行程序,输出结果如下:

i = 10
i = 32

    然后,在 Release 版本模式运行程序,输出结果如下:

i = 10
i = 10

    输出的结果明显表明,Release 模式下,编译器对代码进行了优化,第二次没有输出正确的 i 值。下面,我们把 i 的声明加上 volatile 关键字,看看有什么变化:

01 #include <stdio.h>
02  
03 void main()
04 {
05     volatile int i = 10;
06     int a = i;
07  
08     printf("i = %d", a);
09     __asm {
10         mov dword ptr [ebp-4], 20h
11     }
12  
13     int b = i;
14     printf("i = %d", b);
15 }

    分别在 Debug 和 Release 版本运行程序,输出都是:

i = 10
i = 32

    这说明这个 volatile 关键字发挥了它的作用。其实不只是“内嵌汇编操纵栈”这种方式属于编译无法识别的变量改变,另外更多的可能是多线程并发访问共享变量时,一个线程改变了变量的值,怎样让改变后的值对其它线程 visible。一般说来,volatile用在如下的几个地方: 
1) 中断服务程序中修改的供其它程序检测的变量需要加volatile; 
2) 多任务环境下各任务间共享的标志应该加volatile; 
3) 存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;

2.volatile 指针

    和 const 修饰词类似,const 有常量指针和指针常量的说法,volatile 也有相应的概念:

  • 修饰由指针指向的对象、数据是 const 或 volatile 的:

    1 const char* cpch;
    2 volatile char* vpch;

    注意:对于 VC,这个特性实现在 VC 8 之后才是安全的。

  • 指针自身的值——一个代表地址的整数变量,是 const 或 volatile 的:

    1 char*const pchc;
    2 char*volatile pchv;

    注意:(1) 可以把一个非volatile int赋给volatile int,但是不能把非volatile对象赋给一个volatile对象

          (2) 除了基本类型外,对用户定义类型也可以用volatile类型进行修饰。
              (3) C++中一个有volatile标识符的类只能访问它接口的子集,一个由类的实现者控制的子集。用户只能用const_cast来获得对类型接口的完全访问。此外,volatile向const一样会从类传递到它的成员。

3. 多线程下的volatile   

    有些变量是用volatile关键字声明的。当两个线程都要用到某一个变量且该变量的值会被改变时,应该用volatile声明,该关键字的作用是防止优化编译器把变量从内存装入CPU寄存器中。如果变量被装入寄存器,那么两个线程有可能一个使用内存中的变量,一个使用寄存器中的变量,这会造成程序的错误执行。volatile的意思是让编译器每次操作该变量时一定要从内存中真正取出,而不是使用已经存在寄存器中的值,如下: 

  volatile  BOOL  bStop   FALSE;  
   (1) 在一个线程中:  
  while(  !bStop  )   ...   
  bStop   FALSE;  
  return;    
   (2) 在另外一个线程中,要终止上面的线程循环:  
  bStop   TRUE;  
  while(  bStop  );  //等待上面的线程终止,如果bStop不使用volatile申明,那么这个循环将是一个死循环,因为bStop已经读取到了寄存器中,寄存器中bStop的值永远不会变成FALSE,加上volatile,程序在执行时,每次均从内存中读出bStop的值,就不会死循环了。
    这个关键字是用来设定某个对象的存储位置在内存中,而不是寄存器中。因为一般的对象编译器可能会将其的拷贝放在寄存器中用以加快指令的执行速度,例如下段代码中:  
  ...  
  int  nMyCounter   0;  
  for(;  nMyCounter<100;nMyCounter++)  
  {  
  ...  
  }  
  ...  
   在此段代码中,nMyCounter的拷贝可能存放到某个寄存器中(循环中,对nMyCounter的测试及操作总是对此寄存器中的值进行),但是另外又有段代码执行了这样的操作:nMyCounter  -=  1;这个操作中,对nMyCounter的改变是对内存中的nMyCounter进行操作,于是出现了这样一个现象:nMyCounter的改变不同步。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值