精华内容
下载资源
问答
  • Android 系统源码代码情景分析

    千次阅读 2018-02-02 11:22:29
     《Android系统源代码情景分析》是2012年10月出版的图书,作者是罗升阳。  在内容上,本书结合使用情景,全面、深入、细致地分析了Android系统的源代码,涉及到Linux内核层、硬件抽象层(HAL)、运行时库层...




    一、本书简介

        《Android系统源代码情景分析》是2012年10月出版的图书,作者是罗升阳。

        在内容上,本书结合使用情景,全面、深入、细致地分析了Android系统的源代码,涉及到Linux内核层、硬件抽象层(HAL)、运行时库层(Runtime)、应用程序框架层(ApplicationFramework)以及应用程序层(Application)。

        在组织上,本书将上述内容划分为初识Android系统、Android专用驱动系统和Android应用程序框架三大篇。初识Android系统篇介绍了参考书籍、基础知识以及实验环境搭建;Android专用驱动系统篇介绍了Logger日志驱动程序、Binder进程间通信驱动程序以及Ashmem匿名共享内存驱动程序;Android应用程序框架篇从组件、进程、消息以及安装四个维度对Android应用程序的框架进行了深入的剖析。

        通过上述内容及其组织,本书能使读者既能从整体上把握Android系统的层次结构,又能从细节上掌握每一个层次的要点。

     

     

    二、本书内容

        全书分为初识Android系统篇、Android专用驱动系统篇和Android应用程序框架篇三个部分。

        初识Android系统篇包含三个章节的内容,主要介绍Android系统的基础知识。第1章介绍与Android系统有关的参考书籍,以及Android源代码工程环境的搭建方法;第2章介绍Android系统的硬件抽象层;第3章介绍Android系统的智能指针。读者可能会觉得奇怪,为什么一开始就介绍Android系统的硬件抽象层呢?因为涉及硬件,它似乎是一个深奥的知识点。其实不然,Android系统的硬件抽象层无论是从实现上,还是从使用上,它的层次都是非常清晰的,而且从下到上涵盖了整个Android系统,包括Android系统在用户空间和内核空间的实现。内核空间主要涉及硬件驱动程序的编写方法,而用户空间涉及运行时库层、应用程序框架层及应用程序层。因此,尽早学习Android系统的硬件抽象层,有助于我们从整体上去认识Android系统,以便后面可以更好地分析它的源代码。在分析Android系统源代码的过程中,经常会碰到智能指针,第3章我们就重点分析Android系统智能指针的实现原理,也是为了后面可以更好地分析Android系统源代码。

        Android专用驱动系统篇包含三个章节的内容。我们知道,Android系统是基于Linux内核来开发的,但是由于移动设备的CPU和内存配置都要比PC低,因此,Android系统并不是完全在Linux内核上开发的,而是在Linux内核里面添加了一些专用的驱动模块来使它更适合于移动设备。这些专用的驱动模块同时也形成了Android系统的坚实基础,尤其是Logger日志驱动程序、Binder进程间通信驱动程序,以及Ashmem匿名共享内存驱动程序,它们在Android系统中被广泛地使用。在此篇中,我们分别在第4章、第5章和第6章分析Logger日志系统、Binder进程间通信系统和Ashmem共享内存系统的实现原理,为后面深入分析Android应用程序的框架打下良好的基础。

        Android应用程序框架篇包含十个章节的内容。我们知道,在移动平台中,Android系统、iOS系统和Windows Phone系统正在形成三足鼎立之势,谁的应用程序更丰富、质量更高、用户体验更好,谁就能取得最终的胜利。因此,每个平台都在尽最大努力吸引第三方开发者来为其开发应用程序。这就要求平台必须提供良好的应用程序架构,以便第三方开发者可以将更多的精力集中在应用程序的业务逻辑上,从而开发出数量更多、质量更高和用户体验更好的应用程序。在此篇中,我们将从组件、进程、消息和安装四个维度来分析Android应用程序的实现框架。第7章到第10章分析Android应用程序四大组件Activity、Service、Broadcast Receiver和Content Provider的实现原理;第11章和第12章分析Android应用程序进程的启动过程;第13章到第15章分析Android应用程序的消息处理机制;第16章分析Android应用程序的安装和显示过程。学习了这些知识之后,我们就可以掌握Android系统的精髓了。

     

     

    三、本书特点

        本书从初学者的角度出发,结合具体的使用情景,在纵向和横向上对Android系统的源代码进行了全面、深入、细致的分析。在纵向上,采用从下到上的方式,分析的源代码涉及了Android系统的内核层(Linux Kernel)、硬件抽象层(HAL)、运行时库层(Runtime)、应用程序框架层(Application Framework)以及应用程序层(Application),这有利于读者从整体上掌握Android系统的架构。在横向上,从Android应用程序的组件、进程、消息以及安装四个角度出发,全面地剖析了Android系统的应用程序框架层,这有利于读者深入地理解Android应用程序的架构以及运行原理。

     

    四、本书目录

    第1篇初识Android系统

    第1章 准备知识................................................................2

    1.1 Linux内核参考书籍...................................... ............... 2

    1.2 Android应用程序参考书籍.......................... ............... 3

    1.3 下载、编译和运行Android源代码........................... 3

    1.3.1 下载Android源代码........................................... 4

    1.3.2 编译Android源代码........................................... 4

    1.3.3 运行Android模拟器........................................... 5

    1.4 下载、编译和运行Android内核源代码............................................................ 6

    1.4.1 下载Android内核源代码................................... 6

    1.4.2 编译Android内核源代码................................... 7

    1.4.3 运行Android模拟器........................................... 8

    1.5 开发第一个Android应用程序................................... 8

    1.6 单独编译和打包Android应用程序模块.......................................................... 11

    1.6.1 导入单独编译模块的mmm命令............................................................... 11

    1.6.2 单独编译Android应用程序模块............................................................... 12

    1.6.3 重新打包Android系统镜像文件............................................................... 12

    第2章 硬件抽象层.......................................................13

    2.1 开发Android硬件驱动程序..................................... 14

    2.1.1 实现内核驱动程序模块..................................14

    2.1.2 修改内核Kconfig文件...................................... 21

    2.1.3 修改内核Makefile文件..................................... 22

    2.1.4 编译内核驱动程序模块..................................22

    2.1.5 验证内核驱动程序模块..................................23

    2.2 开发C可执行程序验证Android硬件驱动程序...............................................24

    2.3 开发Android硬件抽象层模块................................. 26

    2.3.1 硬件抽象层模块编写规范...............................26

    2.3.2 编写硬件抽象层模块接口...............................29

    2.3.3 硬件抽象层模块的加载过程...........................33

    2.3.4 处理硬件设备访问权限问题...........................36

    2.4 开发Android硬件访问服务..................................... 38

    2.4.1 定义硬件访问服务接口..................................38

    2.4.2 实现硬件访问服务..........................................39

    2.4.3 实现硬件访问服务的JNI方法.......................... 40

    2.4.4 启动硬件访问服务..........................................43

    2.5 开发Android应用程序来使用硬件访问服务.................................................. 44

    第3章 智能指针...............................................................49

    3.1 轻量级指针.............................................................50

    3.1.1 实现原理分析................................................50

    3.1.2 应用实例分析................................................53

    3.2 强指针和弱指针.....................................................54

    3.2.1 强指针的实现原理分析..................................55

    3.2.2 弱指针的实现原理分析..................................61

    3.2.3 应用实例分析................................................67

    第2篇Android专用驱动系统

    第4章 Logger日志系统............................................. 74

    4.1 Logger日志格式....................................................... 75

    4.2 Logger日志驱动程序.............................................. 76

    4.2.1 基础数据结构................................................77

    4.2.2 日志设备的初始化过程..................................78

    4.2.3 日志设备文件的打开过程...............................83

    4.2.4 日志记录的读取过程......................................84

    4.2.5 日志记录的写入过程......................................88

    4.3 运行时库层日志库.................................................93

    4.4 C/C++日志写入接口............................................. 100

    4.5 Java日志写入接口................................................ 104

    4.6 Logcat工具分析..................................................... 110

    4.6.1 基础数据结构..............................................111

    4.6.2 初始化过程..................................................115

    4.6.3 日志记录的读取过程....................................127

    4.6.4 日志记录的输出过程....................................132

    第5章 Binder进程间通信系统............................... 144

    5.1 Binder驱动程序..................................................... 145

    5.1.1 基础数据结构..............................................146

    5.1.2 Binder设备的初始化过程.............................. 164

    5.1.3 Binder设备文件的打开过程.......................... 165

    5.1.4 Binder设备文件的内存映射过程............................................................ 166

    5.1.5 内核缓冲区管理...........................................173

    5.2 Binder进程间通信库............................................. 183

    5.3 Binder进程间通信应用实例................................. 188

    5.4 Binder对象引用计数技术..................................... 196

    5.4.1 Binder本地对象的生命周期.......................... 197

    5.4.2 Binder实体对象的生命周期.......................... 201

    5.4.3 Binder引用对象的生命周期.......................... 204

    5.4.4 Binder代理对象的生命周期.......................... 209

    5.5 Binder对象死亡通知机制..................................... 212

    5.5.1 注册死亡接收通知........................................213

    5.5.2 发送死亡接收通知........................................216

    5.5.3 注销死亡接收通知........................................221

    5.6 Service Manager的启动过程.................................. 224

    5.6.1 打开和映射Binder设备文件.......................... 226

    5.6.2 注册为Binder上下文管理者.......................... 227

    5.6.3 循环等待Client进程请求............................... 231

    5.7 Service Manager代理对象的获取过程........................................................... 238

    5.8 Service组件的启动过程........................................ 244

    5.8.1 注册Service组件............................................ 245

    5.8.2 启动Binder线程池......................................... 289

    5.9 Service代理对象的获取过程................................ 291

    5.10 Binder进程间通信机制的Java接口.............................................................300

    5.10.1 Service Manager的Java代理对象的获取过程..........................................300

    5.10.2 Java服务接口的定义和解析..................................................................310

    5.10.3 Java服务的启动过程.................................... 313

    5.10.4 Java服务代理对象的获取过程.............................................................. 320

    5.10.5 Java服务的调用过程.................................... 323

    第6章 Ashmem匿名共享内存系统.............................................................. 327

    6.1 Ashmem驱动程序................................................. 328

    6.1.1 基础数据结构..............................................328

    6.1.2 匿名共享内存设备的初始化过程...........................................................330

    6.1.3 匿名共享内存设备文件的打开过程.......................................................332

    6.1.4 匿名共享内存设备文件的内存映射过程................................................334

    6.1.5 匿名共享内存块的锁定和解锁过程.......................................................336

    6.1.6 匿名共享内存块的回收过程..................................................................344

    6.2 运行时库cutils的匿名共享内存访问接口.................................................... 345

    6.3 匿名共享内存的C++访问接口............................. 349

    6.3.1 MemoryHeapBase.........................................349

    6.3.2 MemoryBase.................................................359

    6.3.3 应用实例.....................................................364

    6.4 匿名共享内存的Java访问接口............................. 370

    6.4.1 MemoryFile..................................................370

    6.4.2 应用实例.....................................................375

    6.5 匿名共享内存的共享原理....................................386

    第3篇Android应用程序框架

    第7章 Activity组件的启动过程............................. 392

    7.1 Activity组件应用实例............................................ 392

    7.2 根Activity组件的启动过程.................................... 398

    7.3 子Activity组件在进程内的启动过程............................................................ 432

    7.4 子Activity组件在新进程中的启动过程........................................................ 440

    第8章 Service组件的启动过程............................ 443

    8.1 Service组件应用实例............................................. 443

    8.2 Service组件在新进程中的启动过程............................................................. 451

    8.3 Service组件在进程内的绑定过程.................................................................463

    第9章 Android系统广播机制................................. 486

    9.1 广播机制应用实例...............................................487

    9.2 广播接收者的注册过程........................................493

    9.3 广播的发送过程...................................................501

    第10章 Content Provider组件的实现原理................................................. 524

    10.1 Content Provider组件应用实例........................... 525

    10.1.1 ArticlesProvider...........................................525

    10.1.2 Article.........................................................535

    10.2 Content Provider组件的启动过程................................................................ 550

    10.3 Content Provider组件的数据共享原理........................................................ 573

    10.3.1 数据共享模型.............................................573

    10.3.2 数据传输过程.............................................576

    10.4 Content Provider组件的数据更新通知机制................................................ 596

    10.4.1 注册内容观察者..........................................597

    10.4.2 发送数据更新通知......................................603

    第11章 Zygote和System进程的启动过程.................................................611

    11.1 Zygote进程的启动脚本........................................ 611

    11.2 Zygote进程的启动过程........................................ 614

    11.3 System进程的启动过程....................................... 622

    第12章 Android应用程序进程的启动过程................................................. 630

    12.1 应用程序进程的创建过程..................................630

    12.2 Binder线程池的启动过程................................... 639

    12.3 消息循环的创建过程..........................................641

    第13章 Android应用程序的消息处理机制................................................. 645

    13.1 创建线程消息队列.............................................645

    13.2 线程消息循环过程.............................................650

    13.3 线程消息发送过程.............................................655

    13.4 线程消息处理过程.............................................660

    第14章 Android应用程序的键盘消息处理机制....................................... 667

    14.1 键盘消息处理模型.............................................667

    14.2 InputManager的启动过程.................................... 670

    14.2.1 创建InputManager......................................670

    14.2.2 启动InputManager......................................673

    14.2.3 启动InputDispatcher....................................675

    14.2.4 启动InputReader........................................677

    14.3 InputChannel的注册过程..................................... 688

    14.3.1 创建InputChannel.......................................689

    14.3.2 注册Server端InputChannel........................... 697

    14.3.3 注册系统当前激活的应用程序窗口.....................................................701

    14.3.4 注册Client端InputChannel........................... 706

    14.4 键盘消息的分发过程..........................................709

    14.4.1 InputReader获得键盘事件........................... 710

    14.4.2 InputDispatcher分发键盘事件............................................................... 717

    14.4.3 系统当前激活的应用程序窗口获得键盘消息.......................................727

    14.4.4 InputDispatcher获得键盘事件处理完成通知......................................... 743

    14.5 InputChannel的注销过程..................................... 746

    14.5.1 销毁应用程序窗口......................................747

    14.5.2 注销Client端InputChannel........................... 756

    14.5.3 注销Server端InputChannel........................... 758

    第15章 Android应用程序线程的消息循环模型....................................... 764

    15.1 应用程序主线程消息循环模型..........................765

    15.2 与界面无关的应用程序子线程消息循环模型..........................................766

    15.3 与界面相关的应用程序子线程消息循环模型..........................................769

    第16章 Android应用程序的安装和显示过程............................................ 778

    16.1 应用程序的安装过程.........................................778

    16.2 应用程序的显示过程..........................................814

     

     

     

    五、书籍下载

    地址:http://download.csdn.net/download/u012721519/10236637

     


    Good luck!

    Write by Jimmy.li





    展开全文
  • java程序是跨平台的,可以运行在windows也可以...windows大家经常使用,并且是可视化的权限管理,这里就不多讲了。 本文主要讲讲linux下面的文件的权限和安全性问题,并且探讨一下如何在java程序中考虑文件的安全性。

    简介

    java程序是跨平台的,可以运行在windows也可以运行在linux。但是平台不同,平台中的文件权限也是不同的。windows大家经常使用,并且是可视化的权限管理,这里就不多讲了。

    本文主要讲讲linux下面的文件的权限和安全性问题,并且探讨一下如何在java程序中考虑文件的安全性。

    linux下的文件基本权限

    chmod是linux下面的权限管理命令,我们可以通过chmod来对文件的权限进行修改。

    普通文件的权限有三种,rwx分别是读,写和执行。再加上三个用户分组:owner,group,other 我们可以很方便的使用三个0-7的数字来表示一个文件的权限。

    举个例子,我们创建一个文件:

    touch test.log
    

    看一下默认的文件权限:

    ll test.log
    -rw-r--r--  1 flydean  wheel     0B  8 16 10:36 test.log
    

    默认的文件权限是644,也就是说owner权限是读写,group权限是读,其他权限是读。

    我们可以使用chmod命令对其进行修改,比如:

    chmod 777 test.log
    ll test.log
    -rwxrwxrwx  1 flydean  wheel     0B  8 16 10:36 test.log
    

    可以看出权限被修改成为777。

    linux文件的特殊权限

    讲完普通权限,我们接下来讲一下linux文件中的特殊权限。

    Set UID 和 Set GID

    考虑一个常用的修改密码的例子,修改密码调用的是/usr/bin/passwd,看下这个文件的权限:

    ll /usr/bin/passwd
    -rwsr-xr-x. 1 root root 27832 Jun 10  2014 /usr/bin/passwd
    

    可以看到有个很奇怪的s权限。这个s是什么意思呢?s实际是x的变种,是一种特殊的可执行权限。

    特殊在哪里呢?passwd是修改用户的密码,密码文件实际上是存放在 /etc/shadow中的。

    我们看下/etc/shadow的权限:

    ll /etc/shadow
    ---------- 1 root root 707 Jan  2  2020 /etc/shadow
    

    /etc/shadow的owner是root,只有root才权限强行写入这个文件。

    那么问题来了,普通用户调用passwd是怎么修改的/etc/shadow呢?

    这就是s的妙用,s表示Set UID,简称为SUID,这个UID表示User的ID,而User表示这个程序(/usr/bin/passwd)的拥有者(root),那么我们在调用passwd的过程时候,就会暂时拥有passwd owner的权限,也就是root权限。

    注意,SUID只能用在二进制文件中,它是对x权限的一个替换,并且SUID对目录是无效的。

    同样的,我们也可以给group设置UID权限,也就是Set GID。

    不同的是SGID可以使用在文件和目录两个地方。

    用在文件中是和SUID一样的,用在目录中的意思是在该目录中所建的文件或目录的用户组都和该目录的用户组是一样的。

    Sticky Bit

    Sticky Bit表示的是特殊的other权限,用t来表示。

    /tmp目录就是一个Sticky Bit的例子: drwxrwxrwt 。

    SBit对目录的作用是:“在具有SBit的目录下,用户若在该目录下具有w及x权限,则当用户在该目录下建立文件或目录时,只有文件拥有者与root才有权力删除”

    这个特性就是为了保护我们在共享目录下的文件不被别人删除。

    SUID/SGID/SBIT权限设置

    怎么设置这些权限呢?

    普通权限我们是用3个数字来表示的,我们可以在3个数字之前再加上一个数字表示SUID/SGID/SBIT权限。

    和普通权限一样,我们用4来表示SUID,2表示SGID,1表示SBIT。

    举个例子:

    touch test
    chmod 6755 test
    ll test
    -rwsr-sr-x 1 crawler crawler 0 Aug 16 11:43 test
    

    注意,有时候我们会遇到大写的S与T的情况,这种情况出现在user、group以及others都没有x这个可执行的标志,所以大写的S和T表示为空。

    文件隐藏属性

    有些linux系统提供了chattr命令来设置文件隐藏属性。

    我们看下chattr的使用:

    Usage: chattr [-RVf] [-+=aAcCdDeijsStTu] [-v version] files...
    

    参数:

    • : 增加某个特殊参数,其他原本存在的参数不动。
    • : 删除某个特殊参数,其他原本存在的参数不动。

    = : 设置一定,且仅有后面接的参数

    A : 当设置了A属性时,这个文件(或目录)的存取时间atime(access)将不可被修改,可避免例如手提电脑有磁盘I/O错误的情况发生。

    S : 这个功能有点类似sync.就是将数据同步写入磁盘中。可以有效地避免数据流失。

    a : 设置a之后,这个文件将只能增加数据,而不能删除,只有root才能设置这个属性。

    c : 这个属性设置之后,将会自动将此文件“压缩”,在读取的时候将会自动解压缩,但在存储的时候,将会先进行压缩后再存储(对于大文件有用)。

    d : 当执行dump(备份)程序的时候,设置d属性将可使该文件(或目录)具有转储功效。

    i : i的作用很大。它可以让一个文件“不能被删除、改名、设置连接,也无法写入或新增数据”。对于系统安全性有相当大的帮助。

    j : 当使用ext3文件系统格式时,设置j属性将会使文件在写入时先记录在journal中。但是,当文件系统设置参数为data=journalled时,由于已经设置日志了,所以这个属性无效。

    s : 当文件设置了s参数时,它将会从这个硬盘空间完全删除。

    u : 与s相反,当使用u来设置文件时,则数据内容其实还存在磁盘中,可以用来还原删除。

    特殊文件

    linux中还有一些特殊的文件,比如链接文件和设备文件。

    在处理链接文件的时候,我们需要注意判断链接文件的真实指向。

    而设备文件我们需要注意不合理的授权访问。

    java中在共享目录中使用文件要注意的问题

    共享目录中因为所有人都有操作文件的权限,所以,我们需要特别注意在java中共享目录中文件的操作。

    根据java的规范, java.nio.channels.FileLock可以用来表示文件的锁定。

    通常来讲,锁定有两种,一种是排他锁,一种是共享锁。

    共享锁可防止其他同时运行的程序获取重叠的排他锁,但确实允许它们获取重叠的共享锁。排他锁可防止其他程序获取任一类型的重叠锁。

    共享锁支持来自多个进程的并发读取访问;独占锁支持独占写访问。

    但是,加锁是否真正的阻塞其他程序对该文件的访问,实际是取决于操作系统。

    在使用中,我们需要对用户用户传入的文件进行一些必要的校验,比如是否是常规文件:

    String filename = /* Provided by user */;
    Path path = new File(filename).toPath();
    try {
      BasicFileAttributes attr = Files.readAttributes(
          path, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS);
    
      // Check
      if (!attr.isRegularFile()) {
        System.out.println("Not a regular file");
        return;
      }
      // Other necessary checks
    
      // Use
      try (InputStream in = Files.newInputStream(path)) {
        // Read file
      };
    } catch (IOException x) {
      // Handle error
    }
    

    上面的例子中,我们通过获取File的属性,来判断这个属性是否regularFile,注意,我们在读取文件属性的时候,传入了一个LinkOption.NOFOLLOW_LINKS,表示的是不要follow链接。

    虽然我们首先判断了file的权限,然后再对其进行操作,但是上面的例子还是会有问题的。因为存在时间差的问题,如果恶意用户在判断之后将文件替换成了恶意的链接文件,就会出现问题。

    安全目录

    为了保证用户的文件操作安全性,我们引入一个安全目录的概念,所谓安全目录就是目录除了用户本身和超级管理员之外,没有其他用户的写访问权限,并且给定文件的父目录不会被除了系统管理员之外的其他任何用户删除或重命名。

    在下方的源码链接中,我提供了一个查看安全目录的class,大家可以自行查看。

    本文的代码:

    learn-java-base-9-to-20/tree/master/security

    本文已收录于 http://www.flydean.com/java-security-code-line-file-security/

    最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

    欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

    展开全文
  • C++课程设计—学生信息管理系统 虽然老套,但是很经典,于是就把自己写的代码放上面了,以后或许还能看到当初的幼稚 代码下载地址在文章末尾,有需要的同学自取。 该课程设计含有两个模块: 教师权限模块 学生权限模块...

    C++课程设计—学生信息管理系统

    虽然老套,但是很经典,于是就把自己写的代码放上面了,以后或许还能看到当初的幼稚

    代码下载地址在文章末尾,有需要的同学自取。

    该课程设计含有两个模块:

    • 教师权限模块
    • 学生权限模块

    学生权限模块含有:

    1 .增加 2 .显示 3.追加 4.查找 学生信息功能

    教师权限模块含有:

    1.增加 2.显示 3.追加 4.查找 5 .修改 6.删除 学生信息功能

    用到的主要知识:

    ( 1 )类 ( 2 )继承( 3 )结构体( 4 )循环( 5 )数组( 6 )函数

    实现各功能模块的主线:

    • 输入密码,进入不同权限的菜单界面
    • 进入菜单界面,做出不同的选择,调用相关函数,进入不同功能模块
    • 进行不同的功能模块,进行操作之后,实现相应功能
    • 退出系统

    缺点:

    • 首先必须输入一些学生信息,才能进行各种操作
    • 没有添加文件,将学生信息保存入文件
    • 不能动态实现学生信息的输入,浪费内存空间

    **【文章福利】:**小编推荐自己的C语言交流群:967051845!整理了一些个人觉得比较好的学习书籍、视频资料共享在群文件里面,有需要的可以自行添加哦!~

    代码如下:
    <strong>#include<iostream>
    #include<cstring>
    #include<string>
    #include<fstream>
    #include<algorithm>
    #include<iomanip>
    #include<cstdio>
    #include<cstdlib>
    #include<conio.h>
    #include<windows.h>
    using namespace std;
    class student
    {
    private:
    	long long  num;
    	char name[20];
    	char sex[6];
    	int age;
    	char  phone[20];
    public:
    	static int NUM;
    	student() {}
    	~student() {}
    	void input();
    	friend void readin();
    	friend   void show();
    	friend   void mood();
    	friend  void del();
    	friend  void soort();
    	friend   void save();
    	friend  void findyou();
    	friend void clear1();
    } zhuo_yue[100];
    int student::NUM=0;
    void readin()
    {
    	ifstream in("inf.txt",ios::binary);
    	int i=1;
    	while(!in.eof())
    	{
    		in.read((char*) &zhuo_yue[i],sizeof(zhuo_yue[i]));
    		i++;
    	}
    	in.close();
    	student::NUM=i-2;
    }
    void show()
    {
    	if(student::NUM==0)
    		cout<<endl<<endl<<setw(10)<<"暂无学生信息";
    	else
    	{
    		cout<<"学生信息显示"<<endl<<endl;
    		cout<<"学号"<<setw(15)<<"姓名"<<setw(15)
    			<<"性别"<<setw(15)<<"年龄"<<setw(15)<<"电话"
    			<<endl;
    		for(int i=1; i<=student::NUM; i++)
    		{
    			cout<<zhuo_yue[i].num<<setw(15)<<zhuo_yue[i].name<<setw(15)
    				<<zhuo_yue[i].sex<<setw(15)<<zhuo_yue[i].age<<setw(15)<<zhuo_yue[i].phone
    				<<endl;
    		}
    	}
    	cout<<endl<<setw(40)<<"按任意键退出";
    	getch();
    }
    void mood()
    {
    	long long L;
    	cout<<"请输入欲修改的学号:";
    	cin>>L;
    	cout<<endl<<setw(40)<<"确认修改(y/n)";
    	if(getch()=='y')
    	{
    		system("cls");
    		for(int i=1; i<=student::NUM; i++)
    			if(L==zhuo_yue[i].num)
    			{
    				cout<<"学生信息修改"<<endl<<endl;
    				cout<<"学号:";
    				cin>>zhuo_yue[i].num;
    				cout<<endl<<endl;
    				cout<<"姓名:";
    				cin>>zhuo_yue[i].name;
    				cout<<endl<<endl;
    				cout<<"性别:";
    				cin>>zhuo_yue[i].sex;
    				cout<<endl<<endl;
    				cout<<"年龄:";
    				cin>>zhuo_yue[i].age;
    				cout<<endl<<endl;
    				cout<<"电话:";
    				cin>>zhuo_yue[i].phone;
    				cout<<endl<<endl;
    				break;
    			}
    		cout<<endl<<setw(40)<<"已修改,按任意键退出";
    		getch();
    	}
    	else
    		return;
    }
    void del()
    {
    	int sum=0;
    	cout<<setw(50)<<"[1]按学号删除				  [2]按姓名删除"<<endl;
    	if(getch()=='1')
    	{
    		cout<<"请输入学号:";
    		long long it;
    		cin>>it;
    		cout<<endl<<setw(30)<<"您确定删除此学生吗?(y/n)";
    		if(getch()=='y')
    		{
    			system("cls");
    			for(int i=1; i<=student::NUM; i++)
    			{
    				if(zhuo_yue[i].num==it)
    				{
    					for(int j=i+1; j<=student::NUM; j++)
    						zhuo_yue[j-1]=zhuo_yue[j];
    					student::NUM--;
    					sum++;
    					break;
    				}
    			}
    			cout<<"共删除"<<sum<<"人";
    		}
    		else
    			return;
    	}
    	else  if(getch()=='2')
    	{
    		char name1[20];
    		cout<<"请输入姓名:";
    		cin>>name1;
    		cout<<endl<<setw(30)<<"您确定删除此学生吗?(y/n)";
    		if(getch()=='y')
    		{
    			system("cls");
    			for(int i=1; i<=student::NUM; i++)
    			{
    				if(strcmp(zhuo_yue[i].name,name1)==0)
    				{
    					for(int j=i+1; j<=student::NUM; j++)
    						zhuo_yue[j-1]=zhuo_yue[j];
    					student::NUM--;
    					sum++;
    				}
    			}
    			cout<<"共删除"<<sum<<"人";
    		}
    		else
    			return;
    	}
    	cout<<endl<<endl<<setw(40)<<"按任意键结束";
    	getch();
    }
    void soort()
    {
    	cout<<setw(50)<<"[1]按学号排序				  [2]按年龄排序"<<endl;
    	if(getch()=='1')
    	{
    		for(int i=1; i<student::NUM; i++)
    			for(int j=1; j<student::NUM-i+1; j++)
    			{
    				if(zhuo_yue[j].num>zhuo_yue[j+1].num)
    				{
    					student it=zhuo_yue[j];
    					zhuo_yue[j]=zhuo_yue[j+1];
    					zhuo_yue[j+1]=it;
    				}
    			}
    		cout<<endl<<setw(50)<<"已排序,按任意键退出";
    		getch();
    	}
    	else  if(getch()=='2')
    	{
    		for(int i=1; i<student::NUM; i++)
    			for(int j=1; j<student::NUM-i+1; j++)
    			{
    				if(zhuo_yue[j].age>zhuo_yue[j+1].age)
    				{
    					student it=zhuo_yue[j];
    					zhuo_yue[j]=zhuo_yue[j+1];
    					zhuo_yue[j+1]=it;
    				}
    			}
    		cout<<endl<<setw(50)<<"已排序,按任意键退出";
    		getch();
    	}
    }
    void student::input()
    {
    LI:
    	NUM++;
    	cout<<"学生信息输入"<<endl<<endl;
    	cout<<"学号:";
    	cin>>zhuo_yue[NUM].num;
    	cout<<endl<<endl;
    	cout<<"姓名:";
    	cin>>zhuo_yue[NUM].name;
    	cout<<endl<<endl;
    	cout<<"性别:";
    	cin>>zhuo_yue[NUM].sex;
    	cout<<endl<<endl;
    	cout<<"年龄:";
    	cin>>zhuo_yue[NUM].age;
    	cout<<endl<<endl;
    	cout<<"电话:";
    	cin>>zhuo_yue[NUM].phone;
    	cout<<endl<<endl;
    	cout<<"已输入,是否继续  (y/n)";
    	if(getch()=='y')
    	{
    		system("cls");
    		goto LI;
    	}
    	else return;
    }
    void save()
    {
    	ofstream out("inf.txt",ios::binary);
    	cout<<endl<<setw(40)<<"已保存,按任意键退出";
    	for(int i=1; i<=student::NUM; i++)
    	{
    		out.write((char*)&zhuo_yue[i],sizeof(zhuo_yue[i]));
    	}
    	out.close();
    	getch();
    }
    void findyou()
    {
    	int sum=0;
    	cout<<setw(50)<<"[1]按学号查找				  [2]按姓名查找"<<endl;
    	if(getch()=='1')
    	{
    		cout<<"请输入学号:";
    		long long it;
    		cin>>it;
    		cout<<endl<<setw(30)<<"您确定查看此学生吗?(y/n)";
    		if(getch()=='y')
    		{
    			system("cls");
    			cout<<"查看学生信息"<<endl<<endl;
    			for(int i=1; i<=student::NUM; i++)
    			{
    				if(zhuo_yue[i].num==it)
    				{
    					cout<<setw(20)<<"学号:"<<zhuo_yue[i].num<<endl
    						<<setw(20)<<"姓名:"<<zhuo_yue[i].name<<endl
    						<<setw(20)<<"性别:"<<zhuo_yue[i].sex<<endl
    						<<setw(20)<<"年龄:"<<zhuo_yue[i].age<<endl
    						<<setw(20)<<"电话:"<<zhuo_yue[i].phone<<endl;
    					cout<<"---------------------------------------"<<endl<<endl;
    					sum++;
    				}
    			}
    			cout<<"共显示"<<sum<<"人";
    		}
    		else
    			return;
    	}
    	else  if(getch()=='2')
    	{
    		char name1[20];
    		cout<<"请输入姓名:";
    		cin>>name1;
    		cout<<endl<<setw(30)<<"您确定查看具有此姓名的学生吗?(y/n)";
    		if(getch()=='y')
    		{
    			system("cls");
    			cout<<"查看学生信息"<<endl<<endl;
    			for(int i=1; i<=student::NUM; i++)
    			{
    				if(strcmp(zhuo_yue[i].name,name1)==0)
    				{
    					cout<<setw(20)<<"学号:"<<zhuo_yue[i].num<<endl
    						<<setw(20)<<"姓名:"<<zhuo_yue[i].name<<endl
    						<<setw(20)<<"性别:"<<zhuo_yue[i].sex<<endl
    						<<setw(20)<<"年龄:"<<zhuo_yue[i].age<<endl
    						<<setw(20)<<"电话:"<<zhuo_yue[i].phone<<endl;
    					cout<<"---------------------------------------"<<endl<<endl;
    					sum++;
    				}
    			}
    			cout<<"共显示"<<sum<<"人";
    		}
    		else
    			return;
    	}
    	cout<<endl<<endl<<setw(40)<<"按任意键结束";
    	getch();
    }
    char mainmenu()
    {
    	cout<<"\n\n			  欢迎进入学生信息管理系统 "<<endl<<endl;
    	cout<<"\n\n			 [1]管理员			   [2]学生"<<endl<<endl;
    	char ff=getch();
    	return ff;
    }
    void adminmainmenu()
    {
    	cout<<"\n\n			  欢迎进入学生信息管理系统(管理者) "<<endl<<endl
    		<<endl
    		<<endl
    		<<"			   1: 录入学生信息 "<<endl<<endl
    		<<"			   2: 显示学生信息 "<<endl<<endl
    		<<"			   3: 修改学生信息 "<<endl<<endl
    		<<"			   4: 删除学生信息 "<<endl<<endl
    		<<"			   5: 查找学生信息 "<<endl<<endl
    		<<"			   6: 保存学生信息 "<<endl<<endl
    		<<"			   7: 排序学生信息"<<endl<<endl
    		<<"			   8: 返回初始页面"<<endl<<endl
    		<<"			   0: 退出系统"<<endl;
    }
    void mainmenu1()
    {
    	cout<<"\n\n			  欢迎进入学生信息管理系统(学生) "<<endl<<endl
    		<<endl
    		<<endl
    		<<"			   1: 显示学生信息 "<<endl<<endl
    		<<"			   2: 查找学生信息 "<<endl<<endl
    		<<"			   3: 排序学生信息"<<endl<<endl
    		<<"			   4: 返回初始页面"<<endl<<endl
    		<<"			   0: 退出系统"<<endl;
    }
    void clear1()
    {
    	fstream cl;
    	cl.open("inf.txt",ios::out);
    	cl.close();
    	cout<<"销毁成功";
    	exit(1);
    }
    int main()
    {
    LIIIII:
    	readin();
    	system("cls");
    	char get =  mainmenu();
    	if(get=='1')
    	{
    		char adminname[20],mima[20];
    		ifstream in;
    		ofstream out;
    		in.open("admin.txt",ios::in);
    		if(!in)
    		{
    			cout<<"无管理员账号,请先设定:"<<endl<<endl;
    FF:
    			cout<<"输入账号名:";
    			cin>>adminname;
    			cout<<"输入密码:";
    			cin>>mima;
    			cout<<"确定创建(y/n)";
    			char fff=getch();
    			if(fff=='y')
    			{
    				out.open("admin.txt",ios::app);
    				out<<adminname<<' '<<mima<<' ';
    				system("cls");
    				cout<<"							 已创建,按任意键返回";
    				getch();
    				out.close();
    				goto LIIIII;
    			}
    			else if(fff=='n')
    				goto LIIIII;
    		}
    		else
    		{
    			system("cls");
    			cout<<"					已存在用户"<<endl<<endl;
    			cout<<"是否新建管理员账户(y/n)";
    			char gr=getch();
    			if(gr=='y')
    			{
    				system("cls");
    				goto FF;
    			}
    ss1:
    			system("cls");
    			cout<<"登录账号:";
    			cin>>adminname;
    			cout<<"输入密码:";
    			cin>>mima;
    			char adminname1[20],mima1[20];
    			int flog=0;
    			while(!in.eof())
    			{
    				in>>adminname1>>mima1;
    				if(!strcmp(adminname,adminname1)&&!strcmp(mima1,mima))
    				{
    					flog=0;
    					break;
    				}
    			}
    			if(flog==0)
    			{
    				system("cls");
    				cout<<"			   登陆成功			按任意键继续";
    				getch();
    			}
    			else
    			{
    				cout<<"密码错误"<<endl<<endl;
    				cout<<"[1]返回初始界面	  [2]重新输入密码";
    				char gg=getch();
    				if(gg=='1')
    					goto LIIIII;
    				else
    				{
    					system("cls");
    					goto ss1;
    				}
    			}
    		}
    		while(1)
    		{
    			adminmainmenu();
    			char ch;
    			ch=getchar();
    			system("CLS");
    			switch(ch)
    			{
    			case '1':
    				zhuo_yue[student::NUM].input();
    				break;
    			case '2':
    				show();
    				break;
    			case '3':
    				mood();
    				break;
    			case '4':
    				del();
    				break;
    			case '5':
    				findyou();
    				break;
    			case '6':
    				save();
    				break;
    			case '7':
    				soort();
    				break;
    			case '8':
    				goto LIIIII;
    			case 'F':
    				clear1();
    			case '0':
    				cout<<"\n\n\n\n						 谢谢使用~~";
    				exit(1);
    			}
    		}
    	}
    	else if(get=='2')
    	{
    		char stuname[20],stumima[20];
    		ifstream in;
    		ofstream out;
    		in.open("student.txt",ios::in);
    		if(!in)
    		{
    			cout<<"无学生账号,请先设定:"<<endl<<endl;
    LL:
    			cout<<"输入账号名:";
    			cin>>stuname;
    			cout<<"输入密码:";
    			cin>>stumima;
    			cout<<"确定创建(y/n)";
    			char fff=getch();
    			if(fff=='y')
    			{
    				out.open("student.txt",ios::app);
    				out<<stuname<<' '<<stumima<<' ';
    				system("cls");
    				cout<<"							 已创建,按任意键返回";
    				getch();
    				out.close();
    				goto LIIIII;
    			}
    			else if(fff=='n')
    				goto LIIIII;
    		}
    		else
    		{
    			system("cls");
    			cout<<"					已存在用户"<<endl<<endl;
    			cout<<"是否新建账户(y/n)";
    			char gr=getch();
    			if(gr=='y')
    			{
    				system("cls");
    				goto LL;
    			}
    sss:
    			system("cls");
    			cout<<"登录账号:";
    			cin>>stuname;
    			cout<<"输入密码:";
    			cin>>stumima;
    			char stuname1[20],stumima1[20];
    			int flog=1;
    			while(!in.eof())
    			{
    				in>>stuname1>>stumima1;
    				if(!strcmp(stuname,stuname1)&&!strcmp(stumima1,stumima))
    				{
    					flog=0;
    					break;
    				}
    			}
    			if(flog==0)
    			{
    				system("cls");
    				cout<<"			   登陆成功			按任意键继续";
    				getch();
    			}
    			else if(flog==1)
    			{
    				system("cls");
    				cout<<"密码错误"<<endl<<endl;
    				cout<<"[1]返回初始界面	  [2]重新输入密码";
    				char gg=getch();
    				if(gg=='1')
    					goto LIIIII;
    				else
    				{
    					system("cls");
    					goto  sss;
    				}
    			}
    			in.close();
    		}
    		while(1)
    		{
    			mainmenu1();
    			char ch;
    			ch=getchar();
    			system("CLS");
    			switch(ch)
    			{
    			case '1':
    				show();
    				break;
    			case '2':
    				findyou();
    				break;
    			case '3':
    				soort();
    				break;
    			case 'F':
    				clear1();
    			case '4':
    				goto LIIIII;
    			case '0':
    				cout<<"\n\n\n\n						 谢谢使用~~";
    				exit(1);
    			}
    		}
    	}
    }
    </strong>
    

    福利

    最后,如果觉得学习资料难找的话,可以添加小编的C语言/C++交流群:967051845! 学习资料已经共享在群里了,期待你的加入~

    展开全文
  • GlusterFS集群文件系统研究

    万次阅读 热门讨论 2011-03-28 21:01:00
    GlusterFS借助TCP/IP或InfiniBand RDMA网络将物理分布的存储资源聚集在一起,使用单一全局命名空间管理数据。GlusterFS基于可堆叠的用户空间设计,可为各种不同的数据负载提供优异的性能。GlusterFS是一个具有高...

     GlusterFS集群文件系统研究

    刘爱贵 

    1.      GlusterFS概述

    GlusterFSScale-Out存储解决方案Gluster的核心,它是一个开源的分布式文件系统,具有强大的横向扩展能力,通过扩展能够支持数PB存储容量和处理数千客户端。GlusterFS借助TCP/IPInfiniBand RDMA网络将物理分布的存储资源聚集在一起,使用单一全局命名空间来管理数据。GlusterFS基于可堆叠的用户空间设计,可为各种不同的数据负载提供优异的性能。

    1 GlusterFS统一的挂载点

    GlusterFS支持运行在任何标准IP网络上标准应用程序的标准客户端,如图2所示,用户可以在全局统一的命名空间中使用NFS/CIFS等标准协议来访问应用数据。GlusterFS使得用户可摆脱原有的独立、高成本的封闭存储系统,能够利用普通廉价的存储设备来部署可集中管理、横向扩展、虚拟化的存储池,存储容量可扩展至TB/PB级。GlusterFS主要特征如下:

    l  扩展性和高性能

    GlusterFS利用双重特性来提供几TB至数PB的高扩展存储解决方案。Scale-Out架构允许通过简单地增加资源来提高存储容量和性能,磁盘、计算和I/O资源都可以独立增加,支持10GbEInfiniBand等高速网络互联。Gluster弹性哈希(Elastic Hash)解除了GlusterFS对元数据服务器的需求,消除了单点故障和性能瓶颈,真正实现了并行化数据访问。

    l  高可用性

    GlusterFS可以对文件进行自动复制,如镜像或多次复制,从而确保数据总是可以访问,甚至是在硬件故障的情况下也能正常访问。自我修复功能能够把数据恢复到正确的状态,而且修复是以增量的方式在后台执行,几乎不会产生性能负载。GlusterFS没有设计自己的私有数据文件格式,而是采用操作系统中主流标准的磁盘文件系统(如EXT3ZFS)来存储文件,因此数据可以使用各种标准工具进行复制和访问。

    l  全局统一命名空间

    全局统一命名空间将磁盘和内存资源聚集成一个单一的虚拟存储池,对上层用户和应用屏蔽了底层的物理硬件。存储资源可以根据需要在虚拟存储池中进行弹性扩展,比如扩容或收缩。当存储虚拟机映像时,存储的虚拟映像文件没有数量限制,成千虚拟机均通过单一挂载点进行数据共享。虚拟机I/O可在命名空间内的所有服务器上自动进行负载均衡,消除了SAN环境中经常发生的访问热点和性能瓶颈问题。

    l  弹性哈希算法

    GlusterFS采用弹性哈希算法在存储池中定位数据,而不是采用集中式或分布式元数据服务器索引。在其他的Scale-Out存储系统中,元数据服务器通常会导致I/O性能瓶颈和单点故障问题。GlusterFS中,所有在Scale-Out存储配置中的存储系统都可以智能地定位任意数据分片,不需要查看索引或者向其他服务器查询。这种设计机制完全并行化了数据访问,实现了真正的线性性能扩展。

    l  弹性卷管理

    数据储存在逻辑卷中,逻辑卷可以从虚拟化的物理存储池进行独立逻辑划分而得到。存储服务器可以在线进行增加和移除,不会导致应用中断。逻辑卷可以在所有配置服务器中增长和缩减,可以在不同服务器迁移进行容量均衡,或者增加和移除系统,这些操作都可在线进行。文件系统配置更改也可以实时在线进行并应用,从而可以适应工作负载条件变化或在线性能调优。

    l  基于标准协议

    Gluster存储服务支持NFS, CIFS, HTTP, FTP以及Gluster原生协议,完全与POSIX标准兼容。现有应用程序不需要作任何修改或使用专用API,就可以对Gluster中的数据进行访问。这在公有云环境中部署Gluster时非常有用,Gluster对云服务提供商专用API进行抽象,然后提供标准POSIX接口。

    2.      设计目标

    GlusterFS的设计思想显著区别有现有并行/集群/分布式文件系统。如果GlusterFS在设计上没有本质性的突破,难以在与LustrePVFS2Ceph等的竞争中占据优势,更别提与GPFSStorNextISILONIBRIX等具有多年技术沉淀和市场积累的商用文件系统竞争。其核心设计目标包括如下三个:

    l  弹性存储系统(Elasticity

    存储系统具有弹性能力,意味着企业可以根据业务需要灵活地增加或缩减数据存储以及增删存储池中的资源,而不需要中断系统运行。GlusterFS设计目标之一就是弹性,允许动态增删数据卷、扩展或缩减数据卷、增删存储服务器等,不影响系统正常运行和业务服务。GlusterFS早期版本中弹性不足,部分管理工作需要中断服务,目前最新的3.1.X版本已经弹性十足,能够满足对存储系统弹性要求高的应用需求,尤其是对云存储服务系统而言意义更大。GlusterFS主要通过存储虚拟化技术和逻辑卷管理来实现这一设计目标。

    l  线性横向扩展(Linear Scale-Out

    线性扩展对于存储系统而言是非常难以实现的,通常系统规模扩展与性能提升之间是LOG对数曲线关系,因为同时会产生相应负载而消耗了部分性能的提升。现在的很多并行/集群/分布式文件系统都具很高的扩展能力,Luster存储节点可以达到1000个以上,客户端数量能够达到25000以上,这个扩展能力是非常强大的,但是Lustre也不是线性扩展的。

    纵向扩展(Scale-Up)旨在提高单个节点的存储容量或性能,往往存在理论上或物理上的各种限制,而无法满足存储需求。横向扩展(Scale-Out)通过增加存储节点来提升整个系统的容量或性能,这一扩展机制是目前的存储技术热点,能有效应对容量、性能等存储需求。目前的并行/集群/分布式文件系统大多都具备横向扩展能力。

    GlusterFS是线性横向扩展架构,它通过横向扩展存储节点即可以获得线性的存储容量和性能的提升。因此,结合纵向扩展GlusterFS可以获得多维扩展能力,增加每个节点的磁盘可增加存储容量,增加存储节点可以提高性能,从而将更多磁盘、内存、I/O资源聚集成更大容量、更高性能的虚拟存储池。GlusterFS利用三种基本技术来获得线性横向扩展能力:

    1)        消除元数据服务

    2)        高效数据分布,获得扩展性和可靠性

    3)        通过完全分布式架构的并行化获得性能的最大化

    l  高可靠性(Reliability

    GFSGoogle File System)类似,GlusterFS可以构建在普通的服务器和存储设备之上,因此可靠性显得尤为关键。GlusterFS从设计之初就将可靠性纳入核心设计,采用了多种技术来实现这一设计目标。首先,它假设故障是正常事件,包括硬件、磁盘、网络故障以及管理员误操作造成的数据损坏等。GlusterFS设计支持自动复制和自动修复功能来保证数据可靠性,不需要管理员的干预。其次,GlusterFS利用了底层EXT3/ZFS等磁盘文件系统的日志功能来提供一定的数据可靠性,而没有自己重新发明轮子。再次,GlusterFS是无元数据服务器设计,不需要元数据的同步或者一致性维护,很大程度上降低了系统复杂性,不仅提高了性能,还大大提高了系统可靠性。

    3.      技术特

    GlusterFS在技术实现上与传统存储系统或现有其他分布式文件系统有显著不同之处,主要体现在如下几个方面。

    l  完全软件实现(Software Only

    GlusterFS认为存储是软件问题,不能够把用户局限于使用特定的供应商或硬件配置来解决。GlusterFS采用开放式设计,广泛支持工业标准的存储、网络和计算机设备,而非与定制化的专用硬件设备捆绑。对于商业客户,GlusterFS可以以虚拟装置的形式交付,也可以与虚拟机容器打包,或者是公有云中部署的映像。开源社区中,GlusterFS被大量部署在基于廉价闲置硬件的各种操作系统上,构成集中统一的虚拟存储资源池。简而言之,GlusterFS是开放的全软件实现,完全独立于硬件和操作系统。

    l  完整的存储操作系统栈(Complete Storage Operating System Stack

    GlusterFS不仅提供了一个分布式文件系统,而且还提供了许多其他重要的分布式功能,比如分布式内存管理、I/O调度、软RAID和自我修复等。GlusterFS汲取了微内核架构的经验教训,借鉴了GNU/Hurd操作系统的设计思想,在用户空间实现了完整的存储操作系统栈。

    l  用户空间实现(User Space

    与传统的文件系统不同,GlusterFS在用户空间实现,这使得其安装和升级特别简便。另外,这也极大降低了普通用户基于源码修改GlusterFS的门槛,仅仅需要通用的C程序设计技能,而不需要特别的内核编程经验。

    l  模块化堆栈式架构(Modular Stackable Architecture

    GlusterFS采用模块化、堆栈式的架构,可通过灵活的配置支持高度定制化的应用环境,比如大文件存储、海量小文件存储、云存储、多传输协议应用等。每个功能以模块形式实现,然后以积木方式进行简单的组合,即可实现复杂的功能。比如,Replicate模块可实现RAID1Stripe模块可实现RAID0,通过两者的组合可实现RAID10RAID01,同时获得高性能和高可靠性。

    l  原始数据格式存储(Data Stored in Native Formats

    GlusterFS以原始数据格式(如EXT3EXT4XFSZFS)储存数据,并实现多种数据自动修复机制。因此,系统极具弹性,即使离线情形下文件也可以通过其他标准工具进行访问。如果用户需要从GlusterFS中迁移数据,不需要作任何修改仍然可以完全使用这些数据。

    l  无元数据服务设计(No Metadata with the Elastic Hash Algorithm

    Scale-Out存储系统而言,最大的挑战之一就是记录数据逻辑与物理位置的映像关系,即数据元数据,可能还包括诸如属性和访问权限等信息。传统分布式存储系统使用集中式或分布式元数据服务来维护元数据,集中式元数据服务会导致单点故障和性能瓶颈问题,而分布式元数据服务存在性能负载和元数据同步一致性问题。特别是对于海量小文件的应用,元数据问题是个非常大的挑战。

    GlusterFS独特地采用无元数据服务的设计,取而代之使用算法来定位文件,元数据和数据没有分离而是一起存储。集群中的所有存储系统服务器都可以智能地对文件数据分片进行定位,仅仅根据文件名和路径并运用算法即可,而不需要查询索引或者其他服务器。这使得数据访问完全并行化,从而实现真正的线性性能扩展。无元数据服务器极大提高了GlusterFS的性能、可靠性和稳定性。

    4.      总体架构与设计

     

    2 GlusterFS架构和组成

    GlusterFS总体架构与组成部分如图2所示,它主要由存储服务器(Brick Server)、客户端以及NFS/Samba存储网关组成。不难发现,GlusterFS架构中没有元数据服务器组件,这是其最大的设计这点,对于提升整个系统的性能、可靠性和稳定性都有着决定性的意义。GlusterFS支持TCP/IPInfiniBand RDMA高速网络互联,客户端可通过原生Glusterfs协议访问数据,其他没有运行GlusterFS客户端的终端可通过NFS/CIFS标准协议通过存储网关访问数据。

    存储服务器主要提供基本的数据存储功能,最终的文件数据通过统一的调度策略分布在不同的存储服务器上。它们上面运行着Glusterfsd进行,负责处理来自其他组件的数据服务请求。如前所述,数据以原始格式直接存储在服务器的本地文件系统上,如EXT3EXT4XFSZFS等,运行服务时指定数据存储路径。多个存储服务器可以通过客户端或存储网关上的卷管理器组成集群,如StripeRAID0)、ReplicateRAID1)和DHT(分布式Hash)存储集群,也可利用嵌套组合构成更加复杂的集群,如RAID10

    由于没有了元数据服务器,客户端承担了更多的功能,包括数据卷管理、I/O调度、文件定位、数据缓存等功能。客户端上运行Glusterfs进程,它实际是Glusterfsd的符号链接,利用FUSEFile system in User Space)模块将GlusterFS挂载到本地文件系统之上,实现POSIX兼容的方式来访问系统数据。在最新的3.1.X版本中,客户端不再需要独立维护卷配置信息,改成自动从运行在网关上的glusterd弹性卷管理服务进行获取和更新,极大简化了卷管理。GlusterFS客户端负载相对传统分布式文件系统要高,包括CPU占用率和内存占用。

    GlusterFS存储网关提供弹性卷管理和NFS/CIFS访问代理功能,其上运行GlusterdGlusterfs进程,两者都是Glusterfsd符号链接。卷管理器负责逻辑卷的创建、删除、容量扩展与缩减、容量平滑等功能,并负责向客户端提供逻辑卷信息及主动更新通知功能等。GlusterFS 3.1.X实现了逻辑卷的弹性和自动化管理,不需要中断数据服务或上层应用业务。对于Windows客户端或没有安装GlusterFS的客户端,需要通过NFS/CIFS代理网关来访问,这时网关被配置成NFSSamba服务器。相对原生客户端,网关在性能上要受到NFS/Samba的制约。

     

    3 GlusterFS模块化堆栈式设计

       GlusterFS是模块化堆栈式的架构设计,如图3所示。模块称为Translator,是GlusterFS提供的一种强大机制,借助这种良好定义的接口可以高效简便地扩展文件系统的功能。服务端与客户端模块接口是兼容的,同一个translator可同时在两边加载。每个translator都是SO动态库,运行时根据配置动态加载。每个模块实现特定基本功能,GlusterFS中所有的功能都是通过translator实现,比如Cluster, Storage, Performance, Protocol, Features等,基本简单的模块可以通过堆栈式的组合来实现复杂的功能。这一设计思想借鉴了GNU/Hurd微内核的虚拟文件系统设计,可以把对外部系统的访问转换成目标系统的适当调用。大部分模块都运行在客户端,比如合成器、I/O调度器和性能优化等,服务端相对简单许多。客户端和存储服务器均有自己的存储栈,构成了一棵Translator功能树,应用了若干模块。模块化和堆栈式的架构设计,极大降低了系统设计复杂性,简化了系统的实现、升级以及系统维护。

    5.      弹性哈希算法

    对于分布式系统而言,元数据处理是决定系统扩展性、性能以及稳定性的关键。GlusterFS另辟蹊径,彻底摒弃了元数据服务,使用弹性哈希算法代替传统分布式文件系统中的集中或分布式元数据服务。这根本性解决了元数据这一难题,从而获得了接近线性的高扩展性,同时也提高了系统性能和可靠性。GlusterFS使用算法进行数据定位,集群中的任何服务器和客户端只需根据路径和文件名就可以对数据进行定位和读写访问。换句话说,GlusterFS不需要将元数据与数据进行分离,因为文件定位可独立并行化进行。GlusterFS中数据访问流程如下:

    1、计算hash值,输入参数为文件路径和文件名;

    2、根据hash值在集群中选择子卷(存储服务器),进行文件定位;

    3、对所选择的子卷进行数据访问。

    GlusterFS目前使用Davies-Meyer算法计算文件名hash值,获得一个32位整数。Davies-Meyer算法具有非常好的hash分布性,计算效率很高。假设逻辑卷中的存储服务器有N个,则32位整数空间被平均划分为N个连续子空间,每个空间分别映射到一个存储服务器。这样,计算得到的32hash值就会被投射到一个存储服务器,即我们要选择的子卷。难道真是如此简单?现在让我们来考虑一下存储节点加入和删除、文件改名等情况,GlusterFS如何解决这些问题而具备弹性的呢?

    逻辑卷中加入一个新存储节点,如果不作其他任何处理,hash值映射空间将会发生变化,现有的文件目录可能会被重新定位到其他的存储服务器上,从而导致定位失败。解决问题的方法是对文件目录进行重新分布,把文件移动到正确的存储服务器上去,但这大大加重了系统负载,尤其是对于已经存储大量的数据的海量存储系统来说显然是不可行的。另一种方法是使用一致性哈希算法,修改新增节点及相邻节点的hash映射空间,仅需要移动相邻节点上的部分数据至新增节点,影响相对小了很多。然而,这又带来另外一个问题,即系统整体负载不均衡。GlusterFS没有采用上述两种方法,而是设计了更为弹性的算法。GlusterFS的哈希分布是以目录为基本单位的,文件的父目录利用扩展属性记录了子卷映射信息,其下面子文件目录在父目录所属存储服务器中进行分布。由于文件目录事先保存了分布信息,因此新增节点不会影响现有文件存储分布,它将从此后的新创建目录开始参与存储分布调度。这种设计,新增节点不需要移动任何文件,但是负载均衡没有平滑处理,老节点负载较重。GlusterFS在设计中考虑了这一问题,在新建文件时会优先考虑容量负载最轻的节点,在目标存储节点上创建文件链接直向真正存储文件的节点。另外,GlusterFS弹性卷管理工具可以在后台以人工方式来执行负载平滑,将进行文件移动和重新分布,此后所有存储服务器都会均会被调度。

    GlusterFS目前对存储节点删除支持有限,还无法做到完全无人干预的程度。如果直接删除节点,那么所在存储服务器上的文件将无法浏览和访问,创建文件目录也会失败。当前人工解决方法有两个,一是将节点上的数据重新复制到GlusterFS中,二是使用新的节点来替换删除节点并保持原有数据。

    如果一个文件被改名,显然hash算法将产生不同的值,非常可能会发生文件被定位到不同的存储服务器上,从而导致文件访问失败。采用数据移动的方法,对于大文件是很难在实时完成的。为了不影响性能和服务中断,GlusterFS采用了文件链接来解决文件重命名问题,在目标存储服务器上创建一个链接指向实际的存储服务器,访问时由系统解析并进行重定向。另外,后台同时进行文件迁移,成功后文件链接将被自动删除。对于文件移动也作类似处理,好处是前台操作可实时处理,物理数据迁移置于后台选择适当时机执行。

     

    4 GlusterFS弹性卷管理

       弹性哈希算法为文件分配逻辑卷,那么GlusterFS如何为逻辑卷分配物理卷呢?GlusterFS3.1.X实现了真正的弹性卷管理,如图4所示。存储卷是对底层硬件的抽象,可以根据需要进行扩容和缩减,以及在不同物理系统之间进行迁移。存储服务器可以在线增加和移除,并能在集群之间自动进行数据负载平衡,数据总是在线可用,没有应用中断。文件系统配置更新也可以在线执行,所作配置变动能够快速动态地在集群中传播,从而自动适应负载波动和性能调优。

        弹性哈希算法本身并没有提供数据容错功能,GlusterFS使用镜像或复制来保证数据可用性,推荐使用镜像或3路复制。复制模式下,存储服务器使用同步写复制到其他的存储服务器,单个服务器故障完全对客户端透明。此外,GlusterFS没有对复制数量进行限制,读被分散到所有的镜像存储节点,可以提高读性能。弹性哈希算法分配文件到唯一的逻辑卷,而复制可以保证数据至少保存在两个不同存储节点,两者结合使得GlusterFS具备更高的弹性。

    6.      Translators

    如前所述,TranslatorsGlusterFS提供的一种强大文件系统功能扩展机制,这一设计思想借鉴于GNU/Hurd微内核操作系统。GlusterFS中所有的功能都通过Translator机制实现,运行时以动态库方式进行加载,服务端和客户端相互兼容。GlusterFS 3.1.X中,主要包括以下几类Translator

    (1)  Cluster:存储集群分布,目前有AFR, DHT, Stripe三种方式

    (2)  Debug:跟踪GlusterFS内部函数和系统调用

    (3)  Encryption:简单的数据加密实现

    (4)  Features:访问控制、锁、Mac兼容、静默、配额、只读、回收站等

    (5)  Mgmt:弹性卷管理

    (6)  MountFUSE接口实现

    (7)  Nfs:内部NFS服务器

    (8)  Performanceio-cache, io-threads, quick-read, read-ahead, stat-prefetch, sysmlink-cache, write-behind等性能优化

    (9)  Protocol:服务器和客户端协议实现

    (10)Storage:底层文件系统POSIX接口实现

    这里我们重点介绍一下Cluster Translators,它是实现GlusterFS集群存储的核心,它包括AFRAutomatic File Replication)、DHTDistributed Hash Table)和Stripe三种类型。

    AFR相当于RAID1,同一文件在多个存储节点上保留多份,主要用于实现高可用性以及数据自动修复。AFR所有子卷上具有相同的名字空间,查找文件时从第一个节点开始,直到搜索成功或最后节点搜索完毕。读数据时,AFR会把所有请求调度到所有存储节点,进行负载均衡以提高系统性能。写数据时,首先需要在所有锁服务器上对文件加锁,默认第一个节点为锁服务器,可以指定多个。然后,AFR以日志事件方式对所有服务器进行写数据操作,成功后删除日志并解锁。AFR会自动检测并修复同一文件的数据不一致性,它使用更改日志来确定好的数据副本。自动修复在文件目录首次访问时触发,如果是目录将在所有子卷上复制正确数据,如果文件不存则创建,文件信息不匹配则修复,日志指示更新则进行更新。

    DHT即上面所介绍的弹性哈希算法,它采用hash方式进行数据分布,名字空间分布在所有节点上。查找文件时,通过弹性哈希算法进行,不依赖名字空间。但遍历文件目录时,则实现较为复杂和低效,需要搜索所有的存储节点。单一文件只会调度到唯一的存储节点,一旦文件被定位后,读写模式相对简单。DHT不具备容错能力,需要借助AFR实现高可用性, 如图5所示应用案例。

    Stripe相当于RAID0,即分片存储,文件被划分成固定长度的数据分片以Round-Robin轮转方式存储在所有存储节点。Stripe所有存储节点组成完整的名字空间,查找文件时需要询问所有节点,这点非常低效。读写数据时,Stripe涉及全部分片存储节点,操作可以在多个节点之间并发执行,性能非常高。Stripe通常与AFR组合使用,构成RAID10/RAID01,同时获得高性能和高可用性,当然存储利用率会低于50%

    5 GlusterFS应用案例:AFR+DHT

    7.      设计讨论

    GlusterFS是一个具有高扩展性、高性能、高可用性、可横向扩展的弹性分布式文件系统,在架构设计上非常有特点,比如无元数据服务器设计、堆栈式架构等。然而,存储应用问题是很复杂的,GlusterFS也不可能满足所有的存储需求,设计实现上也一定有考虑不足之处,下面我们作简要分析。

    l  无元数据服务器 vs 元数据服务器

    无元数据服务器设计的好处是没有单点故障和性能瓶颈问题,可提高系统扩展性、性能、可靠性和稳定性。对于海量小文件应用,这种设计能够有效解决元数据的难点问题。它的负面影响是,数据一致问题更加复杂,文件目录遍历操作效率低下,缺乏全局监控管理功能。同时也导致客户端承担了更多的职能,比如文件定位、名字空间缓存、逻辑卷视图维护等等,这些都增加了客户端的负载,占用相当的CPU和内存。

    l  用户空间 vs 内核空间

    用户空间实现起来相对要简单许多,对开发者技能要求较低,运行相对安全。用户空间效率低,数据需要多次与内核空间交换,另外GlusterFS借助FUSE来实现标准文件系统接口,性能上又有所损耗。内核空间实现可以获得很高的数据吞吐量,缺点是实现和调试非常困难,程序出错经常会导致系统崩溃,安全性低。纵向扩展上,内核空间要优于用户空间,GlusterFS有横向扩展能力来弥补。

    l  堆栈式 vs 非堆栈式

    这有点像操作系统的微内核设计与单一内核设计之争。GlusterFS堆栈式设计思想源自GNU/Hurd微内核操作系统,具有很强的系统扩展能力,系统设计实现复杂性降低很多,基本功能模块的堆栈式组合就可以实现强大的功能。查看GlusterFS卷配置文件我们可以发现,translator功能树通常深达10层以上,一层一层进行调用,效率可见一斑。非堆栈式设计可看成类似Linux的单一内核设计,系统调用通过中断实现,非常高效。后者的问题是系统核心臃肿,实现和扩展复杂,出现问题调试困难。

    l  原始存储格式 vs 私有存储格式

    GlusterFS使用原始格式存储文件或数据分片,可以直接使用各种标准的工具进行访问,数据互操作性好,迁移和数据管理非常方便。然而,数据安全成了问题,因为数据是以平凡的方式保存的,接触数据的人可以直接复制和查看。这对很多应用显然是不能接受的,比如云存储系统,用户特别关心数据安全,这也是影响公有云存储发展的一个重要原因。私有存储格式可以保证数据的安全性,即使泄露也是不可知的。GlusterFS要实现自己的私有格式,在设计实现和数据管理上相对复杂一些,也会对性能产生一定影响。

    l  大文件 vs 小文件

    GlusterFS适合大文件还是小文件存储?弹性哈希算法和Stripe数据分布策略,移除了元数据依赖,优化了数据分布,提高数据访问并行性,能够大幅提高大文件存储的性能。对于小文件,无元数据服务设计解决了元数据的问题。但GlusterFS并没有在I/O方面作优化,在存储服务器底层文件系统上仍然是大量小文件,本地文件系统元数据访问是一个瓶颈,数据分布和并行性也无法充分发挥作用。因此,GlusterFS适合存储大文件,小文件性能较差,还存在很大优化空间。

    l  可用性 vs 存储利用率

    GlusterFS使用复制技术来提供数据高可用性,复制数量没有限制,自动修复功能基于复制来实现。可用性与存储利用率是一个矛盾体,可用性高存储利用率就低,反之亦然。采用复制技术,存储利用率为1/复制数,镜像是50%,三路复制则只有33%。其实,可以有方法来同时提高可用性和存储利用率,比如RAID5的利用率是(n-1)/nRAID6(n-2)/n,而纠删码技术可以提供更高的存储利用率。但是,鱼和熊掌不可得兼,它们都会对性能产生较大影响。

    另外,GlusterFS目前的代码实现不够好,系统不够稳定,BUGS数量相对还比较多。从其官方网站的部署情况来看,测试用户非常多,但是真正在生产环境中的应用较少,存储部署容量几TB-几十TB的占很大比率,数百TBPB级案例非常少。这也可以从另一个方面说明,GlusterFS目前还不够稳定,需要更长的时间来检验。然而不可否认,GlusterFS是一个有着光明前景的集群文件系统,线性横向扩展能力使它具有天生的优势,尤其是对于云存储系统。

    8.      参考文献

    [1] Gluster: http://www.gluster.com/products/gluster-file-system-architecture-white-paper/

    [2] Gluster: http://www.gluster.com/products/performance-in-a-gluster-system-white-paper/

    [3] Gluster: http://gluster.com/community/documentation/index.php/Main_Page

    [4] GlusterFS-Design: http://edwyseguru.wordpress.com/2010/06/11/glusterfs-design/

    [5] GlusterFS users: http://www.gluster.org/gluster-users/

    [6] GlusterFS sources: http://download.gluster.com/pub/gluster/glusterfs/3.1/

     

    展开全文
  • Android 匿名共享内存驱动源码分析

    千次阅读 2013-08-31 23:07:22
    Android系统的匿名共享内存Ashmem驱动程序利用了Linux的共享内存子系统导出的接口来实现,本文通过源码分析方式详细介绍Android系统的匿名共享内存机制。在Android系统中,匿名共享内存也是进程间通信方式的一种。...
  • 文件系统

    万次阅读 2016-01-24 17:43:17
    其实一句话就是管理这块文件的机制(组织方式,数据结构之类...) Linux系统中存在很多的文件系统,例如常见的ext2,ext3,ext4,sysfs,rootfs,proc...很多很多。。。我们知道每个文件系统是独立的,
  • 如何学习Android系统源码

    千次阅读 2018-05-22 12:16:37
    参考资料 Android系统的源代码非常庞大和复杂,我们不...我们知道,Android系统是基于Linux内核来开发的,在分析它在运行时库层的源代码时,我们会经常碰到诸如管道(pipe)、套接字(socket)和虚拟文件系统(VFS)等
  • Java实践课程设计附源码和sql脚本(物流管理系统

    千次阅读 多人点赞 2020-07-07 22:32:17
    物流管理系统:定义相关类,通过类的方法实现车辆、物品管理,查询和统计功能等;数据库可选Access、Mysql和SqlServer。 课程设计报告包含内容(论文结构) 实习目的:通过XX(具体设计的题目)课程设计实习过程...
  • LwIP 之一 源码目录文件详解及移植说明

    千次阅读 多人点赞 2018-02-02 08:55:09
    源码目录文件   目前,网络上多数文章所使用的LwIP版本为1.4.1。最新版本为2.0.3。其源码目录结构如下所示(对于简单的文件以注释的形式给出,核心源码下文会详细说明): LWIP-2.0.3 │ CHANGELOG // 版本...
  • 而《linuxnamespace-之使用》包括了网络命名空间管理、配置以及使用,这比LXC译文更接近网络命名空间的实现,但是都是基于用户空间的,这章是关于Linux网络命名空间内核源码。在Linux中,每一个网络空
  • Android系统源码学习步骤

    千次阅读 2014-07-11 10:18:29
    众所周知,如今在移动平台市场上,苹果的iOS、谷歌的Android和微软的Windows Phone系统已经形成了三足鼎立的形势,而Android系统的市场占有率是最高的。Android系统之所以能够在市场上占据着第一的位置,一来是因为...
  • 多种嵌入式文件系统移植集合

    万次阅读 2013-06-01 21:23:34
    1. 嵌入式存储系统 1.1. 计算机组成原理 从冯.诺依曼的存储程序工作原理及计算机的组成来说,计算机由运算器、控制器、存储器和输入/输出设备五大部件组成。其中运算器和控制器统称为中央处理器(CPU),而存储系统...
  • 它能够最大限度的降低内核空间和用户空间之间的数据拷贝, 从而大大提高系统的性能.   以下是创建从内核空间到用户空间共享内存映射的模板代码(在内核2.6.18和2.6.32上测试通过): 1.内核空间分配内存: #...
  • C 语言多文件共享全局变量

    千次阅读 2019-05-26 23:30:00
    只有初次定义的C 文件中的全局变量才会被分配空间,其余文件中被extern修饰的全局变量,只是申明该变量来自外部,编译器不会分配空间。 在一个头文件中定义一个变量,在各个C文件中包含引用,并不能全局共享该变量...
  • 文件系统之格式化与挂载

    千次阅读 2017-04-25 20:42:32
    文件系统 定义 文件系统类型 Linux 文件系统 光盘iso9660 Windows fat32 ntfs Unix FFS fast UFS unix JFS2 网络文件系统NFS CIFS 集群文件系统GFS2 OCFS2 oracle 分布式文件系统 RAW 未经处理或者未经格式化产生的...
  • 文件夹-最好用的文件管理神器

    千次阅读 2017-04-02 20:42:44
    一款精致而实用的文件管理App,提供了丰富的文件操作。如果您不经常鼓捣文件,那没关系,把它作为一...便捷功能:图片浏览器、小说阅读器、音乐播放器、视频播放器、文件压缩器、文件解压器、系统剩余空间提示、中文
  • redis 源码分析(一) 内存管理

    千次阅读 2014-05-21 17:47:22
    一,redis内存管理介绍  redis是一个基于内存的key-value的数据库,其内存管理是非常重要的,为了屏蔽不同平台之间的差异,以及统计内存占用量等,redis对内存分配函数...二,redis内存管理源码分析 redis封装是为了
  • Linux 文件系统部分的主要目录

    千次阅读 2013-10-24 11:08:57
    一、文件系统  1.重要作用简介:  1).承担信息处理的组织、管理和维护等任务。...操作系统正是通过文件系统管理信息的存储、传输和加工等多种处理的功能的。    2.Linux 文件系统部分的主要目录介绍  1). /bin
  •  iptux是ubuntu中一个可以和windows下大家熟悉的飞鸽传书互传文件的软件,在ubuntu软件中心中可以找安装。个人体验还不错,传输速度15M/s左右,(在ubuntu中互传速度能更好)兼容windows下的各种飞鸽传书版 本。 ...
  • 再看鸿蒙用户空间全景图 图来自鸿蒙内核源码注释中文版 【 Gitee仓|CSDN仓|Github仓|Coding仓 】 以上两图是笔者阅读完鸿蒙内核源码内存模块所绘制,给鸿蒙内核源码逐行加上中文注释 【 Gitee仓|CSDN仓|Github仓...
  • Nginx源码剖析之内存池,与内存管理

    万次阅读 多人点赞 2011-12-04 23:43:59
    Nginx源码剖析之内存池,与内存管理作者:July、dreamice、阿波、yixiao。出处:http://blog.csdn.net/v_JULY_v/。引言 Nginx(发音同 engine x)是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)...
  • MFS分布式文件系统
  • 鸿蒙内核源码注释中文版 【 Gitee仓 | CSDN仓 | Github仓 | Coding仓 】 项目中文注解鸿蒙官方内核源码,图文并茂,详细阐述鸿蒙架构和代码设计细节.每个码农,学职生涯,都应精读一遍内核源码.精读内核源码最大的好处是...
  • 分布式文件系统

    万次阅读 2018-09-05 10:24:44
    分布式文件系统(英语:Distributed file system, DFS),或是网络文件系统(英语:Network File System),是一种允许文件通过网络在多台主机上分享的文件系统,可让多机器上的多用户分享文件和存储空间。...
  • 2) 在guest机器上安装一个linux系统(选用了ubuntu)和winxp 3) 主机与guest机器之间可以有目录共享; 4)主机与guest之间可以互通访问;guest机器可以访问外网(需要重设置后再重启) 5)在guest-ubuntu尝试...
  • Linux发行版本之间的差别很少,差别主要表现在系统管理的特色工具以及软件包管理方式的不同。目录结构基本上都是一样的。 Windows的文件结构是多个并列的树状结构,最顶部的是不同的磁盘(分区),如:C,D,E,F等...
  • ramdisk文件系统的介绍与制作

    万次阅读 2016-09-23 20:21:57
    一、文件系统与根文件系统  1、文件系统  文件系统是操作系统用于明确存储设备(常见的是磁盘,也有基于NAND Flash的固态硬盘)分区上的文件的存储方法和数据结构,即在存储设备上组织文件的方法。  看了这个概念...
  • Linux 文件系统的目录结构

    千次阅读 2013-04-16 16:47:52
    1. / 文件系统的入口,最高一级目录; 2. /bin 基础系统所需要的命令位于此目录,是最小系统所需要的命令,如:ls, cp, mkdir等。...在一般情况下,GRUB或LILO系统引导管理器也位于这个目录; 4
  • STM32的FATFS文件系统移植的debug过程

    千次阅读 2016-04-16 21:46:31
    对于FATFS文件系统的移植,正点原子已经有比较完整的移植视频和相应源码。因此关于FATFS内部诸如diskio.c、ff.c和ffconf.h等文件的功能和修改这里就不再详述。博主在这里主要共享一下自己debug的一些过程(主要是针对...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 58,086
精华内容 23,234
关键字:

共享文件空间管理系统源码