无标题文章

目录

 

第1章 概述 - 4 -

1.1 Hello简介 - 4 -

1.2环境与工具 - 4 -

1.3中间结果 - 4 -

1.4本章小结 - 4 -

第2章 预处理 - 5 -

2.1预处理的概念与作用 - 5 -

2.2在Ubuntu下预处理的命令 - 5 -

2.3 Hello的预处理结果解析 - 5 -

2.4本章小结 - 5 -

第3章 编译 - 6 -

3.1编译的概念与作用 - 6 -

3.2在Ubuntu下编译的命令 - 6 -

3.3 Hello的编译结果解析 - 6 -

3.4本章小结 - 6 -

第4章 汇编 - 7 -

4.1汇编的概念与作用 - 7 -

4.2在Ubuntu下汇编的命令 - 7 -

4.3可重定位目标elf格式 - 7 -

4.4 Hello.o的结果解析 - 7 -

4.5本章小结 - 7 -

第5章 链接 - 8 -

5.1链接的概念与作用 - 8 -

5.2在Ubuntu下链接的命令 - 8 -

5.3可执行目标文件hello的格式 - 8 -

5.4 hello的虚拟地址空间 - 8 -

5.5链接的重定位过程分析 - 8 -

5.6 hello的执行流程 - 8 -

5.7 Hello的动态链接分析 - 8 -

5.8本章小结 - 9 -

第6章 hello进程管理 - 10 -

6.1进程的概念与作用 - 10 -

6.2简述壳Shell-bash的作用与处理流程 - 10 -

6.3 Hello的fork进程创建过程 - 10 -

6.4 Hello的execve过程 - 10 -

6.5 Hello的进程执行 - 10 -

6.6 hello的异常与信号处理 - 10 -

6.7本章小结 - 10 -

第7章 hello的存储管理 - 11 -

7.1 hello的存储器地址空间 - 11 -

7.2 Intel逻辑地址到线性地址的变换-段式管理 - 11 -

7.3 Hello的线性地址到物理地址的变换-页式管理 - 11 -

7.4 TLB与四级页表支持下的VA到PA的变换 - 11 -

7.5三级Cache支持下的物理内存访问 - 11 -

7.6 hello进程fork时的内存映射 - 11 -

7.7 hello进程execve时的内存映射 - 11 -

7.8缺页故障与缺页中断处理 - 11 -

7.9动态存储分配管理 - 11 -

7.10本章小结 - 12 -

第8章 hello的IO管理 - 13 -

8.1 Linux的IO设备管理方法 - 13 -

8.2简述Unix IO接口及其函数 - 13 -

8.3 printf的实现分析 - 13 -

8.4 getchar的实现分析 - 13 -

8.5本章小结 - 13 -

结论 - 14 -

附件 - 15 -

参考文献 - 16 -


 

第1章概述

1.1 Hello简介

P2P即 From Program to Process,是将源程序hello.c(Program),在OS(比如linux)中进行预处理(cpp处理器),编译(cll),汇编(as)这三个过程,再链接生成可执行文件,得到可执行的hello的过程。

O2O是指在终端中输入“./hello”运行可执行文件,此时shell会为它创建一个新的子进程,为其execve映射虚拟内存,程序完成之后,shell父进程回收子进程恢复原本的hello进程,这就是O2O的过程

1.2 环境与工具

硬件:Intel Core i5,6G RAM 1T HDD

软件:Windows10,Ubuntu 18.04.1

开发与调试工具:gedit、vim、gcc、edb、readelf、hexedit


1.3 中间结果

列出你为编写本论文,生成的中间结果文件的名字,文件的作用等。

hello.c :用C语言编写的hello程序源代码hello.i :  hello.c经预处理处理得到的文本文件hello.s :编译hello.i后得到的汇编代码hello.o :汇编hello.s后得到的可重定位目标执行文件hello :  hello.o链接后得到的二进制文件

1.4 本章小结

本章中简单的用文字介绍了P2P和O2O的整个过程,并介绍了即将运用的开发工具和所处的开发环境。

(第1章0.5分)



第2章预处理

2.1 预处理的概念与作用

概念:在进行编译之前,将hello.c首先翻译成一个由ASCII码构成的中间文件hello.i,预处理会从宏定义(#define),源文件包含(#include),条件编译(#if  #ifdef  #ifndef  #else  #elif  #endif)等方面进行。主要处理那些用“#”开头的指令。

作用:预处理指令一般被用来使源代码在不同的执行环境中被方便的修改或者编译。

2.2在Ubuntu下预处理的命令


图2-2-1预处理命令行


图2-2-2  hello.i打开图(部分)




图2-2-3  hello.i打开图(部分)

2.3 Hello的预处理结果解析

预处理之后的文件达到了3042行,源文件中的代码出现在在文件的末尾,头文件被引入,以“#”起始的行被展开,文件开头的注释“// 大作业的 hello.c 程序”等等内容被删除。

2.4 本章小结

本章中介绍了预处理的基本概念和作用,介绍了hello.c的预处理命令,给出了预处理后文件的部分截图,并且对hello.i进行了简单的分析


(第2章0.5分)

第3章编译

3.1 编译的概念与作用

概念:利用编译程序从源语言(C语言)编写的源程序产生目标程序(汇编语言程序)的过程, 编译程序把一个源程序翻译成目标程序的工作过程分为五个阶段:词法分析语法分析;语义检查和中间代码生成代码优化目标代码生成。

在本文中可以解释成检查hello.i是否有错误,无错误将其翻译成汇编语言,生成hello.s。

作用:在本文中是将源代码转换称为汇编代码

注意:这儿的编译是指从.i到 .s 即预处理后的文件到生成汇编语言程序

3.2 在Ubuntu下编译的命令


图3-2-1编译的命令行


3.3 Hello的编译结果解析

下面的图是按照顺序将hello.s的各部分截图粘贴


图3-3-1

file:源文件名

.text:代码段

.section  .rodata:rodata节

.align:对齐方式

.global全局变量

.string:字符串

.type:指定对象类型或函数类型




图3-3-2

①汇编语言中各种数据是通过立即数的形式存储的。比如在上图中可以看出main函数的参数argc在%edi内保存,储存在-20(%rbp)内 。

使用了加载有效地址指令leaq计算LC1的段地址%rip+.LC1并传递给%rdi

部分比较argc和4的大小,相等就跳到L2继续程序,不相等则执行下一步程序【源代码中if(argc!=4)的部分】。

调用printf()函数。

把返回值设定为1(说明存在异常),并且调用exit()函数退出程序,给exit()函数传入的参数值是1。





图3-3-3

⑥给i赋值为0,并保存在-4(%rbp)内,然后执行L3部分的程序


图3-3-4

调用printf()函数

调用atoi()函数

调用sleep()函数

i=i+1实现源代码中的i++



图3-3-5


(11)

判断i和7的关系,如果i小于等于7,则执行L4的代码。从而实现了循环功能【源代码中for(i=0;i<8;i++)的部分】

(12)

调用getchar()函数。

(13)

设置返回值为0,退出程序。


图3-3-6




3.4 本章小结

本章主要讲述了编译的作用和概念,hello.s汇编代码的生成方法和具体内容,并且对hello.s中汇编语言是如何表示高级语言的做了简单的分析。


(第3章2分)

第4章汇编

4.1 汇编的概念与作用

概念:as(编译器)把汇编语言代码翻译成和它相对应的机器语言指令,并且这些指令将被打包成为可重定位目标文件,这个过程就是汇编。

作用:把汇编语言转换成机械语言以供计算机识别

注意:这儿的汇编是指从.s到 .o 即编译后的文件到生成机器语言二进制程序的过程。

4.2 在Ubuntu下汇编的命令


图4-2-1汇编的指令行

分析hello.o的ELF格式,用readelf等列出其各节的基本信息,特别是重定位项目分析。

4.3 可重定位目标elf格式

图4-3-1 elf文件头





图4-3-2 hello.o各节的详细信息


图4-3-3 hello.o的可重定位信息


图4-3-4 hello.o的各节基本信息

由上面的图我们可以看出hello.o文件是可重定位文件,采用补码和小端存储。

ELF头(图4-3-1)包括类别(Class),数据(Data),机器类型(Machine),入口点地址(Start of program headers),程序头起点地址(Start of section headers),本头大小,节头部大小等信息。

4.4 Hello.o的结果解析

以下格式自行编排,编辑时删除

objdump -d -r hello.o分析hello.o的反汇编,并请与第3章的 hello.s进行对照分析。

说明机器语言的构成,与汇编语言的映射关系。特别是机器语言中的操作数与汇编语言不一致,特别是分支转移函数调用等。



图4-4 hello.o的反汇编

①机器语言是二进制的机器指令,机器指令由操作码和操作数组成。

②每一条汇编语言都有一条机器语言和它相对应,反之亦然。

③不同之处的分析:

[if !supportLists](1)[endif]hello.s中立即数采用10进制形式,hello.o的反汇编中采用16进制

[if !supportLists](2)[endif]分支转移:hello.o的反汇编中用指令地址代替L1,L2等跳转目标的名称。

[if !supportLists](3)[endif]函数调用:hello.s中调用函数使用函数的名称,hello.o的反汇编中函数调用的目标是一个指令地址。

[if !supportLists](4)[endif]hello.o的反汇编中全局变量和常量已经被存在一个具体的地址里,调用时在具体的地址里存取。

4.5 本章小结

介绍了汇编的基本概念和作用,以及将hello.s汇编成为hello.o的方法。分析了hello.o的ELF格式,查看了各节的信息和hello.o的可重定位信息。

列出了hello.o的反汇编文件内容,分析了机器语言和汇编语言的关系。对比探讨了hello.s与hello.o的区别。

(第4章1分)

5链接

5.1 链接的概念与作用

以下格式自行编排,编辑时删除

概念:将各种代码和数据片段收集并组合成为一个可以在终端下“./文件名”执行的单一的文件的过程

作用:把各个代码和数据片段整合,得到一个可以执行的文件。

注意:这儿的链接是指从hello.o到hello生成过程。

5.2 在Ubuntu下链接的命令

以下格式自行编排,编辑时删除


图5-2-1链接指令


图5-2-2链接后的文件夹

图中hello就是链接成的文件

5.3 可执行目标文件hello的格式

分析hello的ELF格式,用readelf等列出其各段的基本信息,包括各段的起始地址,大小等信息。



图5-3-1 elf文件头信息















图5-3-2 elf节基本信息

由上面的图可以看出hello属于可执行文件,使用补码和小端存储。

5.4 hello的虚拟地址空间  

使用edb加载hello,再Plugins - SymbolViewer就可以查看本进程的虚拟地址空间的信息。

比如说


图纸中红线标出地方对比

我们可以的发现两者显示的init段的起始地址均为0x0000000000401000,是相同的。

再比如

对比,发现rodata的起始地址也是相同的。



5.5 链接的重定位过程分析

以下格式自行编排,编辑时删除

objdump -d -r hello分析hello与hello.o的不同,说明链接的过程。

结合hello.o的重定位项目,分析hello中对其怎么重定位的。

5.6 hello的执行流程

以下格式自行编排,编辑时删除

使用edb执行hello,说明从加载hello到_start,到call main,以及程序终止的所有过程。请列出其调用与跳转的各个子程序名或程序地址。

加载hello之后,首先运行一段程序如下:



然后最后的跳转指令中储存的是_start的地址0x0000000000401090,再运行如下程序:



调用函数到达main函数。

执行main函数,本程序中途会进入exit()函数,运行exit()函数程序终止。


从加载hello到_start:




跳转到*%R12


_start到main调用和跳转的子程序:



5.7 Hello的动态链接分析


程序编译时会采用两种表进行辅助,一个为PLTT表,一个为GOT表,PLT表可以称为内部函数表,GOT表为全局函数表(也可以说是动态函数表这是个人自称),这两个表是相对应的,PLT表中的数据就是GOT表中的一个地址,可以理解为一定是一一对应的。

在dl_init前,初始时每个GOT条目都指向对应的PLT条目的第二条指令。

dl_init后数据应该有改变但是本程序edb时无法执行到那一步

5.8 本章小结

本小节中介绍了hello可执行文件的相关信息,链接生成可执行文件的过程以及它的反汇编语言。


(第5章1分)


6hello进程管理

6.1 进程的概念与作用


概念:进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。进程是正在运行的程序的实例。

作用:从理论角度看,是对正在运行的程序过程的抽象;

从实现角度看,是一种数据结构,目的在于清晰地刻画动态系统的内在规律,有效管理和调度进入计算机系统主存储器运行的程序


6.2 简述壳Shell-bash的作用与处理流程

Shell是用户和操作系统之间完成交互式操作的一个接口程序。

bash是Linux操作系统的默认shell程序。

处理流程:

[if !supportLists](1)[endif]判断收到的是否是内置命令

[if !supportLists](2)[endif]是则解析命令行

[if !supportLists](3)[endif]不是判断是否要打开某个程序

[if !supportLists](4)[endif]搜索路径里没有目标程序则报错


6.3 Hello的fork进程创建过程

Shell调用fork()函数,父进程创建一个子进程,hello的打开是在子进程内进行,子进程不完全但是几乎是和父进程相同的,子进程得到的是父进程虚拟空间的一个副本,这个副本内包含代码段,数据段,malloc,共享区域,用户栈等等和父进程虚拟空间相同的内容。且这个子进程还得到了父进程中打开文件的副本。子进程和父进程唯一的不同是PID。

6.4 Hello的execve过程

shell会调用execve()函数,在创建好的子进程里面加载hello程序,并且允许它进行操作,这个函数把hello的.data节,.bss节等部分的内容都加载到了fork出的子程序的虚拟空间内

6.5 Hello的进程执行

Linux系统的每个程序运行时,一定是处于一个进程的上下文当中的,shell运行hello时,父进程生成一个子进程,它几乎与父进程一样,子进程再由shell调用execve把hello的数据内容载入到子进程的虚拟内存当中。新产生的代码段和数据段经过虚拟内存映射成为可执行文件的内容,然后hello就能够被执行了。

6.6 hello的异常与信号处理


异常种类:中断、终止、故障。

可能出现SIGSTP,SIGINT故障


6.7本章小结

简单介绍了进程的概念和作用,以及Shell-bash和hello进程运行的相关内容,以及hello异常和信号处理的内容。

(第6章1分)

7hello的存储管理

7.1 hello的存储器地址空间

逻辑地址是指在计算机体系结构中是指应用程序角度看到的内存单元(memory cell)、存储单元(storage element)、网络主机(network host)的地址。比如hello.o的反汇编里就给出了这样的一些地址

线性地址:是逻辑地址到物理地址变换之间的中间层。在分段部件中逻辑地址是段中的偏移地址,然后加上基地址就是线性地址。

虚拟地址:程序访问存储器所使用的逻辑地址称为虚拟地址,与实地址模式下的分段地址类似,虚拟地址也可以写为“段:偏移量”的形式,这里的段是指段选择器。

物理地址:在存储器里以字节为单位存储信息,为正确地存放或取得信息,每一个字节单元给以一个唯一的存储器地址,称为物理地址(Physical Address),又叫实际地址或绝对地址。

7.2 Intel逻辑地址到线性地址的变换-段式管理

段式管理是将逻辑地址直接转换成物理地址,在段式存储管理中,将程序的地址空间划分为若干个段(segment),这样每个进程有一个二维的地址空间。在前面所介绍的动态分区分配方式中,系统为整个进程分配一个连续的内存空间。而在段式存储管理系统中,则为每个段分配一个连续的分区,而进程中的各个段可以不连续地存放在内存的不同分区中。程序加载时,操作系统为所有段分配其所需内存,这些段不必连续,物理内存的管理采用动态分区的管理方法。

7.3 Hello的线性地址到物理地址的变换-页式管理

页式管理是一种内存空间存储管理的技术,页式管理分为静态页式管理和动态页式管理。将各进程的虚拟空间划分成若干个长度相等的页(page),页式管理把内存空间按页的大小划分成片或者页面(page frame),然后把页式虚拟地址与内存地址建立一一对应页表,并用相应的硬件地址变换机构,来解决离散地址变换问题。页式管理采用请求调页或预调页技术实现了内外存存储器的统一管理。

7.4 TLB与四级页表支持下的VA到PA的变换


7.5 三级Cache支持下的物理内存访问

cache就是高速缓存,是为了调和CPU得过快访问速度和内存过慢的速度的一个硬件,现代计算机一般都有三级高速缓存,L1、L2、L3,访问速度依次递减。

读取信息的时候一般先访问一级cache,若没有所需数据则向二级cache调用,二级cache没有则向三级cache调用,三级cache向内存调用数据。

7.6 hello进程fork时的内存映射

在shell给hello创建子进程的时候,内核为这个子进程分配了一个唯一的PID,并且创建了各种数据结构。然后创建当前进程的的mm_struct, vm_area_struct和页表的原样副本。将每个页面都标记为只读且每个区域结构(vm_area_struct)都标记为私有的写时复制(COW)。

7.7 hello进程execve时的内存映射

execve的过程中,加载并且运行包含在当前可执行目标文件中,属于hello的程序。

通过删除目前已有的子进程用户区数据,映射私有区域,利用hello的代码段,数据段,bss段等等创建新的区域结构,再映射共享区域的内容,最后设置一个指向hello程序的代码的入口处的程序计数器,就可以执行了。

7.8 缺页故障与缺页中断处理

缺页中断就是要访问的页不在主存,需要操作系统将其调入主存后再进行访问。在这个时候,被内存映射的文件实际上成了一个分页交换文件。


产生缺页中断的几种情况:


1、当内存管理单元(MMU)中确实没有创建虚拟物理页映射关系,并且在该虚拟地址之后再没有当前进程的线性区(vma)的时候,可以肯定这是一个编码错误,这将杀掉该进程;


2、当MMU中确实没有创建虚拟页物理页映射关系,并且在该虚拟地址之后存在当前进程的线性区vma的时候,这很可能是缺页中断,并且可能是栈溢出导致的缺页中断;


3、当使用malloc/mmap等希望访问物理空间的库函数/系统调用后,由于linux并未真正给新创建的vma映射物理页,此时若先进行写操作,将和2产生缺页中断的情况一样;若先进行读操作虽然也会产生缺页异常,将被映射给默认的零页,等再进行写操作时,仍会产生缺页中断,这次必须分配1物理页了,进入写时复制的流程;


[if !supportLists]4、[endif]当使用fork等系统调用创建子进程时,子进程不论有无自己的vma,它的vma都有对于物理页的映射,但它们共同映射的这些物理页属性为只读,即linux并未给子进程真正分配物理页,当父子进程任何一方要写相应物理页时,导致缺页中断的写时复制。

当进程执行过程中发生缺页中断时,需要进行页面换入,步骤如下:


<1>首先硬件会陷入内核,在堆栈中保存程序计数器。大多数机器将当前指令的各种状态信息保存在CPU中特殊的寄存器中。


<2>启动一个汇编代码例程保存通用寄存器及其它易失性信息,以免被操作系统破坏。这个例程将操作系统作为一个函数来调用。


(在页面换入换出的过程中可能会发生上下文换行,导致破坏当前程序计数器及通用寄存器中本进程的信息)


<3>当操作系统发现是一个页面中断时,查找出来发生页面中断的虚拟页面(进程地址空间中的页面)。这个虚拟页面的信息通常会保存在一个硬件寄存器中,如果没有的话,操作系统必须检索程序计数器,取出这条指令,用软件分析该指令,通过分析找出发生页面中断的虚拟页面。


<4>检查虚拟地址的有效性及安全保护位。如果发生保护错误,则杀死该进程。


<5>操作系统查找一个空闲的页框(物理内存中的页面),如果没有空闲页框则需要通过页面置换算法找到一个需要换出的页框。


<6>如果找的页框中的内容被修改了,则需要将修改的内容保存到磁盘上,此时会引起一个写磁盘调用,发生上下文切换(在等待磁盘写的过程中让其它进程运行)。


(注:此时需要将页框置为忙状态,以防页框被其它进程抢占掉)


<7>页框干净后,操作系统根据虚拟地址对应磁盘上的位置,将保持在磁盘上的页面内容复制到“干净”的页框中,此时会引起一个读磁盘调用,发生上下文切换。


<8>当磁盘中的页面内容全部装入页框后,向操作系统发送一个中断。操作系统更新内存中的页表项,将虚拟页面映射的页框号更新为写入的页框,并将页框标记为正常状态。


<9>恢复缺页中断发生前的状态,将程序指令器重新指向引起缺页中断的指令。


<10>调度引起页面中断的进程,操作系统返回汇编代码例程。


<11>汇编代码例程恢复现场,将之前保存在通用寄存器中的信息恢复

7.9动态存储分配管理

以下格式自行编排,编辑时删除

Printf会调用malloc,请简述动态内存管理的基本方法与策略。

1)首次适应:首次适应策略要求空闲区按其起始地址从小到大排列,当某一用户作业要求装入内存时,存储分配程序从起始地址最小的空间区开始扫描,直到找到满足该作业要求的空闲区为止。


2)循环首次适应:在查找空闲区时,不再每次从链首开始查找,而是从上一次找到的空闲区的下一个空闲区开始查找,直到找到一个能满足要求的空闲区为止,并从中划出一块与请求大小相等的内存空间分给该作业。


3)最佳适应:该策略总是把满足要求,又使最小的空闲区分配给请求作业,即在空闲区表中,按空闲区的大小从小到大排列,建立索引,当用户作业请求内存空间时,从索引表中找到第一个满足该作业的空闲区分给它。


4)最差适应:该策略总是把最大的空闲区分配给请求作业,空闲区表(空闲区链)中的空闲分区要按大小从大到小进行排序,自表头开始查找到第一个满足要求的空闲分区分配给作业。

7.10本章小结

本小节主要介绍了hello在执行时,有关储存的管理的各项相关内容。

 

(第7章 2分)

8hello的IO管理

8.1 Linux的IO设备管理方法

设备的模型化:文件

设备管理:unix io接口

8.2 简述Unix IO接口及其函数

Unix IO接口是连接CPU与外设之间的部件,它完成CPU与外界的信息传送。还包括辅助CPU工作的外围电路,如中断控制器、DMA控制器、定时器、高速CACHE。

它最重要的四个函数,打开open,关闭close,读取read,写入write

8.3 printf的实现分析

从vsprintf生成显示信息,到write系统函数,到陷阱-系统调用 int 0x80或syscall.

字符显示驱动子程序:从ASCII到字模库到显示vram(存储每一个点的RGB颜色信息)。

显示芯片按照刷新频率逐行读取vram,并通过信号线向液晶显示器传输每一个点(RGB分量)。

8.4 getchar的实现分析

异步异常-键盘中断的处理:键盘中断处理子程序。接受按键扫描码转成ascii码,保存到系统的键盘缓冲区。

getchar等调用read系统函数,通过系统调用读取按键ascii码,直到接受到回车键才返回。

8.5本章小结

本小节介绍了Linux的IO设备,接口和接口函数,以及prinf和getchar实现过程

(第8章1分)

结论

Hello.c从被编写出来到执行,经历了下面的这些流程:

[if !supportLists](1) [endif]预处理器将hello.c预处理成为hello.i 

[if !supportLists](2) [endif]编译器将hello.i翻译成汇编语言hello.s

[if !supportLists](3) [endif]汇编器将hello.s汇编成可重定位二进制代码hello.o

[if !supportLists](4) [endif]链接器将外部文件和hello.o链接成为可执行二进制文件hello

[if !supportLists](5) [endif]shell进程调用fork为其创建子进程.

[if !supportLists](6) [endif]shell调用execve函数使得hello的数据写入子进程的虚拟内存空间,从而使得hello的代码可以在一个可执行文件中被执行。


如今的电脑程序运行速度主要受限制于读取的速度,未来如果能够实现cache的更准确命中或者提高cache每一级的容量,可以更好的提升电脑速度。

(结论0分,缺失 -1分,根据内容酌情加分)

附件

hello.i预处理之后文本文件

hello.s编译之后的汇编文件

hello.o汇编之后的可重定位目标执行

Hello链接之后的可执行目标文件

(附件0分,缺失 -1分)

参考文献

为完成本次大作业你翻阅的书籍与网站等

[1]林来兴. 空间控制技术[M]. 北京:中国宇航出版社,1992:25-42.

[2]  辛希孟. 信息技术与信息服务国际研讨会论文集:A集[C]. 北京:中国科学出版社,1999.

[3]赵耀东. 新时代的工业工程师[M/OL]. 台北:天下文化出版社,1998 [1998-09-26]. http://www.ie.nthu.edu.tw/info/ie.newie.htm(Big5).

[4]  谌颖.空间交会控制理论与方法研究[D]. 哈尔滨:哈尔滨工业大学,1992:8-13.

[5]  KANAMORI H. Shaking Without Quaking[J]. Science,1998,279(5359):2063-2064.

[6]  CHRISTINE M. Plant Physiology: Plant Biology in the Genome Era[J/OL]. Science,1998,281:331-332[1998-09-23]. http://www.sciencemag.org/cgi/ collection/anatmorp.

(参考文献0分,缺失 -1分)



`���k�x�κ�

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,542评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,822评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,912评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,449评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,500评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,370评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,193评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,074评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,505评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,722评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,841评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,569评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,168评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,783评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,918评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,962评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,781评论 2 354