东北大学 论文格式要求
- 格式:docx
- 大小:16.36 KB
- 文档页数:2
东北大学秦皇岛分校本科生毕业设计(论文)撰写规范毕业设计(论文)是培养学生综合运用本学科的基本理论、专业知识和基本技能,提高分析和解决实际问题的能力,完成初步培养从事科学研究工作和专业工程技术工作基本训练的重要环节。
为了统一和规范我校本科生毕业设计(论文)的写作,保证我校本科生毕业设计(论文)的质量,根据《中华人民共和国国家标准科学技术报告、学位论文和学术论文的编写格式》(国家标准GB7713-87)的规定,制定《东北大学秦皇岛分校本科生毕业设计(论文)撰写规范》:1 内容要求1.1 论文题目论文题目应该简短、明确、有概括性。
读者通过题目,能大致了解论文的内容、专业的特点和学科的范畴。
题目要符合汉语逻辑,字数要适当,一般不宜超过24字。
必要时可加副标题。
1.2 摘要与关键词1.2.1 论文摘要论文摘要应概括地反映出毕业设计(论文)的目的、内容、方法、成果和结论。
摘要中不宜使用公式、图表,不标注引用文献编号。
摘要应是一篇完整的短文,篇幅以300~500字为宜。
1.2.2 关键词关键词是供检索用的主题词条,应采用能覆盖论文主要内容的通用技术词条(参照相应的技术术语标准)。
关键词一般为3~5个,按词条的外延层次排列(外延大的排在前面)。
1.3 目录目录按章、节、条三级标题编写,要求标题层次清晰。
目录中的标题要与正文中标题一致。
目录中应包括绪论、论文主体、结论、致谢、参考文献、附录等。
1.4 论文正文论文正文是毕业设计(论文)的主体和核心部分,一般应包括绪论、论文主体及结论等部分。
1.4.1 绪论绪论一般作为第一章,是毕业设计(论文)主体的开端。
绪论应包括:毕业设计的背景及目的;国内外研究状况和相关领域中已有的研究成果;课题的研究方法;论文构成及研究内容等。
绪论一般不少于2千字。
1.4.2 论文主体论文主体是毕业设计(论文)的主要部分,应该结构合理,层次清楚,重点突出,文字简练、通顺。
论文主体的内容应包括以下各方面:(1) 毕业设计(论文)总体方案设计与选择的论证。
东北大学秦皇岛分校本科生毕业设计(论文)撰写规范与模板毕业设计(论文)是培养学生知识、能力和素质的重要环节,撰写本科毕业设计(论文)是人才能力培养的重要体现,为确保毕业设计论文撰写质量,特制定东北大学秦皇岛分校本科生毕业设计(论文)撰写规范及模板。
在遵照本规范的前提下,各学院还可根据不同专业特点对相关专业的毕业设计(论文)撰写格式提出更为具体的要求。
(一)字体和字号要求论文题目:二号黑体各章标题:三号黑体各节各级标题:小四号黑体正文中中文内容:小四号宋体正文中英文、数字内容:小四号,Times New Roman体中文摘要、结论、参考文献标题:三号黑体中文摘要、结论、参考文献内容:小四号宋体英文摘要、结论、参考文献标题:粗体三号,Times New Roman体英文摘要、结论、参考文献内容:小四号,Times New Roman体中文关键词标题:小四号黑体中文关键词:小四号宋体英文关键词标题:粗体小四号,Times New Roman体英文关键词:小四号,Times New Roman体目录标题:三号黑体目录中各章标题(含结论、参考文献、致小四号黑体谢、附录标题):目录中其他中文内容:小四号宋体目录中其他英文、数字内容:小四号,Times New Roman体页码:五号,Times New Roman体(二)页面设置要求1. 页眉顶端距离设置为1.5cm,底端距离为1.75cm;页眉“东北大学秦皇岛分校本科生毕业设计(论文)”黑体,四号,居中。
2. 论文奇数页上边距:30mm,下边距:25mm,左边距:30mm,右边距:20mm。
3. 论文偶数页上边距:30mm,下边距:25mm,左边距:20mm,右边距:30mm。
4. 行间距为1.5倍行距。
(三)页码编排与排版要求1. 页码位于页脚中间。
2. 摘要和目录页码用罗马数字单独编排。
3. 论文页码从绪论部分开始至附录,用阿拉伯数字连续编排。
4. 绪论首页必须在奇数页码上,各章之间加分页符。
东北大学继续教育学院毕业设计(论文)工作规范第一篇:东北大学继续教育学院毕业设计(论文)工作规范东北大学成人高等教育本科生毕业设计(论文)工作规范毕业设计(论文)是培养学生知识、能力和素质的重要环节,是进行综合训练的教学阶段。
做好毕业设计(论文)对培养学生的工程意识、开拓精神、创新能力、科学作风、综合素质都具有重要作用。
为确保毕业设计(论文)的质量,特制定东北大学继续教育学院本科生毕业设计(论文)工作规范。
一、指导思想通过毕业设计(论文)工作使大学生达到基本知识、基础理论、基本技能(三基)和运用知识能力、文献检索能力、实验测试能力、计算机应用能力、制图能力(六个能力)以及文化素质、思想品德素质、业务素质(三个素质)的训练,培养学生运用所学的专业知识和技术,研究、解决本专业实际问题的能力。
同时,毕业设计(论文)工作是大学教育的综合训练,也是对教育质量的检验。
二、选题选题是对毕业设计(论文)工作范围进行专业确定的环节。
1.毕业设计(论文)的选题要按照所学专业培养目标确定。
围绕本专业、学科选择有一定理论与实用价值的具有运用课程知识、能力训练的题目;2.选题尽可能与科研、生产相结合。
工科类专业以毕业设计为主;文理科类专业毕业论文要理论与实践相结合,有实用价值;3.毕业设计(论文)的题目要坚持每人一题。
指导教师可将大而难的题目分解成若干个子题目,作为由学生完成的课题;4.对于与往届重复的课题,严禁将往届毕业设计(论文)借给学生参考,防止出现抄袭现象;5.毕业设计(论文)的课题须由研究所审核,在审核批准后下达任务书;6.无任务书不能进行毕业设计(论文)工作。
三、对毕业设计(论文)的基本要求1.要求学生能够在毕业设计(论文)中应用基本知识、基础理论和基本技能去分析问题和解决问题,并表现出一定的工程设计和科学研究能力;2.学生能独立检索文献资料并恰当运用;3.学生能进行本专业范围内的实验、测试、计算、绘图、设计、计算机应用等综合训练;4.毕业设计(论文)的理论依据要充分,数据准确,公式推导正确。
东北大学硕士学位论文排版打印格式1. 引言依据中华人民共和国《科学技术报告、学位论文和学术论文的编写格式》和东北大学学位论文格式改编,专为我校申请硕士、博士学位人员撰写打印论文时使用。
本格式自发布日起实行。
2. 学位论文主要部分学位论文主要部分由前头部分、主体部分和结尾部分(只限必要时采用)组成。
2.1 前头部分(1)封面(2)扉页——题名页(中、英两种)(4)声明(独创性声明)(3)摘要(中、英两种文字)(5)目录(6)插图和附表清单(只限必要时)(7)缩略字、缩写词、符号、单位表(只限必要时)(8)名词术语注释表(只限必要时)2.2 主体部分(1)绪论(前言、引言、绪言)(2)正文(3)讨论、结论和建议2.3 结尾部分(只限必要时采用)(1)参考文献(2)致谢(3)攻读学位期间发表的论著、获奖情况及发明专利等项。
(4)作者从事科学研究和学习经历的简历(5)可供参考的文献题录(只限必要时采用)(6)索引(只限必要时采用)3. 版式纸张大小:纸的尺寸为标准A4复印纸(210mm×297mm)。
版芯(打印尺寸):160mm×247mm(不包括页眉行、页码行)。
正文字体字号:小4号宋体,全文统一。
每页30~35行,每行35~38字。
装订:双面打印印刷,沿长边装订。
页码:页码用阿拉伯数字连续编页,字号与正文字体相同,页底居中,数字两侧用圆点或一字横线修饰,如·3·或-3-。
页眉:自摘要页起加页眉,眉体可用单线或双线(二等线、文武线),页眉说明5号楷体,左端“东北大学硕士、博士学位论文”,右端“章号章题”。
封面:东北大学研究生(博士或硕士)学位论文标准封面(双A4)。
4. 体例4.1 标题论文正文按章、条、款、项分级,在不同级的章、条、款、项阿拉伯数字编号之间用点“.”(半角实心下圆点)相隔,最末级编号之后不加点。
排版格式见表4.1。
此分级编号法只分至第四级。
再分可用(1)、(2)……;(a)、(b)……等。
目录一、内容总体要求 (3)(一)引言 (3)(二)论文的类型 (3)(三)毕业设计的选题 (3)(四)论文的写作 (4)二、编写格式 (5)(一)封面 (5)1、论文题目 (6)2、作者姓名 (6)3、指导教师姓名 (6)4、论文封面日期 (6)(二)中文题名页 (6)1、题目 (6)2、姓名 (6)3、学校与日期 (7)(三)英文题名页 (7)1、题目 (7)2、姓名 (7)3、职称 (7)4、学校与日期 (7)(四)毕业设计论文(任务书) (7)1、毕业设计(论文)题目 (7)2、基本内容 (7)3、毕业设计(论文)专题部分 (8)4、学生接受毕业设计(论文)题目日期 (8)(五)中文摘要 (8)1、中文题目 (8)2、摘要 (8)3、摘要内容 (8)4、关键词 (8)5、关键词内容 (8)6、关键词的选取 (8)7、摘要内容的编写 (9)(六)英文摘要 (9)1、题目 (9)2、摘要 (9)3、格式 (9)4、关键词 (9)(七)目录 (9)1、目录 (10)2、索引条目 (10)3、各节 (10)(八)正文 (10)1、标题 (11)2、正文 (11)3、节 (11)4、小节 (12)5、正文编号 (12)6、图 (12)7、表 (12)8、程序代码 (13)9、结论 (13)(九)参考文献 (13)(十)结束语(致谢) (14)三、其他要求 (14)1、打印 (14)2、页码编排 (14)3、页眉设置 (14)4、装订 (14)东北大学软件学院毕业设计(论文)撰写与排版规范一、内容总体要求(一)引言毕业设计(论文)是学生在校学习的最后阶段,是培养学生综合运用所学知识,发现、提出、分析和解决实际问题,锻炼实践能力的重要环节,是对学生实际工作能力的系统训练和考察过程。
毕业设计(论文,下称论文)是学生在教师指导下,对所从事工作和取得成果的完整表述,是学生毕业及学位资格认定的重要依据。
论文的撰写是学生基本能力训练的过程,应当符合国家及有关行业(部门)指定的有关标准,符合汉语语言规范。
东北大学材料科学与工程学院硕士、博士学位论文撰写与版式规范1. 引言依据中华人民共和国《科学技术报告、学位论文和学术论文的编写格式》和东北大学学位论文格式改编,专为我院申请硕士、博士学位人员撰写、打印论文时使用。
本规范自发布日起实行。
2. 学位论文结构组成学位论文由前头部分、主体部分和结尾部分组成。
2.1 前头部分(1)封面(2)扉页——题名页(中、英两种)(3)声明(独创性声明和版权声明)(4)中、英文摘要(5)目录(6)名词术语、缩略字、缩写词等注释表(只限必要时)2.2 主体部分(1)绪论(前言、引言、绪言)(2)正文(3)结论和建议2.3 结尾部分(1)参考文献(2)附录、附表(只限必要时)(3)致谢(4)攻读学位期间发表的论著、获奖情况及发明专利等项。
(5)作者简历3. 学位论文内容要求3.1 题目题目应以简明的词语,恰当、准确、科学地反映论文最重要的内容,一般不超过25字,应中英文对照。
题目通常由名词性短语构成,不能含有标点符号;应尽量避免使用不常用的缩略词、字符、代号和公式等。
3.2 摘要与关键词3.2.1 摘要摘要是论文内容的高度概括,应具有独立性和自含性,即不阅读论文的全文,就能通过摘要了解整个论文的主要信息。
摘要应包括本论文研究的目的、理论与实际意义、主要研究内容、实验方法,重点是研究结果和结论。
摘要的内容要完整、客观、准确,应按层次逐段简要写出。
避免将摘要写成目录式的内容介绍,避免主观性的评价意见,避免对背景、目的、意义、概念和一般性(常识性)理论过多叙述。
摘要中尽量不使用第一人称,采用“分析了……原因”、“认为……”、“对……进行了探讨”等记述方法进行描述。
摘要需采用规范的名词术语(包括地名、机构名和人名)。
对个别新术语或无中文译文的术语,可用外文或在中文译文后加括号注明外文。
摘要中不宜使用图表,尽量少用公式、化学结构式、非常用的缩写词和非公知公用的符号与术语,不标注引用文献编号。
东北大学硕士学位论文排版打印格式1. 引言依据中华人民共和国《科学技术报告、学位论文和学术论文的编写格式》和东北大学学位论文格式改编,专为我校申请硕士、博士学位人员撰写打印论文时使用。
本格式自发布日起实行。
2. 学位论文主要部分学位论文主要部分由前头部分、主体部分和结尾部分(只限必要时采用)组成。
2.1 前头部分(1)封面(2)扉页——题名页(中、英两种)(4)声明(独创性声明)(3)摘要(中、英两种文字)(5)目录(6)插图和附表清单(只限必要时)(7)缩略字、缩写词、符号、单位表(只限必要时)(8)名词术语注释表(只限必要时)2.2 主体部分(1)绪论(前言、引言、绪言)(2)正文(3)讨论、结论和建议2.3 结尾部分(只限必要时采用)(1)参考文献(2)致谢(3)攻读学位期间发表的论著、获奖情况及发明专利等项。
(4)作者从事科学研究和学习经历的简历(5)可供参考的文献题录(只限必要时采用)(6)索引(只限必要时采用)3. 版式纸张大小:纸的尺寸为标准A4复印纸(210mm×297mm)。
版芯(打印尺寸):160mm×247mm(不包括页眉行、页码行)。
正文字体字号:小4号宋体,全文统一。
每页30~35行,每行35~38字。
装订:双面打印印刷,沿长边装订。
页码:页码用阿拉伯数字连续编页,字号与正文字体相同,页底居中,数字两侧用圆点或一字横线修饰,如·3·或-3-。
页眉:自摘要页起加页眉,眉体可用单线或双线(二等线、文武线),页眉说明5号楷体,左端“东北大学硕士、博士学位论文”,右端“章号章题”。
封面:东北大学研究生(博士或硕士)学位论文标准封面(双A4)。
4. 体例4.1 标题论文正文按章、条、款、项分级,在不同级的章、条、款、项阿拉伯数字编号之间用点“.”(半角实心下圆点)相隔,最末级编号之后不加点。
排版格式见表4.1。
此分级编号法只分至第四级。
再分可用(1)、(2)……;(a)、(b)……等。
东北大学东软信息学院外文资料和译文格式要求一、译文必须采用计算机输入、打印,幅面A4。
外文资料原文(复印或打印)在前,译文在后,于左侧装订。
二、具体要求1、至少翻译一篇内容与所选课题相关的外文文献。
2、译文汉字字数不少于4000字。
3、正文格式要求:宋体五号字。
附:外文资料和译文封面、空白页外文资料和译文专业:班级:姓名:学号:指导教师:2010年12月23日5.2.5. Read/Write Spin LocksRead/write spin locks have been introduced to increase the amount of concurrency inside the kernel. They allow several kernel control paths to simultaneously read the same data structure, as long as no kernel control path modifies it. If a kernel control path wishes to write to the structure, it must acquire the write version of the read/write lock, which grants exclusive access to the resource. Of course, allowing concurrent reads on data structures improves system performance.Figure 5-2 illustrates two critical regions (C1 and C2) protected by read/write locks. Kernel control paths R0 and R1 are reading the data structures in C1 at the same time, while W0 is waiting to acquire the lock for writing. Kernel control path W1 is writing the data structures inC2, while both R2 and W2 are waiting to acquire the lock for reading and writing, respectively.Figure 5-2. Read/write spin locksEach read/write spin lock is a rwlock_t structure; its lock field is a 32-bit field that encodes two distinct pieces of information:∙ A 24-bit counter denoting the number of kernel control paths currently reading the protected data structure. The two's complement value of this counter is stored in bits 023 of the field.∙An unlock flag that is set when no kernel control path is reading or writing, and clear otherwise. This unlock flag is stored in bit 24 of the field.Notice that the lock field stores the number 0x01000000 if the spin lock is idle (unlock flag set and no readers), the number 0x00000000 if it has been acquired for writing (unlock flag clear and no readers), and any number in the sequence 0x00ffffff, 0x00fffffe, and so on, if it has been acquired for reading by one, two, or more processes (unlock flag clear and the two's complement on 24 bits of the number of readers). As the spinlock_t structure, the rwlock_t structure also includes a break_lock field.The rwlock_init macro initializes the lock field of a read/write spin lock to 0x01000000 (unlocked) and the break_lock field to zero.5.2.5.1. Getting and releasing a lock for readingThe read_lock macro, applied to the address rwlp of a read/write spin lock, is similar to thespin_lock macro described in the previous section. If the kernel preemption option has been selected when the kernel was compiled, the macro performs the very same actions as those of spin_lock( ), with just one exception: to effectively acquire the read/write spin lock in step 2, the macro executes the _raw_read_trylock( ) function:int _raw_read_trylock(rwlock_t *lock){atomic_t *count = (atomic_t *)lock->lock;atomic_dec(count);if (atomic_read(count) >= 0)return 1;atomic_inc(count);return 0;}The lock fieldthe read/write lock counteris accessed by means of atomic operations. Notice, however, that the whole function does not act atomically on the counter: for instance, the counter might change after having tested its value with the if statement and before returning 1. Nevertheless, the function works properly: in fact, the function returns 1 only if the counter was not zero or negative before the decrement, because the counter is equal to 0x01000000 for no owner, 0x00ffffff for one reader, and 0x00000000 for one writer.If the kernel preemption option has not been selected when the kernel was compiled, theread_lock macro yields the following assembly language code:movl $rwlp->lock,%eaxlock; subl $1,(%eax)jns 1fcall _ _read_lock_failed1:where _ _read_lock_failed( ) is the following assembly language function:_ _read_lock_failed:lock; incl (%eax)1: pausecmpl $1,(%eax)js 1block; decl (%eax)js _ _read_lock_failedretThe read_lock macro atomically decreases the spin lock value by 1, thus increasing the number of readers. The spin lock is acquired if the decrement operation yields a nonnegative value; otherwise, the _ _read_lock_failed( ) function is invoked. The function atomically increases the lock field to undo the decrement operation performed by the read_lock macro, and then loops until the field becomes positive (greater than or equal to 1). Next, _ _read_lock_failed( ) tries to get the spin lock again (another kernel control path could acquire the spin lock for writing right after the cmpl instruction).Releasing the read lock is quite simple, because the read_unlock macro must simply increase the counter in the lock field with the assembly language instruction:lock; incl rwlp->lockto decrease the number of readers, and then invoke preempt_enable( ) to reenable kernel preemption.5.2.5.2. Getting and releasing a lock for writingThe write_lock macro is implemented in the same way as spin_lock( ) andread_lock( ). For instance, if kernel preemption is supported, the function disables kernel preemption and tries to grab the lock right away by invoking_raw_write_trylock( ). If this function returns 0, the lock was already taken, thus the macro reenables kernel preemption and starts a busy wait loop, as explained in the description of spin_lock( ) in the previous section.The _raw_write_trylock( ) function is shown below:int _raw_write_trylock(rwlock_t *lock){atomic_t *count = (atomic_t *)lock->lock;if (atomic_sub_and_test(0x01000000, count))return 1;atomic_add(0x01000000, count);return 0;}The _raw_write_trylock( ) function subtracts 0x01000000 from the read/write spin lock value, thus clearing the unlock flag (bit 24). If the subtraction operation yieldszero (no readers), the lock is acquired and the function returns 1; otherwise, the function atomically adds 0x01000000 to the spin lock value to undo the subtraction operation.Once again, releasing the write lock is much simpler because the write_unlock macro must simply set the unlock flag in the lock field with the assembly language instruction:lock; addl $0x01000000,rwlpand then invoke preempt_enable().5.2.6. SeqlocksWhen using read/write spin locks, requests issued by kernel control paths to perform a read_lock or a write_lock operation have the same priority: readers must wait until the writer has finished and, similarly, a writer must wait until all readers have finished.Seqlocks introduced in Linux 2.6 are similar to read/write spin locks, except that they give a much higher priority to writers: in fact a writer is allowed to proceed even when readers are active. The good part of this strategy is that a writer never waits (unless another writer is active); the bad part is that a reader may sometimes be forced to read the same data several times until it gets a valid copy.Each seqlock is a seqlock_t structure consisting of two fields: a lock field of type spinlock_t and an integer sequence field. This second field plays the role of a sequence counter. Each reader must read this sequence counter twice, before and after reading the data, and check whether the two values coincide. In the opposite case, a new writer has become active and has increased the sequence counter, thus implicitly telling the reader that the data just read is not valid.A seqlock_t variable is initialized to "unlocked" either by assigning to it the value SEQLOCK_UNLOCKED, or by executing the seqlock_init macro. Writers acquire and release a seqlock by invoking write_seqlock( ) and write_sequnlock( ). The first function acquires the spin lock in the seqlock_t data structure, then increases the sequence counter by one; the second function increases the sequence counter once more, then releases the spin lock. This ensures that when the writer is in the middle of writing, the counter is odd, and that when no writer is altering data, the counter is even. Readers implement a critical region as follows:unsigned int seq;do {seq = read_seqbegin(&seqlock);/* ... CRITICAL REGION ... */} while (read_seqretry(&seqlock, seq));read_seqbegin() returns the current sequence number of the seqlock; read_seqretry() returns 1 if either the value of the seq local variable is odd (a writer was updating the data structure when the read_seqbegin( ) function has been invoked), or if the value of seq does not match the current value of the seqlock's sequence counter (a writer started working while the reader was still executing the code in the critical region).Notice that when a reader enters a critical region, it does not need to disable kernel preemption; on the other hand, the writer automatically disables kernel preemption when entering the critical region, because it acquires the spin lock.Not every kind of data structure can be protected by a seqlock. As a general rule, the following conditions must hold:∙The data structure to be protected does not include pointers that are modified by the writers and dereferenced by the readers (otherwise, a writer couldchange the pointer under the nose of the readers)∙The code in the critical regions of the readers does not have side effects (otherwise, multiple reads would have different effects from a single read) Furthermore, the critical regions of the readers should be short and writers should seldom acquire the seqlock, otherwise repeated read accesses would cause a severe overhead. A typical usage of seqlocks in Linux 2.6 consists of protecting some data structures related to the system time handling (see Chapter 6).5.2.7. Read-Copy Update (RCU)Read-copy update (RCU) is yet another synchronization technique designed to protect data structures that are mostly accessed for reading by several CPUs. RCU allows many readers and many writers to proceed concurrently (an improvement over seqlocks, which allow only one writer to proceed). Moreover, RCU is lock-free, that is, it uses no lock or counter shared by all CPUs; this is a great advantage over read/write spin locks and seqlocks, which have a high overhead due to cache line-snooping and invalidation.How does RCU obtain the surprising result of synchronizing several CPUs without shared data structures? The key idea consists of limiting the scope of RCU as follows:1.Only data structures that are dynamically allocated and referenced by meansof pointers can be protected by RCU.2.No kernel control path can sleep inside a critical region protected by RCU.When a kernel control path wants to read an RCU-protected data structure, it executes the rcu_read_lock( ) macro, which is equivalent to preempt_disable( ). Next, the reader dereferences the pointer to the data structure and starts reading it. As stated above, the reader cannot sleep until it finishes reading the data structure; the end of the critical region is marked by the rcu_read_unlock( ) macro, which is equivalent to preempt_enable( ).Because the reader does very little to prevent race conditions, we could expect that the writer has to work a bit more. In fact, when a writer wants to update the data structure, it dereferences the pointer and makes a copy of the whole data structure. Next, the writer modifies the copy. Once finished, the writer changes the pointer to the data structure so as to make it point to the updated copy. Because changing the value of the pointer is an atomic operation, each reader or writer sees either the old copy or the new one: no corruption in the data structure may occur. However, a memory barrier is required to ensure that the updated pointer is seen by the other CPUs only after the data structure has been modified. Such a memory barrier is implicitly introduced if a spin lock is coupled with RCU to forbid the concurrent execution of writers.The real problem with the RCU technique, however, is that the old copy of the data structure cannot be freed right away when the writer updates the pointer. In fact, the readers that were accessing the data structure when the writer started its update could still be reading the old copy. The old copy can be freed only after all (potential) readers on the CPUs have executed the rcu_read_unlock( ) macro. The kernel requires every potential reader to execute that macro before:∙The CPU performs a process switch (see restriction 2 earlier).∙The CPU starts executing in User Mode.∙The CPU executes the idle loop (see the section "Kernel Threads" in Chapter 3).In each of these cases, we say that the CPU has gone through a quiescent state.The call_rcu( ) function is invoked by the writer to get rid of the old copy of the data structure. It receives as its parameters the address of an rcu_head descriptor (usually embedded inside the data structure to be freed) and the address of a callback function to be invoked when all CPUs have gone through a quiescent state. Once executed, the callback function usually frees the old copy of the data structure.The call_rcu( ) function stores in the rcu_head descriptor the address of the callback and its parameter, then inserts the descriptor in a per-CPU list of callbacks. Periodically, once every tick (see the section "Updating Local CPU Statistics" in Chapter 6), the kernel checks whether the local CPU has gone through a quiescent state. When all CPUs have gone through a quiescent state, a local taskletwhose descriptor is stored in the rcu_tasklet per-CPU variableexecutes all callbacks in the list.RCU is a new addition in Linux 2.6; it is used in the networking layer and in the Virtual Filesystem.5.2.8. SemaphoresWe have already introduced semaphores in the section "Synchronization and Critical Regions" in Chapter 1. Essentially, they implement a locking primitive that allows waiters to sleep until the desired resource becomes free.Actually, Linux offers two kinds of semaphores:∙Kernel semaphores, which are used by kernel control paths∙System V IPC semaphores, which are used by User Mode processesIn this section, we focus on kernel semaphores, while IPC semaphores are described in Chapter 19.A kernel semaphore is similar to a spin lock, in that it doesn't allow a kernel control path to proceed unless the lock is open. However, whenever a kernel control path tries to acquire a busy resource protected by a kernel semaphore, the corresponding process is suspended. It becomes runnable again when the resource is released. Therefore, kernel semaphores can be acquired only by functions that are allowed to sleep; interrupt handlers and deferrable functions cannot use them.A kernel semaphore is an object of type struct semaphore, containing the fields shown in the following list.countStores an atomic_t value. If it is greater than 0, the resource is free that is, itis currently available. If count is equal to 0, the semaphore is busy but noother process is waiting for the protected resource. Finally, if count isnegative, the resource is unavailable and at least one process is waiting for it.waitStores the address of a wait queue list that includes all sleeping processes that are currently waiting for the resource. Of course, if count is greater than orequal to 0, the wait queue is empty.sleepersStores a flag that indicates whether some processes are sleeping on thesemaphore. We'll see this field in operation soon.The init_MUTEX( ) and init_MUTEX_LOCKED( ) functions may be used to initialize a semaphore for exclusive access: they set the count field to 1 (free resource with exclusive access) and 0 (busy resource with exclusive access currently granted to the process that initializes the semaphore), respectively. The DECLARE_MUTEX and DECLARE_MUTEX_LOCKED macros do the same, but they also statically allocate the struct semaphore variable. Note that a semaphore could also be initialized with an arbitrary positive value n for count. In this case, at most n processes are allowed to concurrently access the resource.5.2.8.1. Getting and releasing semaphoresLet's start by discussing how to release a semaphore, which is much simpler than getting one. When a process wishes to release a kernel semaphore lock, it invokes the up( ) function. This function is essentially equivalent to the following assembly language fragment:movl $sem->count,%ecxlock; incl (%ecx)jg 1flea %ecx,%eaxpushl %edxpushl %ecxcall _ _uppopl %ecxpopl %edx1:where _ _up( ) is the following C function:__attribute__((regparm(3))) void _ _up(struct semaphore *sem){wake_up(&sem->wait);}The up( ) function increases the count field of the *sem semaphore, and then it checks whether its value is greater than 0. The increment of count and the setting of the flag tested by the following jump instruction must be atomically executed, or else another kernel control path could concurrently access the field value, with disastrousresults. If count is greater than 0, there was no process sleeping in the wait queue, so nothing has to be done. Otherwise, the _ _up( ) function is invoked so that one sleeping process is woken up. Notice that _ _up( ) receives its parameter from the eax register (see the description of the _ _switch_to( ) function in the section "Performing the Process Switch" in Chapter 3).Conversely, when a process wishes to acquire a kernel semaphore lock, it invokes the down( ) function. The implementation of down( ) is quite involved, but it is essentially equivalent to the following:down:movl $sem->count,%ecxlock; decl (%ecx);jns 1flea %ecx, %eaxpushl %edxpushl %ecxcall _ _downpopl %ecxpopl %edx1:where _ _down( ) is the following C function:__attribute__((regparm(3))) void _ _down(struct semaphore * sem){DECLARE_WAITQUEUE(wait, current);unsigned long flags;current->state = TASK_UNINTERRUPTIBLE;spin_lock_irqsave(&sem->wait.lock, flags);add_wait_queue_exclusive_locked(&sem->wait, &wait);sem->sleepers++;for (;;) {if (!atomic_add_negative(sem->sleepers-1, &sem->count)) {sem->sleepers = 0;break;}sem->sleepers = 1;spin_unlock_irqrestore(&sem->wait.lock, flags);schedule( );spin_lock_irqsave(&sem->wait.lock, flags);current->state = TASK_UNINTERRUPTIBLE;}remove_wait_queue_locked(&sem->wait, &wait);wake_up_locked(&sem->wait);spin_unlock_irqrestore(&sem->wait.lock, flags);current->state = TASK_RUNNING;}The down( ) function decreases the count field of the *sem semaphore, and then checks whether its value is negative. Again, the decrement and the test must be atomically executed. If count is greater than or equal to 0, the current process acquires the resource and the execution continues normally. Otherwise, count is negative, and the current process must be suspended. The contents of some registers are saved on the stack, and then _ _down( ) is invoked.Essentially, the _ _down( ) function changes the state of the current process from TASK_RUNNING to TASK_UNINTERRUPTIBLE, and it puts the process in the semaphore wait queue. Before accessing the fields of the semaphore structure, the function also gets the sem->wait.lock spin lock that protects the semaphore wait queue (see "How Processes Are Organized" in Chapter 3) and disables local interrupts. Usually, wait queue functions get and release the wait queue spin lock as necessary when inserting and deleting an element. The _ _down( ) function, however, uses the wait queue spin lock also to protect the other fields of the semaphore data structure, so that no process running on another CPU is able to read or modify them. To that end, _ _down( ) uses the "_locked" versions of the wait queue functions, which assume that the spin lock has been already acquired before their invocations.The main task of the _ _down( ) function is to suspend the current process until the semaphore is released. However, the way in which this is done is quite involved. To easily understand the code, keep in mind that the sleepers field of the semaphore is usually set to 0 if no process is sleeping in the wait queue of the semaphore, and it is set to 1 otherwise. Let's try to explain the code by considering a few typical cases. MUTEX semaphore open (count equal to 1, sleepers equal to 0)The down macro just sets the count field to 0 and jumps to the nextinstruction of the main program; therefore, the _ _down( ) function is notexecuted at all.MUTEX semaphore closed, no sleeping processes (count equal to 0, sleepers equal to 0)The down macro decreases count and invokes the _ _down( ) function withthe count field set to -1 and the sleepers field set to 0. In each iteration of theloop, the function checks whether the count field is negative. (Observe thatthe count field is not changed by atomic_add_negative( ) because sleepers isequal to 0 when the function is invoked.)∙If the count field is negative, the function invokes schedule( ) tosuspend the current process. The count field is still set to -1, and thesleepers field to 1. The process picks up its run subsequently insidethis loop and issues the test again.∙If the count field is not negative, the function sets sleepers to 0 and exits from the loop. It tries to wake up another process in thesemaphore wait queue (but in our scenario, the queue is now empty)and terminates holding the semaphore. On exit, both the count fieldand the sleepers field are set to 0, as required when the semaphore isclosed but no process is waiting for it.MUTEX semaphore closed, other sleeping processes (count equal to -1, sleepers equal to 1)The down macro decreases count and invokes the _ _down( ) function withcount set to -2 and sleepers set to 1. The function temporarily sets sleepers to 2, and then undoes the decrement performed by the down macro by addingthe value sleepers-1 to count. At the same time, the function checks whethercount is still negative (the semaphore could have been released by theholding process right before _ _down( ) entered the critical region).∙If the count field is negative, the function resets sleepers to 1 andinvokes schedule( ) to suspend the current process. The count field isstill set to -1, and the sleepers field to 1.∙If the count field is not negative, the function sets sleepers to 0, tries to wake up another process in the semaphore wait queue, and exitsholding the semaphore. On exit, the count field is set to 0 and thesleepers field to 0. The values of both fields look wrong, becausethere are other sleeping processes. However, consider that anotherprocess in the wait queue has been woken up. This process doesanother iteration of the loop; the atomic_add_negative( ) functionsubtracts 1 from count, restoring it to -1; moreover, before returningto sleep, the woken-up process resets sleepers to 1.So, the code properly works in all cases. Consider that the wake_up( ) function in _ _down( ) wakes up at most one process, because the sleeping processes in the wait queue are exclusive (see the section "How Processes Are Organized" in Chapter 3).Only exception handlers , and particularly system call service routines , can use the down( ) function. Interrupt handlers or deferrable functions must not invoke down( ),because this function suspends the process when the semaphore is busy. For this reason, Linux provides the down_trylock( ) function, which may be safely used by one of the previously mentioned asynchronous functions. It is identical to down( ) except when the resource is busy. In this case, the function returns immediately instead of putting the process to sleep.A slightly different function called down_interruptible( ) is also defined. It is widely used by device drivers, because it allows processes that receive a signal while being blocked on a semaphore to give up the "down" operation. If the sleeping process is woken up by a signal before getting the needed resource, the function increases the count field of the semaphore and returns the value -EINTR. On the other hand, if down_interruptible( ) runs to normal completion and gets the resource, it returns 0. The device driver may thus abort the I/O operation when the return value is -EINTR.Finally, because processes usually find semaphores in an open state, the semaphore functions are optimized for this case. In particular, the up( ) function does not execute jump instructions if the semaphore wait queue is empty; similarly, the down( ) function does not execute jump instructions if the semaphore is open. Much of the complexity of the semaphore implementation is precisely due to the effort of avoiding costly instructions in the main branch of the execution flow.5.2.9. Read/Write SemaphoresRead/write semaphores are similar to the read/write spin locks described earlier in the section "Read/Write Spin Locks," except that waiting processes are suspended instead of spinning until the semaphore becomes open again.Many kernel control paths may concurrently acquire a read/write semaphore for reading; however, every writer kernel control path must have exclusive access to the protected resource. Therefore, the semaphore can be acquired for writing only if no other kernel control path is holding it for either read or write access. Read/write semaphores improve the amount of concurrency inside the kernel and improve overall system performance.The kernel handles all processes waiting for a read/write semaphore in strict FIFO order. Each reader or writer that finds the semaphore closed is inserted in the last position of a semaphore's wait queue list. When the semaphore is released, the process in the first position of the wait queue list are checked. The first process is always awoken. If it is a writer, the other processes in the wait queue continue to sleep. If it is a reader, all readers at the start of the queue, up to the first writer, are also woken up and get the lock. However, readers that have been queued after a writer continue to sleep.Each read/write semaphore is described by a rw_semaphore structure that includes the following fields:countStores two 16-bit counters. The counter in the most significant word encodesin two's complement form the sum of the number of nonwaiting writers(either 0 or 1) and the number of waiting kernel control paths. The counter inthe less significant word encodes the total number of nonwaiting readers andwriters.wait_listPoints to a list of waiting processes. Each element in this list is arwsem_waiter structure, including a pointer to the descriptor of the sleepingprocess and a flag indicating whether the process wants the semaphore forreading or for writing.wait_lockA spin lock used to protect the wait queue list and the rw_semaphorestructure itself.The init_rwsem( ) function initializes an rw_semaphore structure by setting the count field to 0, the wait_lock spin lock to unlocked, and wait_list to the empty list. The down_read( ) and down_write( ) functions acquire the read/write semaphore for reading and writing, respectively. Similarly, the up_read( ) and up_write( ) functions release a read/write semaphore previously acquired for reading and for writing. The down_read_trylock( ) and down_write_trylock( ) functions are similar todown_read( ) and down_write( ), respectively, but they do not block the process if the semaphore is busy. Finally, the downgrade_write( ) function atomically transforms a write lock into a read lock. The implementation of these five functions is long, but easy to follow because it resembles the implementation of normal semaphores; therefore, we avoid describing them.5.2.10. CompletionsLinux 2.6 also makes use of another synchronization primitive similar to semaphores: completions . They have been introduced to solve a subtle race condition that occurs in multiprocessor systems when process A allocates a temporary semaphore variable, initializes it as closed MUTEX, passes its address to process B, and then invokes down( ) on it. Process A plans to destroy the semaphore as soon as it awakens. Later。
如何写论文——东北大学毕业论文格式
2010年04月19日星期一02:28 P.M.
论文开始排版了,老师要求的十分严格,大家是否像我一样为论文格式发愁呢?终于找到了本校的格式要求,分享给大家。
本格式来源,研究生入排版格式见下表:
(3)介于标题要求下的其它要求:
A.前置部分
(a)任务书:统一格式。
(b)扉页:中文题名按一级标题排版,居中,其它字体采用四号宋体,与提名左对齐;英文题名采用二号“Times New Roman”字体,居中,其它字体
(c)摘要页:摘要标题按一级标题排版;中文摘要和关键词采用小四号宋体,英文摘要和英文关键词采用小四号“Times New Roman”字体,1.5倍行
(d)目录:“目录”两字采用一级标题排版;章题目和结尾内容题目采用二级标题排版;节题目采用四号宋体字,1.5倍行距,居左;条题目采用小四须注明各题目的起始页码,页码为小四号“Times New Roman”字体,题目与页码用“·······”相连。
B.主体部分
(a)绪论、正文、结论部分除有标题要求外,汉字字体采用小四号宋体,1.5倍行距。
外文、数字字号与同行汉字字号相同,字体用“Times New R
(b)插图:插图包括图解、示意图、构造图、框图、流程图、布置图、地图、照片、图版等。
插图注明项有图号、图题、图例。
图号编码用章序题文字间置一字空格,置于图的正下方,图题用5号宋体,须全文统一。
图中标注符号文字字号不大于图题的字号。
(c)表:表的一般格式是数据依序竖排,内容和项目由左至右横读,通版排版。
表号也用章序号编码,如:表3.1是第3章中的第1表。
表应有方居中,用5号宋体,须全文统一。
表中的内容和项目字号不大于表题的字号。
(d)公式:公式包括数学、物理和化学公式。
正文中引用的公式、算式或方程式等可以按章序号用阿拉伯数字编号,如式(3.1)表示第3章第式号与公式同行居公式右侧排版。
C.结尾部分
(a)参考文献:中文字体采用小四号宋体。
外文、数字字号与汉字字号相同,字体用“Times New Roman”字体,1.5倍行距。
参考文献采用顺序
专著格式:序号.编著者.书名[M],出版地:出版社,年代,起止页码.
期刊论文格式:序号.作者.论文名称[J],期刊名称,年度,卷(期):起止页码.
会议文献格式:
序号.作者1,作者2,作者3等.文章题目名[A].论文集名[C].出版地:出版社,年代.起止页码.
学位论文格式:序号.作者.学位论文名称[D],发表地:学位授予单位,年度
注:作者姓名写到第三位,余者写“等.”。
(b)结束语(致谢):“结束语”标题采用一级标题格式排版。
中文字体采用小四号宋体,1.5倍行距。
外文、数字字号与同行汉字字号相同,字体
(c)附录:附录中的内容要与正文内容分开,用阿拉伯数字编号,须在数码前加上附录序码。
如:图A.1,式(B.2),表C.3等。
外文翻译部分小四号宋体,英文采用小四号“Times New Roman”字体,1.5倍行距。