2017-2018-1 20155313 《信息安全系统设计基础》第十三周学习总结

2017-2018-1 20155313 《信息安全系统设计基础》第十三周学习总结

本周学习任务

找出全书你认为最重要的一章,深入重新学习一下,要求(期末占10分):

  • 完成这一章所有习题
  • 详细总结本章要点
  • 给你的结对学习搭档讲解你的总结并获取反馈
  • 参考上面的学习总结模板,把学习过程通过博客(随笔)发表,博客标题“学号 《信息安全系统设计基础》第十三周学习总结”,博客(随笔)要通过作业提交,截至时间本周日 23:59。

  • 我认为本书最重要的是第九章——虚拟存储器。
  • 虚拟存储器通过软件设计参与到了计算机的硬件运行上,有效地增加了计算机的运行效率且合理地分配了计算机的硬件任务,是现代计算机体系中十分重要的内容。
  • 本章的核心内容是理解虚拟存储器其运行的原理。

任务1:

  • 完成这一章所有习题

  • 重点学习例题:
练习题9.1
虚拟地址位数(n)虚拟地址数 (N)最大可能的虚拟地址
82^8^ = 2562^8^-1 = 255
162^16^ = 64K2^16^-1 = 64K-1
322^32^ = 4G2^32^-1 = 4G-1
482^48^ = 256T2^48^-1 = 256T-1
642^64^ = 16384P2^64^-1 = 16384P-1

练习题9.2
nP =2^p^PTE的数量
164K16
168K8
324K1M
328K512K

练习题9.3
PVPN位数VPO位数PPN位数PPO位数
1KB22101410
2KB21111311
4KB20121212
1KB19131113

练习题9.4

虚拟地址:0x03d7

A.虚拟地址格式

  • 00 0011 1101 0111

B.地址翻译

参数
VPN0xf
TLB索引0x3
TLB标记0x3
TLB命中?(是/否)
缺页?(是/否)
PPN0xd

C.物理地址格式

  • 0011 0101 0111

D.物理内存引用

参数
CO0x3
CI0x5
CT0xd
高度缓存命中?(是/否)
告诉缓存字节返回0x1d

练习题9.6
请求块大小(十进制字节)块头部(十六进制)
malloc(1)80x9
malloc(5)160x11
malloc(12)160x11
malloc(13)240x19

练习题9.7
对其要求已分配块空闲块最小块大小(字节)
单字头部和脚部头部和脚部12
单字头部,没有脚部头部和脚部8
双字头部和脚部头部和脚部16
双字头部,没有脚部头部和脚部8

任务2:

  • 详细总结本章要点
全章内容纲要
  • 虚拟存储器(virtual memory, VM)是计算机系统一种对主存的抽象概念。本章首先讲解虚拟存储器是如何工作的,之后讲解应用程序如何使用和管理虚拟存储器。
  • 1.物理寻址和虚拟寻址:物理寻址是CPU直接生成物理地址返回物理内存,虚拟寻址是CPU生成虚拟地址经地址翻译后转化为物理地址对其进行寻址。
  • 2.虚拟存储器作为缓存的工具:
  • 1)虚拟存储器被组织为存放在磁盘上的N个连续的字节大小的数组。VM系统通过将虚拟存储器分割为称为虚拟页的大小固定的块来处理。任意时刻,虚拟页面的集合分为三种:未分配的、缓存的、未缓存的。
  • 2)虚拟页与物理页(内存/主存)的缓存关系由页表来维持,页表就是一个页表条目(Pagetable entry,PTE),将虚拟页映射到物理页。
  • 3)简单的讲解了虚拟存储器页命中、缺页、页面分配的基本处理流程,以及因为程序局部性而保证虚拟存储器系统能高效工作的原理。
  • 3.虚拟存储器作为存储器管理的工具:实际上,操作系统为每个进程提供了一个独立的页表,因为也就是一个独立的虚拟地址空间。
  • 1)简化链接:独立的地址空间允许每个进程的存储器映像使用相同的基本格式,而不管代码的数据实际存放在物理存储器的何处。
  • 2)简化加载:简单的来说exec类函数可以方便的执行,操作系统只需要更改适当修改页表条目。同时,还为存储器映射(将一个虚拟页映射到任意一个文件中的任意位置)提供可能:mmap。
  • 3)简化共享。
  • 4)简化存储器的分配:malloc类函数
  • 4.虚拟存储器作为存储器保护的工具:通过在PTE(页表条目)上添加一些额外的许可位可控制程序对相关虚拟页的访问权限。
  • 5.地址翻译。
  • 6.Linux存储器系统,也就是linux内存管理。
  • 7.动态存储器分配。讲解了linux系统malloc/free类函数的实现原理,并配有小的实践代码。
  • 8.垃圾回收:C语言不存在垃圾回收,malloc分配的存储空间需要程序员显式释放。主要讲解了垃圾回收的原理。
  • 9.C程序中常见的与存储器有关的错误:空指针、野指针、越界、泄漏等。

  • 进程提供给应用程序的关键抽象:
  • 一个独立的逻辑控制流,它提供一个假象,好像我们的程序独占地使用处理器。
  • 一个私有的地址空间,它提供一个假象,好像我们的程序独占地使用存储器系统。

虚拟存储器
  • 硬件地址翻译、主存、磁盘文件和内核软件的完美交互,它为每个进程提供了一个大的、一致的和私有的地址空间。通过一个很清晰的机制,虚拟存储器提供了三个重要的能力:
  • (1)它将主存看成是一个存储在磁盘上的地址空间的高速缓存,在主存中只保存活动区域,并根据需要在磁盘和主存之间来回传送数据, 通过这种方式,它高效地使用了主存。
  • (2)它为每个进程提供了一致的地址空间, 从而简化了存储器管理。
  • (3)它保护了每个进程的地址空间不被其他进程破坏。

物理和虚拟寻址
物理寻址
  • 计算机系统的主存被组织成一个由M个连续的字节大小的单元组成的数组。每字节都有一个唯一的物理地址(Physical Address,PA)。第一个字节的地址为0,接下来的字节的地址为1,再下一个为2,依此类推。给定这种简单的结构,CPU访问存储器的最自然的方式就是使用物理地址,我们把这种方式称为物理寻址。
虚拟寻址
  • 使用虚拟寻址时,CPU通过生成一个虚拟地址(Virtual Address,VA)来访问主存,这个虚拟地址在被送到存储器之前先转换成适当的物理地址。将一个虚拟地址转换为物理地址的任务叫做地址翻译(address translation)。就像异常处理一样,地址翻译需要CPU硬件和操作系统之间的紧密合作。CPU芯片上叫做存储器管理单元(Memory Management Unit,MMU)的专用硬件,利用存放在主存中的查询表来动态翻译虚拟地址,该表的内容是由操作系统管理。

1071530-20171217173142046-653913059.png


地址空间
  • 地址空间(adress space)是一个非整数地址的有序集合:{0,1,2,...}
  • 如果地址空间中的整数是连续的,那么我们说它是一个线性地址空间(linear address space)。在一个带虚拟存储器的系统中,CPU从一个有N = 2^n^个地址空间中生成虚拟地址,这个地址空间称为虚拟地址空间(virtual address space):{0,1,2,3,...,N-1}
  • 一个地址空间的大小是由表示最大地址所需要的倍数来描述的。例如,一个包含N=2^n^个地址的虚拟地址空间叫做一个n位地址空间。现在系统典型地支持32位或者64位虚拟地址空间是。
  • 一个系统还有一个物理地址空间(physical addresss space),它与系统中物理存储器的M字节相对应:{0,1,2,...M-1}
  • M不要求是2的幂,但是为了简化讨论,我们假设M = 2^m^。
  • 地址空间的概念是很重要的,因为它清楚地区分了数据对象(字节)和它们的属性(地址)。一旦认识到了这种区别,那么我们就可以将其推广,允许每个数据对象有多个独立的地址,其中每个地址都选自一个不同的地址空间。这就是虚拟存储器的基本思想。 主存中每个字节都有一个选自虚拟地址空间的虚拟地址和一个选自物理地址空间的物理地址。

1071530-20171217173146983-1821211142.png


地址翻译
  • 地址翻译将虚拟地址翻译为物理地址。虚拟地址被划分为虚拟页号和虚拟页内偏移,虚拟页号用来定位页表中的页表项,页表项中保存着物理页号,也就得到了物理页号。虚拟页偏移和物理页偏移相同。有了物理页号和物理页偏移,就得到了物理地址。

1071530-20171217173151952-638677605.png


虚拟存储器作为缓存的工具
  • 概念上而言,虚拟存储器(VM)被组织为一个由存放在磁盘上N个连续的字节大小的单元组成的数组。每个字节都有一个唯一的虚拟地址,这个唯一的虚拟地址是作为到数组的索引的。磁盘上的数组的内容被缓存在主存中。和存储器层次结构中其他缓存一样,磁盘(较低层)上的数据被分割成块,这些块作为磁盘和主存(较高层)之间的传输单元。VM系统通过将虚拟存储器分割称为虚拟页(Vitual Page,VP)的大小固定的块来处理这个问题。每个虚拟页的大小为P = 2^n^字节。类似地,物理存储器被分割为物理页(Physical Page,PP),大小也为P字节(物理页也称为页帧(page frame))。
  • 在任意时刻,虚拟页面的集合都分为三个不相交的子集:
  • 未分配的:VM系统还未分配(或者创建)的页。未分配的块没有任何数据和它们相关联,因此也就不占用任何磁盘空间。(没有调用malloc或者mmap的)
  • 缓存的:当前缓存在物理存储中的已分配页。(已经调用malloc和mmap的,在程序中正在引用的)
  • 未缓存的:没有缓存在物理存储器中的已分配页。(已经调用malloc和mmap的,在程序中还没有被引用的)

1071530-20171217173240327-305756407.png


页表
  • 同任何缓存一样,虚拟存储器系统必须有某种方法来判定一个虚拟页是否存放在DRAM中的某个地方。如果是,系统还必须确定这个虚拟页存放在哪个物理页中。如果不命中,系统必须判断这个虚拟页存放在磁盘的哪个位置,在物理存储器中选择一个牺牲页,并将虚拟页从磁盘拷贝到DRAM中,替换这个牺牲页。
  • 这些功能是由许多软硬件联合提供的,包括操作系统软件,MMU(存储器管理单元)中地址翻译硬件和一个存放在物理存储器中叫做页表(page table)的数据结构,页表将虚拟页映射到物理页。页表就是一个页表条目(Page Table Entry,PTE)的数组。

1071530-20171217173257593-304509872.png


Linux虚拟存储器系统
  • Linux为每个进程维持了一个单独的虚拟地址空间。

1071530-20171217173302499-1196385012.png

  • 内核虚拟存储器包含内核中的代码和数据结构。内核虚拟存储器的某些区域被映射到所有进程共享的物理页面。例如,每个进程共享内核的代码和全局数据结构。

Linux虚拟存储器区域(Windows下也有区域的概念)
  • Linux将虚拟存储器组织成一些区域(也叫做段)的集合。一个区域(area)就是已经存在着的(已分配的)虚拟存储器的连续片(chunk),这些页是以某种方式相关联的。例如,代码段、数据段、堆、共享库段,以及用户栈都不同的区域。每个存在的虚拟页面保存在某个区域中,而不属于某个区域的虚拟页是不存在的,并且不能被进程引用。区域的概念很重要,因为它允许虚拟地址空间有间隙。内核不用记录那些不存在的虚拟页,而这样的页也不占用存储器。磁盘或者内核本身的任何额外资源。
  • 内核为系统中的每个进程维护一个单独的任务结构(源代码中的task_struct)。任务结构中的元素包含或者指向内核运行该进程所需要的所有信息(例如,PID,指向用户栈的指针、可执行的目标文件的名字以及程序计数器)。

1071530-20171217173310155-875187239.png

  • task_struct中的一个条目指向mm_struct,它描述了虚拟存储器中的当前状态。其中pgd指向第一级页表(页全局目录)的基址,而mmap指向一个vm_area_struct(区域结构)的链表,其中每个vm_area_structs都描述了当前虚拟地址空间的一个区域(area)。当内核运行这个进程时,它就将pgd存放在CR3控制寄存器中。
    一个具体区域结构包含下面的字段:
  • vm_start:指向这个区域的起始处。
  • vm_end:指向这个区域的结束处。
  • vm_prot:描述这个区域的内包含的所有页的读写许可权限。
  • vm_flags:描述这个区域内页面是与其他进程共享的,还是这个进程私有的(还描述了其他一些信息)。
  • vm_next:指向链表中下一个区域结构。

存储器映射(Windows下也有类似的机制,名叫内存映射)
  • Linux(以及其他一些形式的Unix)通过将一个虚拟存储器区域与一个磁盘上的对象(object)关联起来,以初始化这个虚拟存储器区域的内容,这个过程称为存储器映射(memory mapping)。虚拟存储器区域可以映射到两种类型的对象的一种:
  • (1)Unix文件上的普通文件:一个区域可以映射到一个普通磁盘文件的连续部分,例如一个可执行目标文件。文件区(section)被分成页大小的片,每一片包含一个虚拟页面的初始化内容。因为按需进行页面高度,所以这些虚拟页面没有实际进行物理存储器,直到CPU第一次引用到页面(即发射一个虚拟地址,落在地址空间这个页面的范围之内)。如果区域文件区要大,那么就用零来填充这个区域的余下部分。
  • (2)匿名文件:一个区域也可以映射到一个匿名文件,匿名文件是由内核创建的,包含的全是二进制零。CPU第一次引用这样一个区域内的虚拟页面时,内核就在物理存储器中找到一个合适的牺牲页面,如果该页面被修改过,就将这个页面换出来,用二进制零覆盖牺牲页面并更新页表,将这个页面标记为是驻留在存储器中的。注意在磁盘和存储器之间没有实际的数据传送。因为这个原因,映射到匿名文件的区域中的页面有时也叫做请求二进制零的页(demand-zero page)。
  • 无论在哪种情况下,一旦一个虚拟页面被初始化了, 它就在一个由内核维护的专门的交换文件(swap file)之间换来换去。交换文件也叫做交换空间(swap space)或者交换区域(swap area)。需要意识到的很重要的一点,在任何时刻,交换空间都限制着当前运行着的进程能够分配的虚拟页面的总数。

共享对象
  • 一个对象可以被映射到虚拟存储的一个区域,要么作为共享对象,要么作为私有对象。如果一个进程将一个共享对象映射到它的虚拟地址空间的一个区域内,那么这个进程对这个区域的任何写操作,对于那些也把这个共享对象映射到它们虚拟存储器的其他进程而言也是可见的。而且,这此变化也会反映在磁盘上的原始对象中。(IPC的一种方式)
  • 另一方面,对一个映射到私有对象的区域做的改变,对于其他进程来说是不可见的,并且进程对这个区域所做的任何写操作都不会反映在磁盘上的对象中。一个映射到共享对象的虚拟存储器区域叫做共享区域。类似地,也有私有区域。

  • 共享对象的关键点在于即使对象被映射到了多个共享区域,物理存储器也只需要存放共享对象的一个拷贝。
    一个共享对象(注意,物理页面不一定是连续的。)

1071530-20171217173325671-2024952932.png

  • 私有对象是使用一种叫做写时拷贝(copy-on-write)的巧妙技术被映射到虚拟存储器中的。对于每个映射私有对象的进程,相应私有区域的页表条目都被标记为只读,并且区域结构被标记为私有的写时拷贝。

1071530-20171217173329796-1869944700.png


fork函数
  • 当fork函数被当前进程调用时,内核为新进程创建各种数据结构,并分配给它一个唯一的PID。为了给这个新进程创建虚拟存储器,它创建了当前进程的mm_struct、区域结构和页表的原样拷贝。它将两个进程中的每个页面都为标记只读,并将两个进程中的每个区域结构都标记为私有的写时拷贝。
  • 当fork在新进程中返回时,新进程现在的虚拟存储器刚好和调用fork时存在的虚拟存储器相同。当这两个进程中的任一个后来进行写操作时,写时拷贝机制就会创建新页面,因此,也就为每个进程保持了私有地址空间的抽象概念。
execve函数
  • 假设运行在当前进程中的程序执行了如下的调用:
  • execve("a.out",NULL,NULL) ;
  • execve函数在当前进程中加载并运行包含在可执行目标文件a.out中的程序,用a.out程序有效地替代了当前程序。加载并运行a.out需要以下几个步骤:
  • 删除已存在的用户区域。删除当前进程虚拟地址用户部分中的已存在的区域结构。
  • 映射私有区域。为新程序的文本、数据、bss和栈区域创建新的区域结构。所有这些新的区域都是私有的、写时拷贝的。文本和数据区域被映射为a.out文件中的文本和数据区。bss区域是请求二进制零的,映射到匿名文件,其大小包含在a.out中。栈和堆区域也是请求二进制零的。
  • 映射共享区域。如果a.out程序与共享对象(或目标)链接,比如标准C库libc.so,那么这些对象都是动态链接到这个程序的,然后再映射到用户虚拟地址空间中的共享区域内。
  • 设置程序计数器(PC)。execve做的最后一件事情就是设置当前进程上下文中的程序计数器,使之指向文本区域的入口点。

使用mmap函数的用户级存储器映射


#include <unistd.h>  
#include <sys/mman.h>  
  
  
void *mmap(void *start,size_t length,int prot,int flags,int fd,off_t offset) ;  
                //返回:若成功时则为指向映射区域的指针,若出错则为MAP_FAILED(-1) 
  • mmap函数要求内核创建一个新的虚拟存储器区域是,最好是从地址start开始的一个区域,并将文件描述符fd指定的对象的一个连续的片(chunk)映射到这个新区域。连续的对象片大小为length字节,从距文件开始处偏移量为offset字节的地方开始。start地址仅仅是一个暗示,通常被定义为NULL。
//munmap函数删除虚拟存储器的区域:  

#include <unistd.h>  
#include <sys/mman.h>  
  
  
int munmap(void *start,size_t length);  
    //返回:若成功则为0,若出错则为-1  

  • 1、需要额外的虚拟存储器时,使用一种动态存储器分配器(dynamic memory allocator)。一个动态存储器分配器维护着一个进程的虚拟存储器区域,称为堆(heap)。在大多数的unix系统中,堆是一个请求二进制0的区域;对于每个进程,内核维护着一个变量brk,它指向堆的顶部。

1071530-20171217173345077-1475583057.png

  • 2、分配器将堆视为一组不同大小的块(block)的集合来维护。每个块就是一个连续的虚拟存储器组块(chunk),要么是已分配的,要么是未分配的。
  • 1)显式分配器(explicit allocator):如通过malloc,free或C++中通过new,delete来分配和释放一个块。
  • 2)隐式分配器(implicit allocator):也叫做垃圾收集器(garbage collector)。自动释放未使用的已分配的块的过程叫做垃圾回收(garbage collection)。
  • 3、malloc不初始化它返回的存储器,calloc是一个基于malloc的包装(wrapper)函数,它将分配的存储器初始化为0。想要改变一个以前已分配的块的大小,可以使用realloc函数。
  • 4、分配器必须对齐块,使得它们可以保存任何类型的数据对象。在大多数系统中,以8字节边界对齐。
  • 不修改已分配的块:分配器只能操作或者改变空闲块。一旦被分配,就不允许修改或者移动它。
  • 5、碎片(fragmentation)
  • 有内部碎片(internal)和外部碎片(external)。
  • 外部碎片:在一个已分配块比有效载荷在时发生的。(如对齐要求,分配最小值限制等)
  • 外部碎片:当空闲存储器合计起来足够满足一个分配请求,但是没有一个单独的空闲块足够大可以来处理这个请求时发生的。
  • 6、隐式空间链表

1071530-20171217173352093-1918053206.png

1071530-20171217173355952-1719796819.png

  • 放置分配的块的策略有:首次适配(first fit),下一次适配(next fit),和最佳适配(best fit)。
  • 如果空闲块已经最大程度的合并,而仍然不能生成一个足够大的块,来满足要求的话,分配器就会向内核请求额外的堆存储器,要么是通过调用nmap,要么是通过调用sbrk函数;分配器都会将额外的(增加的)存储器转化成一个大的空闲块,将这个块插入到空闲链表中,然后将被请求的块放置在这个新的空闲块中。
  • 7、书中对分配器的设计举了一个小例子,10.9.12节。
  • 8、一种流行的减少分配时间的方法,称为分离存储(segregated storage),维护多个空闲链表,其中每个链表中的块有大致相等的大小。

垃圾收集
  • 垃圾收集器是一种动态存储分配器,自动释放程序不再需要的已分配块(垃圾)。支持垃圾收集的系统中,应用显式分配堆块,但从不显式释放它们。
  • 垃圾收集器将存储器视为一个有向可达图,节点分为根节点和堆节点,堆节点对应堆中的已分配块,根节点对应包含指向堆中的指针但不在堆中的位置,如寄存器、栈里的变量、虚拟存储器中读写数据区域内的全局变量。当存在根节点到p的有向路径时,称p是可达的,不可达节点无法被应用再次使用,即为垃圾。
  • Java等语言对于创建和使用指针有严格的控制,能够回收所有垃圾。C/C++语言的垃圾收集器通常不能维护可达图的精确表示,称为保守的垃圾收集器,它不能回收所有垃圾。

和存储器有关的错误
  • 在使用C语言和虚拟存储器打交道时,很容易犯一些错误,而且它们常常是致命的。
  • 间接引用坏指针。间接引用指向空洞或只读区域的指针,会造成段异常或保护异常而终止。
  • 读未初始化的存储器。.bss存储器位置总是被加载器初始化为0,但堆存储器不是这样,假定它为0会造成不可预料的结果。
  • 允许栈缓冲区溢出。不检查串的大小就写入栈中的目标缓冲区可能会有缓冲区溢出错误。
  • 假设指针和指向的对象大小相同。这可能会导致分配器的合并代码失败,但没有明显的原因。
  • 造成错位错误。如超出循环造成覆盖错误。
  • 引用指针,而不是指向的对象。
  • 误解指针运算。指针的算术操作是以指向的对象的大小为单位进行的,而不是字节。
  • 引用不存在的变量。比如栈中的局部变量,栈弹出后它就不再合法了。
  • 引用空闲堆块中的数据。和上一个类似,这回发生在被释放的堆中。
  • 引起存储器泄漏。忘记释放已分配块,产生垃圾,对于不终止的程序(守护进程、服务器),存储器泄漏的错误非常严重。

任务3:

  • 给你的结对学习搭档讲解你的总结并获取反馈
结对学习照片

1071530-20171217203751014-2139776486.jpg

结对同学博客

2017-2018-1 20155201 《信息安全系统设计基础》第十三周学习总结

我的学习反馈

(S,E,B,m)=(4,1,2,4),即4个组,每个组1行,每个块2个字节,地址是4位。这里假设每个字都是单字节,每次都读1个字。
初始时,高速缓存是空的:

  • a)读地址0的字。因为组0的有效位是0,缓存不命中,所以高速缓存从存储器取出块0,,并存储在组0中。然后高速缓存返回取出的高速缓存行的m[0]。

1071530-20171217202458577-1502558081.png

  • b)读地址1的字。高速缓存命中。

  • c)度地址13的字。

1071530-20171217202527530-145998036.png

  • d)读地址8的字。

1071530-20171217202541296-643345450.png

  • e)读地址0的字。又发生缓存不命中,因为前面引用地址8时,刚好替换了块8。

1071530-20171217202545624-636623162.png


任务4:

  • 参考上面的学习总结模板,把学习过程通过博客(随笔)发表,博客标题“学号 《信息安全系统设计基础》第十三周学习总结”,博客(随笔)要通过作业提交,截至时间本周日 23:59。

实验测试个人解析

1、实验5:使用openssl进行混合密码系统加密时,会话秘钥的分发最可能用到()

  • [x] - A .
    AES_encrypt
  • [x] - B .
    RSA_public_encrypt
  • [ ] - C .
    AES_decrypt
  • [ ] - D .
    RSA_private_decrypt
  • [ ] - E .
    AES_cbc_encrypt
  • [x] - F .
    RSA_private_encrypt
  • [ ] - G .
    RSA_public_decrypt

正确答案:
B、C

答案解析:

非对称算法的应用:

  • 秘钥分发:用对方公钥加密,对方用自己的私钥解密
  • 签名验签:签名主要是用自己私钥加密,对方用自己公钥验签名

测试时我的理解是选择加密的选项,所以就选择了三个en开头的加密类型。


2、实验4:中我们实现的测试程序是()驱动。

  • [ ] - A .
    网络设备
  • [ ] - B .
    字符设备
  • [x] - C .
    块设备
  • [ ] - D .
    以上都不是

正确答案:B

答案解析:

  • 实验中实现了字符设备。
  • 在LINUX里面,设备类型分为:字符设备、块设备以及网络设备, PCI是一种和ISA为一类的总线结构,归属于网络驱动设备~
  • 字符设备、块设备主要区别是:在对字符设备发出读/写请求时,实际的硬件I/O一般就紧接着发生了,而块设备则不然,它利用一块系统内存作为缓冲区,当用户进程对设备请求能满足用户的要求时,就返回请求的数据,如果不能就调用请求函数来进行实际的I/O操作

在实验的笔记提交中我重点摘抄了块设备驱动的内容,所以在考试时就理所当然的选择了块设备,在实验中没有理论与实践相结合地进行学习。


3、实验3:在Ubuntu虚拟机中编译多线程程序时,gcc使用()选项

  • [ ] - A .
    -g
  • [ ] - B .
    -lthread
  • [ ] - C .
    -pthread
  • [x] - D .
    -lpthread

正确答案:C

答案解析:

  • 实际环境中只有-pthread可用

在网络上查找资料的时候看到使用D选项进行编译所以就选择了D。

参考资料:

多线程编程之Linux环境下的多线程(一)


4、实验3:wc的使用中,wc () a.txt 给出a.txt文件的行数。

  • [x] - A .
    -L
  • [ ] - B .
    -l
  • [ ] - C .
    -Ll
  • [ ] - D .
    -c

正确答案:B

答案解析:

  • wc -l统计行数

心急看错了选择大写的L。


5、实验1:使用mount命令时,会涉及到()的修改。

  • [x] - A .
    /etc/fstab
  • [ ] - B .
    /etc/hosts
  • [ ] - C .
    /etc/passwd
  • [ ] - D .
    /etc/exports

正确答案:D

答案解析:

nfs服务器的配置,配置文件/etc/exports:

  • ro 该主机对该共享目录有只读权限

  • rw 该主机对该共享目录有读写权限

root_squash 客户机用root用户访问该共享文件夹时,将root用户映射成匿名用户

no_root_squash 客户机用root访问该共享文件夹时,不映射root用户

all_squash 客户机上的任何用户访问该共享目录时都映射成匿名用户

anonuid 将客户机上的用户映射成指定的本地用户ID的用户

anongid 将客户机上的用户映射成属于指定的本地用户组ID

sync 资料同步写入到内存与硬盘中

async 资料会先暂存于内存中,而非直接写入硬盘

insecure 允许从这台机器过来的非授权访问

这个路径确实在实验的时候没有注意。


6、实验1:Windows 宿主机,Ubuntu虚拟机,ARM实验箱三者IP要在同一网段,操作中是根据()的IP来确定网段的。

  • [ ] - A .
    Windows 宿主机
  • [ ] - B .
    Ubuntu虚拟机
  • [ ] - C .
    ARM实验箱
  • [x] - D .
    以上都可以

正确答案:C

答案解析:

  • ARM实验箱的IP修改要重新烧录Linux系统,Windows 宿主机,Ubuntu虚拟机的IP比较容易修改,所以我们在超级终端中通过ifconfig查看ARM实验箱的IP,把Windows 宿主机,Ubuntu虚拟机的IP改成和ARM实验箱同一个网段。

事实上根据三者任意一者的IP地址确定网段都可以,但是在实验步骤中,通过ARM实验箱的IP地址确定网段比较简单。


7、实验2:有关套接字接口函数open_clientfd()、open_listenfd(),下面说法正确的是()

  • [ ] - A .
    这两个函数中open_clientfd()只可以用于客户端编程
  • [x] - B .
    这两个函数中open_clientfd()可以用于客户端和服务器端编程
  • [ ] - C .
    这两个函数中open_listenfd()只可以用于服务器端编程
  • [x] - D .
    open_clientfd()中的port参数是客户端的端口
  • [ ] - E .
    open_clientfd()中的port参数是服务器端的端口
  • [x] - F .
    open_clientfd()返回的clientfd可以有Unix I/O接口读写
  • [ ] - G .
    open_listenfd()返回的listenfd可以有Unix I/O接口读写

正确答案:A、C、E、F

答案解析:

  • 根据书本p666

clientfd是客户端的socket套接字,其中的端口port参数是根据服务器端的端口来选择的,目的是为了与服务器端建立连接。listen是socket传输中服务器端才有的监听行为。


8、实验2:有关socket接口中的socket(),下面说法正确的是()

  • [x] - A .
    不论客户端编程还是服务器端编程都要调用socket()
  • [x] - B .
    socket()中的type参数设置为SOCK_STREAM时,基于TCP的,数据传输比较有保障
  • [ ] - C .
    socket()中的type参数设置为SOCK_DGRAM时,基于TCP的,数据传输比较有保障
  • [x] - D .
    使用socket()返回的文件描述符通过read(),write()就可以传输数据了
  • [ ] - E .
    socket()中的protocol参数一般设为0
  • [x] - F .
    socket()中的type参数设置为 SOCK_RAW ,允许对底层协议如IP或ICMP进行直接访问
  • [x] - G .
    socket()可用getaddrinfo返回的ai_family,ai_socktype和ai_protocol填充

正确答案:A、B、E、F、G

答案解析:

  • 根据书本p654

socket中的Protocol在TCP传输中一般设为0。


学习进度条

代码行数(新增/累积)博客量(新增/累积)学习时间(新增/累积)重要成长
目标5000行20篇400小时
第一周100/1001/15/5
第二周100/2002/35/10
第三周100/3002/55/15
第四周100/4001/65/20
第六周100/5001/75/25
第七周100/6001/85/30
第八周800/14003/1110/40
第九周1000/24003/1415/55
第十一周300/27002/1620/75
第十三周100/28002/1820/95

代码托管


参考资料

转载于:https://www.cnblogs.com/bonsai/p/8052593.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ava实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),可运行高分资源 Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。下面详细介绍C语言的基本概念和语法。 1. 变量和数据类型 在C语言中,变量用于存储数据,数据类型用于定义变量的类型和范围。C语言支持多种数据类型,包括基本数据类型(如int、float、char等)和复合数据类型(如结构体、联合等)。 2. 运算符 C语言中常用的运算符包括算术运算符(如+、、、/等)、关系运算符(如==、!=、、=、<、<=等)、逻辑运算符(如&&、||、!等)。此外,还有位运算符(如&、|、^等)和指针运算符(如、等)。 3. 控制结构 C语言中常用的控制结构包括if语句、循环语句(如for、while等)和switch语句。通过这些控制结构,可以实现程序的分支、循环和多路选择等功能。 4. 函数 函数是C语言中用于封装代码的单元,可以实现代码的复用和模块化。C语言中定义函数使用关键字“void”或返回值类型(如int、float等),并通过“{”和“}”括起来的代码块来实现函数的功能。 5. 指针 指针是C语言中用于存储变量地址的变量。通过指针,可以实现对内存的间接访问和修改。C语言中定义指针使用星号()符号,指向数组、字符串和结构体等数据结构时,还需要注意数组名和字符串常量的特殊性质。 6. 数组和字符串 数组是C语言中用于存储同类型数据的结构,可以通过索引访问和修改数组中的元素。字符串是C语言中用于存储文本数据的特殊类型,通常以字符串常量的形式出现,用双引号("...")括起来,末尾自动添加'\0'字符。 7. 结构体和联合 结构体和联合是C语言中用于存储不同类型数据的复合数据类型。结构体由多个成员组成,每个成员可以是不同的数据类型;联合由多个变量组成,它们共用同一块内存空间。通过结构体和联合,可以实现数据的封装和抽象。 8. 文件操作 C语言中通过文件操作函数(如fopen、fclose、fread、fwrite等)实现对文件的读操作。文件操作函数通常返回文件指针,用于表示打开的文件。通过文件指针,可以进行文件的定位、读等操作。 总之,C语言是一种功能强大、灵活高效的编程语言,广泛应用于各种领域。掌握C语言的基本语法和数据结构,可以为编程学习和实践打下坚实的基础

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值