乐虎国际点击下图进入官网:
乐虎国际点击下图进入活动:
乐虎国际点击下图进入领取彩金:
百家博官网|http://bjbgwylql.weebly.com
金沙会娱乐平台|http://jshylptgntl.weebly.com
白菜注册送18体验金|http://bczcstyjnqeg.weebly.com
ca亚洲国际娱乐城|http://cayzgjylcaqus.weebly.com
斗牛技巧|http://dnjqcwgm.weebly.com
金沙会娱乐|http://jshylshwk.weebly.com
recated这个javadoc tag,并使用它们产生警告信息。但是这种状况将在后续版本中改变,我们应在现在就开始使用@Deprecated来修饰过时的方法而不是 @deprecated javadoc tag。下面一段程序中使用了@Deprecated注解标示方法过期,同时在方法注释中用@deprecated tag 标示该方法已经过时,代码如下:
AppleService类的showTaste() 方法被@Deprecated标注为过时方法,在FruitRun类中使用的时候,编译器会给出该方法已过期,不推荐使用的提示。
SuppressWarnnings,抑制编译器警告:
@SuppressWarnings 被用于有选择的关闭编译器对类、方法、成员变量、变量初始化的警告。在java5.0,sun提供的javac编译器为我们提供了-Xlint选项来使编译器对合法的程序代码提出警告,此种警告从某种程度上代表了程序错误。例如当我们使用一个generic collection类而又没有提供它的类型时,编译器将提示出"unchecked warning"的警告。通常当这种情况发生时,我们就需要查找引起警告的代码。如果它真的表示错误,我们就需要纠正它。例如如果警告信息表明我们代码中的switch语句没有覆盖所有可能的case,那么我们就应增加一个默认的case来避免这种警告。
有时我们无法避免这种警告,例如,我们使用必须和非generic的旧代码交互的generic collection类时,我们不能避免这个unchecked warning。此时@SuppressWarning就要派上用场了,在调用的方法前增加@SuppressWarnings修饰,告诉编译器停止对此方法的警告。
SuppressWarning不是一个标记注解。它有一个类型为String[]的成员,这个成员的值为被禁止的警告名。对于javac编译器来讲,被-Xlint选项有效的警告 名也同样对@SuppressWarings有效,同时编译器忽略掉无法识别的警告名。
annotation语法允许在annotation名后跟括号,括号中是使用逗号分割的name=value对用于为annotation的成员赋值。实例如下:
在这个例子中SuppressWarnings annotation类型只定义了一个单一的成员,所以只有一个简单的value={...}作为name=value对。又由于成员值是一个数组,故使用大括号来声明数组值。注意:我们可以在下面的情况中缩写annotation:当annotation只有单一成员,并成员命名为"value="。这时可以省去"value="。比如将上面方法getFruit()的SuppressWarnings annotation就是缩写的 果博娱乐 。
SuppressWarnings注解的常见参数值的简单说明:
1.deprecation:使用了不赞成使用的类或方法时的警告;
2.unchecked:执行了未检查的转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型;
3.fallthrough:当 Switch 程序块直接通往下一种情况而没有 Break 时的警告;
4.path:在类路径、源文件路径等中有不存在的路径时的警告;
5.serial:当在可序列化的类上缺少 serialVersionUID 定义时的警告;
6.finally:任何 finally 子句不能正常完成时的警告;
7.all:关于以上所有情况的警告。
Linux 2.6内核笔记【Process-2:切换】在看Linux内核的时候发现,CPU自己认得(或者说is expecting)很多struct,很多时候内核要做的事情是在内存里准备好这些struct里CPU需要的数据,以供CPU完成相应的任务。比如寻址中的paging部分,内核只需要把page directory中的数据准备好,并把page directory的地址放入cr3,CPU自己就能根据page directory中的数据进行寻址。就像一种契约,CPU对struct的期望,正是内核所要做的事情,反过来说,内核要做的事情仅仅是满足CPU的期望而已。不知读者是否与我有同感,但对于我而言,这使得写操作系统突然变得远远不如想象中那么困难了。因为困难的地方在底层,在硬件。这正是学编程的世界,没学之前,你永远觉得编程是不可能的事情——如果刚刚学会了C的语法,你会觉得,C里头把数据在内存里移来移去,加加减减,明明是只能让小孩子玩过家家的东西,怎么就可以在屏幕上画画?让机器做事?后来意识到了好多好多的库,原来自己只需要调用API就好了,那 API的那一边又是怎么实现的呢?终于知道API里面是怎么实现的了,却发现这些实现永远也只是在调用另外一层API,只不过更为底层的API。往地里越钻越深,穿越一层又一层的API,才发现最终不过是在为硬件的期望准备内存中的数据。当然这样的描述忽略了同时在底层我们也发出了汇编指令让机器去做一些除了操作内存加加减减的事情,但硬件才是生命自身,它的电路决定了它如何理会指令、中断和各种事件,如何突然不执行我们(比如,当前用户进程)给它的下一个指令,突然知道利用内存中的数据去进行上下文转换,如此等等。其实上面这番话也可以反过来说。每当我们的知识前进一步,学的更深了,回头望去,我们承学的东西,不过是一层API,一层界面罢了。一点感想,下面进入正题,这次的笔记是讲述Process的切换:【TSS】先介绍一下对80x86的hardware context switch很重要的TSS结构。Task State SegmentA task gate descriptor provides an indirect, protected reference to a Task State Segment.The Task State Segment is a special x86 structure which holds information about a task. It is used by the operating system kernel for task management. Specifically, the following information is stored in the TSS: * Processor register state * I/O Port permissions * Inner level stack pointers * Previous TSS linkAll this information should be stored at specific locations within the TSS as specified in the IA-32 manuals.在Linux低版本中,进程切换仅仅需要far jmp到要切换的进程的TSS的selector所在就可以了。(far jmp除了修改eip还修改cs)。在Linux 2.6当中,TSS保存在每CPU一个的GDT(其地址存在gdtr中)中,虽然每个process的TSS不同,但Linux 2.6却不利用其中的 hardware context switch以一个far jmp来实现任务转换,而用一系列的mov指令来实现。这样做的原因是:1、可以检验ds和es的值,以防恶意的forge。2、硬转换和软转换所用时间相近,而且硬转换是无法再优化的,软转换则可以。Linux 2.6对TSS的使用仅限于:1、User Mode向Kernel Mode切换的时候,从TSS中获取Kernel Stack。2、User Mode使用in或者out指令的时候,用TSS中的 I/O port permission bitmap验证权限.有一点要注意,process switching是发生在Kernel Mode,在转为Kernel Mode的时候,用户进程使用的通用register已经保存在Kernel Stack上了。然而非通用的register,如esp,由于不能放在TSS中,所以是放在task_t中的一个类型为thread_struct的 thread字段中。process切换两部分:切换paging这里不讲,切换kernel stack、hardware context是由switch_to宏完成的。【switch_to宏中的last】switch_to宏的任务就是让一个process停下来,然后让另外一个process运行起来。switch_to(prev, next, last)。prev、next分别是切换前后的process的process descriptor(task_t)的地址。last的存在要解释一下:由于switch_to中造成了进程的切换,所以其中前半部分指令在prev的语境(context、Kernel Stack)中执行,后半部分却在next的语境中执行。假设B曾切换为O, 华硕娱乐 那么由于一切换,B就停下来了,所以在B的感觉保持是next为O,prev为B。当我们要从A切换到B的时候,一切换B就醒了,但它却仍然以为next是O,prev是B,就不认识A了。然而A switch_to B中的后半部分却需要B知道A。因此这个宏通常都是这么用的:switch_to(X, Y, X)。【switch_to详解】书上认为直接看pseudo的汇编代码比较好,我却觉得直接看Linux源代码中的inline汇编代码更为自在(为了阅读方便和语法高亮有效,却掉了原代码中宏定义的换行,想查看原来的代码,请访问http://lxr.linux.no/linux+v2.6.11/include/asm-i386/system.h#L15 ): C代码 #define switch_to(prev,next,last) do { unsigned long esi,edi; asm volatile("pushfl\n\t" "pushl %%ebp\n\t" "movl %%esp,%0\n\t" "movl %5,%%esp\n\t" "movl $1f,%1\n\t" "pushl %6\n\t" "jmp __switch_to\n" "1:\t" "popl %%ebp\n\t" "popfl" :"=m" (prev->thread.esp),"=m" (prev->thread.eip), "=a" (last),"=S" (esi),"=D" (edi) :"m" (next->thread.esp),"m" (next->thread.eip), "2" (prev), "d" (next)); } while (0) #define switch_to(prev,next,last)do { unsigned long esi,edi; asm volatile("pushfl\n\t" "pushl %%ebp\n\t" "movl %%esp,%0\n\t" "movl %5,%%esp\n\t" "movl $1f,%1\n\t" "pushl %6\n\t" "jmp __switch_to\n" "1:\t" "popl %%ebp\n\t" "popfl" :"=m" (prev->thread.esp),"=m" (prev->thread.eip), "=a" (last),"=S" (esi),"=D" (edi) :"m" (next->thread.esp),"m" (next->thread.eip), "2" (prev), "d" (next)); } while (0) 简单解说一下这里用到的gcc的inline汇编语法。首先看上去像是汇编代码的自然就是汇编代码了,每个指令写到一对""中(这是换行接