资讯详情

计算机科学与技术(python方向)-计算机科学基础

本文是作者在梳理计算机系统脉络时做的一点整理。作者的专业方向是机器人和智能控制。熟悉的领域包括经典控制和规划理论、强化学习和传统计算机视觉(在引入深度学习之前)。他对深度学习在视觉上的应用有一点了解(写了一些分类和测试模型的程度),对计算机的其他方向并不熟悉。由于本人才疏学浅且绝大多数内容与本人研究方向毫无关联,不能保证正确,若有错误或不够准确的地方,还望读者不吝赐教。(似乎知乎不支持多级列表,所以文章中可能有奇怪的排版)

本文允许转载,请注明出处。

目录:

1. 从原始到现代的计算机

1.1 从机械继电器到逻辑电路

1.2 从逻辑电路到早期计算机

1.3 运行逻辑从永久存储到现代计算机

2. 编程语言

2.1 C语言与C

2.2 Java与Python语言

2.3 Java基本环境

3. 计算机网络和Web技术简介

3.1 基本的计算机网络

3.2 Web技术

3.2.1 建立连接

3.2.2 Web服务器

3.2.3 静态响应

3.2.4 动态响应

3.3 JavaWeb开发常见概念

3.3.1 Java开发基本工具

3.3.2 JavaEE框架基础

3.3.3 Spring

3.3.4 中间件等

3.4 学习路线

4. 大数据工程简介

4.1 Google的三篇论文

4.2 Hadoop及其扩展

4.3 常见的大数据概念

4.4 MapReduce

5. 人工智能

1. 从原始到现代的计算机

1.1 从机械继电器到逻辑电路

最早的计算机是用算盘和其他设备来表示和辅助计算的。在第二次工业革命之前,人们设计了一些纯机械结构的辅助计算设备。第二次工业革命后,从1890年开始,计算逻辑的动力来自电动驱动设备。早期的计算器使用机械继电器。以数据分类统计为例,纸带上的孔代表了每个分类的数据值,机械针扫描到孔连接继电器以改变统计数据。

机械继电器的使用持续到20世纪中旬。由于机械结构耐久性低,滞后时间长,人们寻求更高效、更耐用的替代设备。1904年,最早的真空管通过一个电极释放到真空中,另一个电极接收电子形成电流。在这种情况下,电子需要另一个带正电场的电极来吸引电子,否则就不能形成电流,因此具有二极管的特性。基于此设计,人们可以在真空管中添加控制电极来控制接收电极的正负,从而实现继电器的作用,称为三极管。使用大量的三极管和电线连接组织其结构可以实现一定的逻辑功能,三极管电路可以实现输入输出的逻辑构成现代电子计算机的基石,而电路连接的变化是编程的基石。同时,也在研究更快、更可靠的电子开关,它是基于半导体材料的晶体管。晶体管不仅能实现三极管的功能,还具有额外的功能。构建基于晶体管特性的非门电路,并进一步将这些结构抽象成各种逻辑操作,构成CPU的基本组件ALU(算数逻辑单元)。

特殊操作芯片是通过逻辑操作电路、输出数据操作结果和一些标志信息,接收外部输入代表数据的电平和代表特定操作的电平。存储器可以根据与运算器相同的原理构建。依靠与非门电路建立记录或重置输入数据的电路,即输出仅依赖于第一次输入,除非收到重置信号,称为定器(latch),这样的位置存储器可以组成寄存器(register),可以存储一个带宽下的数字和控制是否允许写入,因此有8个寄存器和64个寄存器的概念,扩展到64个CPU、操作系统等概念。存储基本上是大量的锁存器,可以使用一种方法来减少记录大量锁存器所需的线路数量trick:矩阵存储方式。32条线携带的01信息分为16条x不需要256条线就可以确定256个锁定器的位置。将地址信息转换为具体锁定位置的选择电路为多路复用器。抽象上述结构为256位并行存储8倍,可获得256字节(byte,8-bits)由8位地址定义的存储可以实现地址定义字节。存储和地址的扩展是构成现代计算机内存的内存(RAM,随机访问存储)。

1.2 从逻辑电路到早期计算机

到目前为止,我们已经知道如何从基于半导体材料特性的逻辑电路构建计算单元和存储单元,但它离真正的计算机还很远。前面提到,除了接收数据外,计算器还将接收指定其操作的控制信息,这与三极管的控制极有点相似。这些控制信息本质上也是以高低电平为代表的01信息,代表了最原始的代码。

我们逐步了解物理层面的实际情况。开始通电时,CPU内部寄存器全部置0,其中CPU有指令地址寄存器,CPU根据其地址从内存中选择相应的锁存器,注意锁存器在收到重置信号前保持其输出,CPU输出后输入其内部指令寄存器。注意到内存中的锁存器刚通电时没有数据,也就是说CPU执行指令前,我们需要先将指令存入内存。最直观的自然是手打电平逐个输入锁定器,大型程序可以通过打孔卡机械控制输入电平。这种方法在1980年之前被广泛使用,成为当时最重要的编程手段。根据冯诺依曼结构的定义,我们可以构建计算机的五个基本部分:算术逻辑单元、数据寄存器、指令地址寄存器、指令寄存器、存储数据和程序的内存。

编程语言同时发展。在内存中,编写程序只能使用二进制码,这给程序员带来了巨大的思维负担。人们通常使用英语和二进制应的方法,然后将其转换为二进制码。所以有些人认为,既然计算机可以识别指令,为什么不写一个程序来将英语指令转换为二进制码呢?比如我们用ASCII将代码写入英文代表的指令到内存中,然后执行某个程序,将内存中的英文指令转换为二进制码不是很容易吗?由于转换程序不需要重复编写,这种想法直接导致汇编器(Assembler)的出现。人们可以直接使用英文代码输入内存程序,然后添加汇编程序执行后获得具体指令。随着研究的深入,汇编功能越来越强大,一些功能可以在相应的基础上逐一扩展。然而,在高级语言概念诞生之前,这种写作效率仍然很低。高级语言的特点是一个句子可以实现更复杂的功能,因此一个句子可能对应十几个或更多的机器指令。编译器的概念诞生了,它负责将高级语言转化为汇编代码。FORTRAN(Formula Transition)语言是1957年发布的第一种主流高级语言。随后20世纪60年代出现了如LISP、BASIC语言,70年代Pascal、C语言,80年代C 、Perl,90年代Python、Java、Ruby等语言。关于这些语言中的几种主流语言的对比和分析我们会在之后的章节中详细描述。

1.3 运行逻辑从永久存储到现代计算机

早期计算机使用打孔纸带等通电内存,先写入程序,再通电CPU在内存中逐步执行指令。程序通过打孔卡写入内存的效率很低,不方便扩展计算机的功能和影响力。为了解决这个问题,最好在断电后保存程序的存储介质。这种存储器有很多种。磁介质存储器在早期被广泛使用。它利用电磁化后的磁介质来保持其磁极的特性,然后发展成磁带和软硬介质磁盘。与此同时,光盘在盘面上刻有大量小孔,通过光反射读取信息。为了加快读写,避免机械结构非常重要,人们发现半导体的电子特性可以支持读写,其通电可以改变材料的性质(临界电压),并在断电后保持,类似于磁结构,称为半导体存储器。理论上,闪存发展起来了(Flash)根据单个存储单元存储的数据位数开发芯片SLC(Single Level Cell)和MLC(Multi Level Cell)作为当今主流的存储类别,等级存储SSD存储介质的固态硬盘。

通过永久(非易失性)存储,我们可以收集所有组件,并开始探索现代计算机从启动到真正启动的操作逻辑。首先,计算机通电,电压最初不稳定。主板控制芯片组通电后,首先向前移动CPU发送一个RESET(重置)信号,让 CPU内部自动恢复到初始状态称为POST(Power On Self Test,此时上电自检CPU指令不执行。当芯片组检测到稳定的电源时,RESET信号立即撤回,CPU开始执行指令。启动程序称为BIOS(Basic Input Output System),存储在主板中的可擦写只读存储器(EPROM)上,一般属于永久存储Flash芯片。这里看似CPU要执行内存中的指令,必须先有东西把指令写进内存中。事实上,现代计算机的设计略有不同。

CPU我们简单地说过内部逻辑,它通过指令寄存器搜索地址来执行指令,但并不是所有的地址空间都在内存中。在进入具体CPU在执行搜索指令之前,我们需要解释搜索空间。经典架构是Intel于1978年设计的8086 16位微处理器芯片x86架构的鼻祖有20位地址总线、16位数据总线和复杂的寄存器架构。2的20次方为1M,也就是说,20个地址总线可以找到1个地址MB存储空间。32位CPU(如80386)对应32位地址总线,可寻址4GB存储空间。其中,8086的1MB空间分为常规内存(640)KB,0-A0000H)上位内存区(384KB,用于BIOS ROM系统设备),x86架构扩展(4GB减去1MB)空间称为扩展内存。这一传统进一步扩展到现代标准:常规内存供应DOS上位内存分为低128KB显示缓冲区和高64KB系统BIOS使用,中间192KB空间保留。更具体的我们在这里就不说了,见计算机组成原理或微机原理。

我们以x以86(32位)计算机为例。具体而言,Intel默认CPU重置后,寄存器的硬件设计将导致其第一个指令地址 0xFFFFFFF0H(其中,H表示16进制,然后我们省略)。此时内存中什么都没有,如何获得?BIOS的指令呢?根据上一段,我们知道在Intel在架构设计中,CPU访问地址不全是内存中的存储空间,少数留给了它BIOS和其他。由于历史遗留,指向BIOS存储空间的地址为0xF0000,Intel考虑其兼容性,将BIOS映射到了两个地址空间上,第一个即是0xFFFFFFFF(代表4GB搜索空间的末端),第二个是0xFFFFF(代表原16位时1MB搜索空间的末端)。两个地址均向下扩展64KB的空间给BIOS。显然,BIOS第一条指令应放置在映射地址0xFFFFFFF0的存储位置,方便CPU执行。

BIOS常见的设计是将该指令设计为跳转指令: JMP F000:E05B,CPU跳转后地址为0x000FE05B,依旧对应于BIOS。需要注意的是,CPU初始地址计算与后续地址计算方法不一致,跳转指令也避免了指令地址计算方法的不同BIOS指令执行不连续,因此仍有一种设计是不跳转和保持CPU直接执行第一次地址计算BIOS中RAM等重要硬件的初始化。这些工作完成后BIOS需要内容制到RAM中了。复制完成后,CPU执行RAM中BIOS的剩余指令。通常,BIOS指定启动硬盘,读取硬盘的分区记录(DPT,Disk Partition Table)和主引导记录(MBR,Master Boot Record),读取DOS(Disk Operating System,磁盘操作系统)引导记录,逐步启动操作系统。至此,系统初步启动完成。MBR分区后续发展为GPT分区(GUID Partition Table,全局唯一标识磁盘分区表),在Mac OS X和Linux系统中广泛使用。本部分参考至https://wenku.baidu.com/view/73e0db79a26925c52cc5bf66.html,链接内有该过程的更详细描述。

2. 编程语言

有了操作系统后,计算机神秘的面纱便已基本褪去,通过复杂的指令逻辑即可逐步实现文件系统、图形界面等功能。自然,显示器的发展也是独立成体系的,其主要技术基于CRT(Cathode Ray Tube,阴极射线管)和液晶显示原理等,此处不详述。工具已经齐备,为进一步扩展计算机的用途,便于人们设计更复杂的软件应用,众多高级编程语言出现。我们在此章只简单介绍下最主流的三个语言:C++、Java、Python。

2.1 C语言与C++

C++是C语言发展而来的,其很多特性都有很多的历史原因。早期计算机内存很小,无法将整个项目的源文件全部放入内存编译并构建起交叉引用,所以编译器需要分别编译各个源文件,生成多个目标文件,再将这些文件链接起来得到最终的可执行文件。为了减少内存并分别编译,C语言采用了隐式函数声明的做法,可直接编译未定义的函数,这样,编译器可以不考虑源文件间的链接问题逐个编译完所有源文件即可。C程序的编译往往对应于一条工具链,其包含一个预处理器(preprocessor)、一个编译器(compiler)、一个汇编器(assembler)、一个链接器(linker)。预处理器主要处理#include和#define等语句,编译器我们在第一章已经提过,用于将高级语言翻译成汇编代码,自然,汇编器则是将汇编代码翻译成机器码,最后链接器将所有得到的目标文件以及其调用的库函数根据依赖关系链接起来,最终得到可执行程序。关于每步生成的文件格式我们这里不详述,主要介绍下主逻辑涉及的工具。

主流发行的编译器有:GNU Compiler Collection (GCC):包含 gcc(GNU C Compiler)和 g++(GNU C++ Compiler);

Microsoft"s Visual C 和 Visual C++ compilers,若涉及其 IDE时,Visual C/C++ 通常被称为 Visual C Studio 和 Visual C++ Studio;

Intel C++ compiler、Clang 及其他。

GCC为开源编译器,基于GNU General Public License (GPL协议) 下,用户可以修改自定义的版本,而 Visual C/C++ 仅有一项版本是免费的。基于跨平台(主要考虑类Unix系统)、高效、和开放性的考虑,我们主要采用GCC编译器。Windows系统也可以通过Cygwin和MinGW实现对类Unix程序的支持。

典型的C或C++程序通常由几个模块(.c/.cpp/.cc等,GCC编译器不会明确区分)和头文件(.h)组成,头文件用于分离函数声明等内容,对于编译的C++代码而言,编译器首先将#include xxx.h替换为xxx.h头文件的内容,并依据#ifndef #define #endif防止重复导入。 头文件存在不少弊病,如头文件包含具有传递性,引入不必要的依赖;头文件在编译时使用,动态库文件在运行时使用,二者时间差可能带来不匹配,导致二进制兼容方面的问题。

如果工程较大时每次更改文件都重新全部编译将是十分耗时的事。此时,我们可以使用makefile文件依据makefile规则定义C项目的编译和链接规则,然后使用make工具调用gcc编译和链接多个源文件,更新仅仅修改过的源文件和依赖,减少编译量。类似于make这样的工具称为构建系统,依赖于如makefile这种的写入了调用的脚本。然而手动编写makefile文件通常要指定操作系统,且多平台、多编译器、多方案的支持使构建系统文件变得难以维护,于是人们提出了元构建系统。元构建系统的目的是使构建系统文件不再需要手工编写,而是自动生成,典型的工具有CMake和Autotools。CMake为其他构建系统生成文件,如CMake使用CMakeList.txt文件(跨平台)来生成makefile(特定于平台),make再将makefile(由CMake生成或手动编写)作为编译和构建的指南。通常元构建系统也可称为构建系统(build system)。

程序员开发软件需要一个方便编写和调试程序的工具,我们称其为集成开发环境(IDE,Integrated Development Environment)。我们这里以CLion为例,CLion与CMake高度集成,除了支持CMake项目外,还支持编译数据库项目(依赖于compile_commands.json文件)和Gradle项目(依赖于build.gradle文件)。

为了启动一个CLion的CMake项目,我们首先要设置一个CMakeList.txt文件,当然也可以通过创建一个新项目让其自动生成。我们简单介绍下构建项目所需的核心语句:

# 指定最低要求的CMake版本,默认设置为CLion中捆绑的CMake版本cmake_minimum_required(VERSION 3.13)# 自定义的项目名称project(sinyer)# 选择C++版本(98、11、14)set(CMAKE_CXX_STANDARD 11)# 包含项目sinyer所有的可执行文件add_executable(sinyer main.cpp xx.cpp)

add_executable 命令会指定项目的可执行文件,add_library 命令可以创建库文件,CMakeList还有许多默认参数和命令,更多的请参考官方文档,此处不详述了。

由于头文件、全局变量和函数、预处理器等机制使得C++十分复杂,但也赋予了其高效的机能和较强的内存管理能力。

2.2 Java与Python语言

上节我们描述了一个C++项目启动和运行的基本逻辑,Java、Python与C++的逻辑大同小异,我们主要简单介绍下其差异,更详细的我们会在Java和Python的应用领域(Web和人工智能)中详述。

Java执行过程是将源码通过编译器编译为字节码(class,非二进制码),再通过一个解释器逐条将字节码翻译为机器码并直接运行,这两项通过JVM(Java Virtual Machine)实现,JVM的实现和运作方式以及Java语法我们不在科普级文章中讲解。

Python被称为脚本语言,可以不通过编译直接解释运行,常见的解释器为CPython。但Python也可以先编译,如使用PyPy解释器时,其采用了JIT(just-in-time compilation,即时编译)技术,能提升部分性能,但由于对C的支持不如CPython,所以未能广泛运用。

总结一下可以认为,C++是编译型语言,编译完成后生成可执行程序(机器码)直接运行。Java和Python都是解释型语言,Java编译后生成字节码,交给解释器逐条解释成机器码运行,而Python则可以直接逐条交给解释器运行。

为便于我们之后介绍Web技术,我们之后会简单介绍下Java软件开发的一些基本知识。

2.3 Java基本环境

Java通常使用的平台版本有三个:Standard Edition(SE):主要用于桌面应用开发,包含Java语言基础、JDBC(数据库连接)、I/O、网络通信、多线程等技术;

Enterprise Edition(EE):在SE基础上增加了 Web 服务、组件模型、管理和通信 API等,如Servlet、JSP,面向企业服务和Web应用开发;

Micro Edition(ME):用于移动设备和嵌入式设备。

实际安装过程中首先都需要安装JDK,JavaEE是在安装完JDK的基础上进行扩展,可以认为JDK对应于JavaSE。下面解释下JDK相关概念:JVM(Java Virtual Machine):Java核心,用于将代码转化为计算机需要执行的动作;

JRE(Java Runtime Environment):JRE封装了JVM和Java运行时所需的一些基本类库,可以运行Java代码,故称为运行环境;

JDK(Java Development Kit):继续集成了JRE和另外一些工具(如编译器),故称为开发工具包,可以说构成了Java开发所需环境的全部基本。

3. 计算机网络与Web技术简介

3.1 计算机网络基本

网络的历史与计算机的发展一样也很复杂,但基本脉络较为清晰,简单来讲就是计算机间数据通信实现局域网,扩张交换数据规模后为方便数据交换管理出现交换机,进一步发展出现路由,然后出现因特网。在定义上,计算机互联通信的网络我们都可以称之为互联网,在英文中通常用internet(首字母小写)与表示全球互联的网络因特网(Internet)区分。关于计算机网络我们不再分析其发展历程,直接简单介绍目前计算机网络的实现。

计算机间的数据交换通过数据包传递,这个数据包是要传递的数据分段后加上必要的信息构成的包,也称分组。为了使分组可读,数据传输就需要遵从一定的规则,如TCP协议等。我们一步一步来看数据交换需要在每个阶段遵循怎样的规则。首先是物理层,用户首先要接入互联网,物理层主要体现传输技术的不同:DSL(Digital Subscribe Line):DSL调制解调器通过电话线与因特网服务提供商(Internet Service Provider,简称ISP)中的数字用户线接入复用器(DSLAM)来交换数据,ISP为电话公司;

CIC(Cable Internet Access):ISP是有线电视公司,通信链路为混合光纤同轴(Hybrid Fiber Coax HFC),而FTTH(Fiber TO The Home)为纯光纤;

以太网:用户通过双绞线与以太网交换机相连来访问互联网;

WIFI、广域无线接入。

然后,除去物理层后,计算机网络体系结构可简单分为4层:应用层:软件应用程序层面,用于将网络传输来的原始数据展示出来,或将自己的数据打包成底层数据发送出去。该层协议主要有HTTP(超文本传输协议)、FTP(文件传输协议)、SMTP(邮件传输协议),DNS(Domain Name System)负责域名解析服务。

传输层(运输层):应用层提出交换数据的请求后建立一个进程,对方接收到请求后也建立一个进程,两个应用程序的数据交换转化为进程间的通信,应用程序进程对网络的访问体现在应用层对传输层的访问,两层之间通过一个接口交互,称为套接字(socket),也称Application Programming Interface。进程套接字的标记由两部分组成:其主机地址和其在该主机中的标记。主机由IP地址标记,进程由端口号标记,如Web使用80端口、邮件使用25端口等。

原始数据(如HTTP报文)在网络上传输需要切分成数据包(报文段),而之后的层(网络层IP协议)只是尽可能保证数据交付(best-effort delivery service),但不保证报文段的交付、按序交付、及其数据的完整性,此时便需要有TCP(Transmission Control Protocol)协议、UDP(User Datagram Protocol)协议等保证数据准确无误地传至目标,具体不详述。

网络层:主要用于解决选择路由和路由选择转发线路的问题,可视为路由层。注意除提供给世界网络互联的因特网以外,也存在其他的互联网(如局域网)可用与因特网不同的网络服务模型。因特网在网络层采用三个协议:IP协议:定义编址规则、数据报格式、分组处理规则;路由选择协议:定义路径选择等;控制报文协议(ICMP,Internet Control Message Protocol):用于报告数据报中的差错、对某些网络层信息请求进行响应)。

数据链路层:负责路由间的数据帧交互。链路层协议负责:封装链路层帧;帧在链路上传输的规则:点对点链路中的点对点协议PPP和高级数据链路控制协议HDLC,媒体访问控制MAC协议,链路层寻址MAC地址的地址解析协议ARP等;协调多个结点的帧传输:多路访问协议中的信道划分协议负责协调共享信道的访问,包括时分多路复用TDM、频分多路复用FDM、 码分多址CDMA等,随机接入协议负责解决出现帧碰撞时帧的重发问题,包括时隙ALOHA、ALOHA、载波侦听多路访问CSMA等;硬件检测差错等。在网络适配器(网卡)和路由线路卡中实现。

3.2 Web技术

Web技术主要指人们上网访问各种网页或互联网软件页面时,用户发送的访问请求数据经过网络传输到对方电脑(服务器)后,对方对此请求进行处理和回应的一系列技术。用户在本机上调用浏览器等应用程序传输数据给计算机网络原理分层概念中的应用层,然后逐级下传传送再在对方网络连接相关设备上传到对方网络应用层,对方最终接收到请求数据。

3.2.1 建立连接

深入解释下我们访问网站的过程,首先我们访问的是服务器,所以我们访问的是服务器的IP地址。一般,我们会通过URL访问网页,URL指定了网络上各信息资源的唯一地址,其一般语法为:protocol :// hostname[:port] / path / [;parameters][?query]#fragment,传输协议包括file(:///)、ftp、http、ed2k等,hostname指服务器DNS或IP,可加端口(web默认80),由分号引导特殊参数,由问号引导动态网页的传参,格式为key=value&key=value,井号引导页面的名词定位,如百度百科里的跳转。

浏览器解析URL,如果遇到DNS定义的主机名(类似http://baidu.com这种而不是具体IP地址),则浏览器按顺序查找本地hosts文件映射、本地DNS缓存、DNS服务器。找到IP地址后浏览器尝试与对方服务器建立连接(以TCP连接为例)。TCP在发送数据之前,需要通过三次握手建立连接,此处直接参见教科书。

3.2.2 服务器

Web中服务器主要分为Web服务器和应用服务器。数据传输到目标后首先被Web服务器接收。Web服务器用于返回浏览器页面展示,遵从应用层的HTTP协议进行数据交换,处理根据HTTP协议所定义的格式传输的数据,故此也称HTTP服务器。目前最主流的Web服务器就是Apache、Microsoft的Internet Information Services(IIS)、和Nginx。Nginx性能优于Apache,在企业中应用极多,IIS只能用于Windows系统,由于支持http://ASP.NET,也可作为应用服务器使用。

Web服务器的机能极为简单,仅用于解析基于HTTP协议的数据,如接收HTTP请求、处理请求(如返回静态页面数据,或委托动态响应给程序执行)、返回HTTP响应(如HTML页面)等。简单来说就三种机能:支持HTTP协议、HTML文档格式及URL。注意,在JavaWeb开发中,应用服务器常称为Web容器、应用容器、动态容器等。

关于Apache,我们简单补充下。Apache软件基金会(Apache Software Foundation,ASF)是专门为支持开源软件项目而办的一个非盈利性组织。其起源于Apache组织,其成员在美国伊利诺伊斯大学超级计算机应用程序国家中心(National Center for Supercomputing Applications,NCSA)开发的NCSA HTTPd服务器的基础上开发与维护了一个叫Apache的HTTP服务器(HTTP server)。这些开发者不断将其完善壮大,并以Apache HTTP服务器为中心,启动了更多的与Apache项目并行的项目,比如mod perl、PHP、Java Apache等等,由Apache软件基金会进行管理。

应用服务器最著名的就是Tomcat,也是隶属于Apache的子项目。著名的Spring Boot就使用Tomcat作为内嵌的默认应用服务器。这部分我们在讲完动态响应后在Web开发部分会更多提及。

3.2.3 静态响应

静态响应包括HTML、JavaScript、CSS文件、图片、图像,并确定相应的MIME(Multipurpose Internet Mail Extensions,描述信息类型的因特网标准),如生成text/html的字符流或video/mpeg的字节流。其中,HTML用标签格式化显示文字和图像等,CSS文件描述标签的属性,JavaScript通过网页动作改变标签的属性(JavaScript 是 HTML 中的默认脚本语言,由浏览器执行)。除此之外还有些隐式的数据,如文档类型、cookies、缓存参数等。

除了一次HTTP请求全部页面静态数据以外,对于页面局部数据交互,需要有比重新获得页面全部数据(或利用缓存减少一定数据获取)更加高效的选择。如微信网页版、搜索提交、查询结果返回,这些都不需要重新渲染网页,只需要显示局部数据即可,所以此时浏览器与服务器交互的格式主体是数据。使这种局部数据交互成为可能得就是JavaScript的XMLHttpRequest对象,XMLHttpRequest对象允许发送HTTP请求和接收HTTP响应。响应返回的数据通常是XML或JSON格式,JavaScript中对对象的定义类似于Python的字典,格式上与JSON(JavaScript Object Notation)数据一致,也因此JSON成为了主流数据交换的格式。对服务器端不断更新页面局部数据,需要服务器端不断发送信息的,就需要保持交互连接的协议,如WebSocket技术。

3.2.4 动态响应

动态响应如CGI、JSP、Servlets、ASP、服务器端的JavaScript等,则是交于应用服务器负责。以CGI动态响应为例,整个流程可以分为:用户以HTTP协议访问URL(Uniform Resouce Locator),浏览器解码URL的第一部分以连接到Web服务器,并将剩余部分传输到所连接的Web服务器;

Web服务器将URL转换成要访问的路径和文件名,并返回对应的HTML文件(或别的组成请求页面的文件),传送完毕后连接断开;

HTML页面提示用户做动作或输入,用户响应后,浏览器请求Web服务器建立一个新的连接,并传输请求的URL信息;

Web服务器把URL信息和别的进程变量传送URL指定的(应用)服务器端的CGI程序,CGI程序执行并返回HTML响应给Web服务器,服务器返回响应并关闭连接。

我们简单解释一下几种动态响应:CGI(Common Gateway Interface):即公共网关接口,是Web服务器与外部应用程序交互的标准接口,在Web服务器上运行。前端以URL的形式将HTTP请求(如HTML表单)发送给Web服务器,Web服务器将所得的信息以环境变量的方式写入操作系统(如HTTP头),或通过标准输入(如POST请求)传递给CGI接口。CGI程序为操作系统的一个脚本程序,存放在CGI-BIN目录下,通过所用语言的库函数来获取环境变量。CGI通过标准输出(stdout) 返回HTTP协议的响应,包括HTTP主体和HTTP响应报头。所有具有标准输入输出的语言(如Perl、C++、JAVA、VB等)均可用于编写CGI程序。注意HTTP协议是一个字符协议,需要一个空行区分报头和实体。缺陷在于访问CGI每次都会令Web服务器开启一个进程执行,另外不同操作系统支持的语言也不太一致。

WSGI(Web Server Gateway Interface):类似于CGI,Python独立的网关通信技术,Django、Flask等Python网络框架的底层。由于我们主用语言是Python,所以对其网络编程应有一定认识。

PHP(Hypertext Preprocessor):服务器端脚本语言,解析基于CGI程序。程序段嵌入在HTML代码中。Web服务器收到.php的请求时会交给CGI程序,在php语言下,所调用的程序就是php-cgi。为解决高并发问题出现了FastCGI,为解决FastCGI常驻进程占用内存的问题出现了PHP-FPM(PHP FastCGI Process Manager)用于管理php-fastcgi进程。

ASP(Active Server Pages):服务器端脚本语言,解析基于ASP解释程序。程序段嵌入在HTML代码中。Web服务器收到.asp的请求时通过配置文件搜索ASP解释程序,生成并返回完整HTML页面。

Servlet:服务器端Java对象,响应时实际返回的是运行Java程序的响应,程序部署前需使用Java编译器javac编译。Web服务器通过在配置文件中通过servlet相关标签定义servlet的编译后文件,使得程序可被浏览器调用运行并响应。由于用户请求被激活成单个程序中的一个线程,所以执行速度快于CGI程序。

JSP(JavaServer Pages):基于Servlet的进一步封装,目的是直接在HTML中嵌入Java程序。JSP编译器把JSP文件编译成用Java写的Servlet,然后再由Java编译器来编译成二进制机器码。

3.3 JavaWeb开发常见概念

3.3.1 Java基本开发工具Maven:Java的包管理器,属于Java项目管理部分的内容;

Linux:一种操作系统,由于其开源可定制、轻量、安全等原因广泛用于服务器上。其起源自然是Unix系统,所以Linux和MacOS均称为类Unix系统。Unix不开源,于是Richard Stallman开发了GNU工具,先前在C++编译器部分提到的GNU即是GNU"s Not Unix!的递归缩写,Linus Torvald开发了Linux内核,构成了Linux的基础。

3.3.2 JavaEE框架基础

这部分非作者专业,实际上由专业人士解释会更加清晰。由于本文目的只是简介,所以较深入的东西一概没有。

JavaWeb主要涉及的内容为Web请求分发、对象管理、事务管理、数据库连接,初期使用JSP(页面显示和请求传递)和Servlet(请求处理)即可完成一个Java项目。但随着项目越来越大,代码复用、标准化、可维护性、开发成本等因素变得不可忽视,框架的出现就是为了解决这个问题。

在介绍具体框架前,首先我们解释JavaWeb中可谓最基础的框架模式:MVC(model、view、control)。MVC是J2EE(Java 2 Platform Enterprise Edition,现在均称JavaEE)中的三层架构,其在J2EE初期的典型实现为:control层:Controller 处理用户来自页面的请求,使用 Servlet 从 Model 获取数据,返回恰当的视图用于显示;(Servlet在动态响应小节有解释,可先简单理解为control层的Java程序。)

view层:使用JSP(嵌入HTML)将control层返回的数据渲染成页面;

model层:使用JavaBean(Java抽象的一种标准)封装数据的层。

最终达到任一层代码的改动不影响其他层的解耦效果。我们需要极为注意的是,MVC框架模式是一个局部模式,不是完整的JavaWeb逻辑。事实上它可以说只涉及数据展示,甚至与复杂的业务逻辑无关。另外,J2EE初期的分层概念效率低下,使用EJB(Enterprise Java Beans)开发,存在大量代码重复和严格定义,同样JNDI(Java Naming and Directory Interface)进行对象查找也十分单调而枯燥。

为解决上述问题,ssh(Struts+Spring+Hibernate)架构被提出,将整个逻辑分为三层体系架构:第一层是表示层,实际上就是MVC的机能,由Struts执行,用于接收和分发用户请求、将封装的数据显示在界面上,不再深入涉及到任何业务和数据库交互逻辑;

第二层是业务层,用于处理业务逻辑,对应ssh中的Spring,实际上用到的是Spring中的IoC容器,用来管理对象,减少对象耦合;

第三层是持久层,基本可以理解为对JDBC(Java Database Connectivity)的简单封装,也就是对数据库操作的一层抽象,属于ORM(Object Relation Mapping)框架,对应Hibernate,类似的还有如MyBatis、SpringDAO等。

这就是JavaWeb经典三层架构。这里面有些概念我们待会解释,但首先要说明的是由于Struts因性能、安全等因素已经过时,目前国内主流的JavaWeb开发已经切换到了ssm(SpringMVC+Spring+MyBatis)架构,并且考虑到ssm还留有一些多余的复杂度,JavaWeb更进一步统一到Spring Boot,甚至Spring Cloud。我们将主要介绍这些概念。

3.3.3 Spring

Spring,Java后端领域的王者。其主要思想为多使用接口、多面向对象、更好地配置JavaBean。典型情况下分为四层:View、Control、Service(业务层)、DAO(持久层),V和C可统一理解为表示层。

ssm中的Spring对应于Service层,代表了当今JavaEE后端开发的两大核心:IoC(Inversion of Control,控制反转):将对象的控制权转向容器的一种编程思路。具体而言,如果一个对象在创建时需要依赖多个对象,那么改动时将十分麻烦。控制反转令对象在被创建时交由IoC容器进行管理,并仅将其依赖对象的引用传递给它,称为依赖注入(Dependency Injection,DI)。IoC使对象间依赖关系的管理变得十分简单,实践中体现为XML配Bean,从事Web开发的话需要深入学习;

AOP(Aspect Oriented Programming,面向切面):通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术,如同面向对象将相似属性封装成类,面向切面将系统中的一些通用任务提取出来进行单独处理,避免大量代码重复。AOP是OOP(Object Oriented Programming,面向对象)的延续。

3.3.4 中间件及其他

在具体应用和底层硬件操作系统之间的程序都可以成为中间件,如静动态服务器、Hadoop、消息队列等。MQ(Message Queue,消息队列):可粗略理解为数据队列寄存,起解耦、异步、限峰、削流的作用,常用的有ActiveMQ、Kafka等;

RPC(Remote Procedure Call,远程过程调用):可粗略理解为网络服务器进程通信;

Docker:应用容器,可粗略理解为仅封装需要的应用和依赖包就可以依赖当前操作系统启动独立服务的一个迷你虚拟机;

Kubernetes:用于部署和管理云平台中多个主机上的容器化的应用。

3.4 学习路线

通识课:C语言、计算机组成原理、计算机网络、数据结构与算法、计算机体系结构。以下推荐书籍参考B站Up主程序羊的建议:基础:Essential C++、TCP/IP详解、鸟哥的Linux私房菜、剑指offer、LeetCode题库;

C++进阶:C++ Primer、Effeetive C++、More Effeetive C++、C++ 标准程序库、深入探索C++对象模型;

Java进阶:Java编程思想、Spring MVC +MyBatis开发从入门到精通、Spring技术内幕、深入理解Java虚拟机、Java并发编程实战;

扩展:redis入门指南、elasticsearch服务器开发等。

4. 大数据工程简介

我们在上述章节中简要提及了操作系统和互联网,那么互联网最显而易见的好处自然是知识的交换变得方便了,如何更高效地获取知识呢?搜索引擎在这样的需求背景下应运而出。但是,随着互联网数据的爆炸,建立起搜索所需的索引变得越发困难,大规模的数据对存储容量和计算能力提出了极高要求,于是大数据相关技术开始出现。

4.1 Google的三篇论文

2004年,Google为解决搜索问题,发表三篇论文:Google File System(GFS):谷歌分布式文件系统

MapReduce:谷歌分布式计算架构

BigTable:谷歌NoSQL的数据库系统

这三篇论文决定了大数据技术的三个重要问题:分布式文件存储方法、分布式计算方法、数据库交互方法。

GFS的目的是存储大量的数据。BigTable将这些数据结构化为众多大表,使查询这些数据的耗费最小,类似于数据库组织数据的结构。MapReduce是处理大量半结构化数据的方式,类似于与数据库交互的方法。如关系数据库使用SQL执行查询,系统使用特定的方式执行计算就是一种处理大量半结构化数据的方式。关于MapReduce我们会在这章的结尾给个具体的介绍。

4.2 Hadoop及其扩展

2006年,程序员Doug Cutting根据谷歌GFS和MapReduce的实现,开发出了类似的框架,后演化为著名的Hadoop框架。Hadoop是一个分布式系统基础架构,包含分布式文件系统 HDFS(Hadoop Distributed File System)和大数据计算引擎 MapReduce。HDFS主要目的是支持以流的形式访问和写入大型文件。后期Hadoop分理出独立的NoSQL数据库HBase。

2008年,Hadoop成为Apache开源组织下最重要的项目。在此基础上,Yahoo开发了Pig,Facebook开发了Hive用于封装MapReduce。由于MapReduce的实现包括了一个资源调度框架和一个执行引擎,2012年,Apache发布了Hadoop Yarn作为专门的通用资源管理系统,为上层应用提供统一的资源管理和调度。同年,伯克利为弥补基于MapReduce处理数据速度上的缺陷,开发了基于Scala语言的Spark,可用Java操作。

类似于MapReduce和Spark这种都属于批处理计算,这种计算处理的是历史数据,数据量较大、花费时间长,也被称为离线计算。针对的实时数据进行的计算称为流式计算,即把批处理计算的时间单元缩小到数据产生的间隔,Flink、Storm、Spark Streaming是主流的流式计算框架。

4.3 大数据常见概念Redis:键值数据库(主流的非关系型数据库之一),其余还有列存储数据库(HBase)、文档型数据库(MongoDb)、图形数据库等。关系型数据库主流有Oracle和MySQL等。

ZooKeeper:分布式系统的协调系统,用于处理高并发问题。

Kafka:在ZooKeeper之下的分布式消息队列系统。

4.4 MapReduce

大部分数据任务可以分为两步:处理原始数据,整理处理后数据。在面对大量数据时,这些任务需要分布运行在大量计算机上,这就涉及到并行计算、分配数据(负载均衡)、解决故障等麻烦的问题需要处理。MapReduce架构的目的,就是为了将这些问题封装起来,让我们可以只关注任务的具体实现,而无需关心那些问题如何处理。其具体的实现方式为:用户自定义Map操作(将每一项输入数据处理成一组中间键值对数据),用户自定义Reduce操作(根据一项中间键对多组键值对数据进行整理合并)。

如一组数据有如下形式:ID - value,用户可能不关心具体是哪个文件(ID),而是需要统计一些value内部的数据,需要将整个大value切分成key1、key2、key3,比如用户只关心具有key2的value里key3的值,那么处理后key3就变成了新的value,key2就代替原来的ID成为新的key,即key2 - key3,这就是一项Map操作。用户现在需要对这组处理后的数据进行整理,如有一项任务,在这些数据中key2的某一个值十分特殊,用户需要整理出所有具有该key值的数据,最后处理的结果可能就是:list(key3),这就是一项Reduce操作。

MapReduce常用于创建索引,具体例子有:计数URL访问次数:Map函数处理网络页面请求日志并生成URL1 - 1、URL2 - 1、URL3 - 1。Reduce函数对所有来自相同URL的值求和并生成URL1 - 总和、URL2 - 总和、URL3 - 总和。

反向索引(统计各单词在哪些文档中出现):Map处理每个文档,生成word1 - ID、word2 - ID、word3 - ID,Reduce整合某word得到word - list(ID)。

运行流程为:自动划分数据为M段(split操作),使Map操作可分布式;

得到中间键集,使用划分函数划分得到R片数据,使Reduce操作可分布式;

由一个主机管理Map和Reduce操作的工作机分配,在任务结束后唤醒主机。

关于MapReduce更加具体的实现方式和需要考虑的可能问题请参见其原始论文:「MapReduce: Simplified Data Processing on Large Clusters」。

5. 人工智能

这是作者相对比较熟悉的一章,虽然作者出身计算机科班,但对计算机本身兴趣不大,虽然会惊叹于技术的发展,但不认为其能最终带领人类超越人类的极限,且作者经济上有远比做基础性技术高效的来源,所以技术一直只学了个皮毛,直到人工智能的出现。

人工智能这个大概念最基本落实到的技术就是机器学习,虽然名字听起来是赋予机器学习的能力,但本质上是数学计算,考虑狭义的机器学习,其最显著的应用领域是数据分析,用于分类或聚类数据。在此基础上发展的深度学习给机器学习的方法本身赋予了一种基于数据能够拟合几乎任何映射函数的方法,由此刺激了计算机视觉和自然语言处理的发展,造成了当今人工智能繁荣的现象。

我们在这一章不讨论具体的技术,仅仅是介绍些概念。这些概念其实也没有什么深度,计算机视觉本质就是令计算机识别图片中的信息,那么利用机器学习的分类能力提取一些信息便是一种自然的想法,由此衍生出一些扩展,自然语言处理简单来讲就是处理自然语言,如机器翻译需要建立一些复杂的映射,那么深度学习赋予的映射能力自然展现出魅力。虽然这其中涉及到各种模型结构、算法等研究工作,但本质上并未展现出人类所理解的智能,直到AlphaGo的出现。

AlphaGo可以说令世界突然发现计算机能够实现较高的智能等级。虽然很多人认为下棋也是程序能轻松办到的,但更多人从中恐怕理解到了计算机正逐渐接近人类的智能,或者说他们发觉到人类的智能可能与计算机的智能不再是不可逾越的区别了。而在AlphaGo背后的,便是强化学习技术。

强化学习之所以与上述人工智能技术不太一样的原因在于其完成的是序列决策任务并且目标是获得奖励。这种设计直接令人感觉到强化学习更加接近人处理问题的方式。虽然其中依旧有着无数的不同,但这个方向或许意味着强化学习是实现通用人工智能最有可能的途径。这个想法令谷歌等大公司在不像其他人工智能技术能够产出实际价值的强化学习技术上投入大量人力物力进行研究,并始终坚持。通用人工智能技术的出现将直接导致生产力革命,进一步若机器智能超越人脑智能则很有可能出现智能爆炸增长的情况,世界和人类将从根本上发生变革。作为一个计算机人,我自然希望能为奇点到来贡献自己的一份力量。

标签: 三极管分离正负电流

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台