首页> 标签> 网络协议
"网络协议"
共 39686 条结果
全部 问答 文章 公开课 课程 电子书 技术圈 体验
前端需要去了解的nodejs知识(工具模块)
nodejs中有许多在框架中常用而我们又不知道的工具模块,本文介绍下这几个工具模块,算是自己的一个知识回顾吧。UtilNode.js 的工具模块常用的判断属性,在util.types对象isDate:判断是否是日期格式的变量isAnyArrayBuffer:判断是否是bufferisAsyncFunction:判断函数是否是异步的let util = require('util'); // types: 判断变量/函数的一些类型 const {isAnyArrayBuffer,isAsyncFunction,isDate} = util.types // isDate const is_date = isDate(new Date()) const is_date2 = isDate('2022-09-01') console.log('is_date2: ', is_date2); console.log('is_date: ', is_date); // isAnyArrayBuffer const isBuff1 = isAnyArrayBuffer('buffer') console.log('isBuff1: ', isBuff1); const isBuff2 = isAnyArrayBuffer(new ArrayBuffer(14)) console.log('isBuff2: ', isBuff2); // isAsyncFunction const f2 = async function function2(){} const f1 = function function1(){} const isAsyncFunc = isAsyncFunction(f1) const isAsyncFunc2 = isAsyncFunction(f2) console.log('isAsyncFunc2: ', isAsyncFunc2); console.log('isAsyncFunc: ', isAsyncFunc);常用的方法和属性format:格式化字符串inspect: 将对象转为字符串isDeepStrictEqual:判断两个字符是否强相等,相当于===deprecate:将函数包装为弃用// inspect const obj = {name:'inspect',date:'2022-09-01'} const str = util.inspect(obj) console.log('str: ', str); // 格式化字符串util.format(arg1,arg2,arg3,arg4) const str2 = util.format('%s:%s','12','34','56') console.log('str2: ', str2); // deprecate util.deprecate(()=>{ console.log('this is a deprecate func') }) // isDeepStrictEqual const v1 = '2' const v2 = 2; const isEqual = util.isDeepStrictEqual(v1,v2) console.log('isEqual: ', isEqual); console.log(v1 == v2); console.log(v1 === v2);DNSNode.js DNS 模块用于解析域名DNS(Domain Name System): 域名系统、组成:他是由解析器和域名服务器组成作用:域名解析,将域名转换成IP地址,将IP地址转换成域名列表nodejs中DNS支持域名和对应IP地址的相互解析,主要代码如下:let dns = require("dns"); //lookup(底层系统工具进行):将域名(比如 'runoob.com')解析为第一条找到的记录 A (IPV4)或 AAAA(IPV6)。 const hostname = "www.runoob.com"; dns.lookup(hostname, function (err, address, famliy) { if (!err) { console.log(hostname + "绑定的IP地址为:" + address); } }); //lookupService:实现给定的ip地址和端口号,解析为对应的域名 dns.lookupService("104.20.23.46", 80, (err, hostname, service) => { if (err) { console.log(err); } console.log("主机:" + hostname); console.log("协议:" + service); }); //resolve:使用网络域名系统 dns.resolve("nodejs.org", (err, address) => { if (err) { return; } console.log('resolve address: ', address); }); // reverse:反向解析 IP 地址,指向该 IP 地址的域名数组。 const ip = "192.30.252.130"; dns.reverse(ip, function (err, hostnames) { if (!err) { console.log(ip + "IP绑定的语言数组为:" + hostnames); } else { console.log(err); } }); // 返回当前正在使用的ip地址 const servers = dns.getServers(); console.log("current server ip address: ", servers);OSNode.js OS 模块提供了一些基本系统操作函数常用的方法和属性networkInterfaces获取网络信息cpus:获取系统的CPU内核细腻,返回个数组totalmem:系统总共内存容量freemem:系统空余内存变量hostname:系统主机名version: 系统内核版本的字符串const os =require('os'); console.log('系统所有内存变量为(单位M):',os.totalmem()/1024/1024); console.log('系统空余内存变量为(单位M):',os.freemem()/1024/1024); console.log('系统主机名:',os.hostname()); console.log('系统主机内核版本:',os.version());platform: 主机操作系统平摊type: 主机的操作系统平台名称,可能的值为'aix'、'darwin'、'freebsd'、'linux'、'openbsd'、'sunos'、以及 'win32'。uptime: 操作系统正常运行时间console.log('主机的平台:',os.platform()); console.log('主机的平台名称:',os.type()); console.log('主机的x正常运行时间:',os.uptime()/3600/24);Pathnodejs用来处理文件路径的工具模块,主要处理绝对路径,相对路径常用的方法和属性const path = require('path') //属性- 平台路径的分隔符 const sep =path.sep; console.log('sep: ', sep); //属性- 分隔符获取 const delimiter = path.delimiter; console.log('delimiter: ', delimiter); //属性- 提供上述 path 的方法,不过总是以 win32 兼容的方式交互。 const win32 = path.win32; // console.log('win32: ', win32); // resolve参数解析为绝对路径 const r1 = path.resolve(__dirname,'../'); console.log('r1: ', r1); // join参数拼接为一个路径 const j1 = path.join(r1,'http/app.js') console.log('j1: ', j1); // path.relative(from, to)用于将绝对路径转为相对路径,返回从 from 到 to 的相对路径(基于当前工作目录) const r2 = path.relative(j1,'http/app.js') console.log('rl: ', r2); // isAbsolute判断是否是绝对路径 const isAbs1 = path.isAbsolute(r2) console.log('isAbs1: ', isAbs1); const isAbs2 = path.isAbsolute(j1) console.log('isAbs2: ', isAbs2); // path.dirname(p):返回路径中代表文件夹的部分,同 Unix 的dirname 命令类似。 const dir = path.dirname(j1) console.log('dir: ', dir); // path.basename:返回路径中的最后一部分。同 Unix 命令 bashname 类似。 const basename = path.basename(j1) console.log('basename: ', basename); // path.extname(p): 返回路径中文件的后缀名,即路径中最后一个'.'之后(包含'.')的部分。如果一个路径中并不包含'.'或该路径只包含一个'.' 且这个'.'为路径的第一个字符,则此命令返回空字符串。 const extname = path.extname(j1); console.log('extname: ', extname); // path.parse(pathString):返回路径字符串的对象,与path.format相反。 const pathObj = path.parse('D:\\demo\\demo\\nodejs\\http\\app.js') console.log('pathObj: ', pathObj); // path.format(pathObject):从对象中返回路径字符串,和 path.parse 相反。 const pathStr = path.format(pathObj) console.log('pathStr: ', pathStr);总结nodejs中的util path os dns是我们开发web服务会常用的几个模块,再次做一了解很有必要。
文章
域名解析  ·  JavaScript  ·  网络协议  ·  前端开发  ·  Unix  ·  Linux
2023-01-16
前端需要去了解的nodejs知识(dgram)
对于前端开发,http服务是我们最长接触的通信服务,偶尔也会用到一些类似于聊天框的长链接应用,这些应用都不是基于HTTP开发的,HTTP是是无状态的短连接,说到长连接是不是首先会想到TCP,TCP是有状态的长连接协议。TCP和HTTP都是有连接的意思就是通信前需要建立连接,但是在计算机网络世界还有种无连接的协议UDP,下面我们就来了解下TCP在nodejs中的应用。dgramUDP(用户数据报协议)协议对于UDP,我们可以结合TCP一起来看,他们之间的区别以及共同之处。UDP是无连接的用户数据报协议UDP是不可靠的传输,数据在传输过程中可能会丢失UDP的传输速度是更快的UDP的连接是可以一对一,一对多,多对多,多对一的UDP应用场合:流媒体或游戏之类对数据准确性要求不是很高的应用,例如我们常用的视频通话,目前发展比较好的智能家居也是基于UDP在传输协议nodejs中的dgramnodejs中dgram的UDP传输共有三种,分别为:单播,组播,广播单播:服务端向单个客户端发送数据const dgram =require('dgram'); const server = dgram.createSocket('udp4'); server.on('listening',()=>{ var address=server.address(); console.log('listening on:'+address.address+':'+address.port) }) // 单播发送数据 server.on('message',(message,remote)=>{ console.log('收到了你的消息: ', message.toString()); const address = remote.address; console.log('remote.address: ', remote.address); const port = remote.port; console.log('remote.port: ', remote.port); // server.send('我已经收到你们发送的消息了!',port,address) }) server.on('error',()=>{ console.log('服务其出错了'); }) //绑定8888端口 server.bind(4000)广播、组播:通过ip和子网掩码计算出广播地址const dgram =require('dgram'); const server = dgram.createSocket('udp4'); const multicastAddr = "*******" server.on('listening',()=>{ var address=server.address(); //设置广播发送 server.setBroadcast(true); server.setMulticastTTL(128); setInterval(()=>{ console.log('发送消息') server.send('我已经上线了!',5000,'广播地址**') server.send('大家好啊,我是服务端组播消息', 8061, multicastAddr); },3000) console.log('listening on:'+address.address+':'+address.port) }) server.on('error',()=>{ console.log('服务其出错了'); }) //绑定8888端口 server.bind(4000)启动客户端服务const dgram =require('dgram'); const client = dgram.createSocket('udp4'); // 需要和服务端设置的相同 const multicastAddr = "*******" client.on("listening", () => { console.log("listening"); //设置客户的组播地址 client.addMembership(multicalAddress)\ }) client.on('message',(msg)=>{ console.log('我收到了服务端发送的消息!') console.log('msg: ', msg.toString()); client.send(`hello,I am client`,4000,'localhost'); }) client.on("close", () => { console.log("socket已经关闭"); }) client.bind(5000,"127.0.0.1")总结UDP协议最经典的应用应该就是微信端视频聊天了,视频聊天追求的是时效性,而TCP为了保证数据的准确性会在进行回复,重传,网络探测等等一系列的控制,这些都影响了传输的时效性,因此对于追求快速传输且对数据准确性要求不太高的应用UDP就是更好的选择。UDP在我们前端开发中其实接触的比较少,但我们可以和TCP一起了解,这两个协议许多都是相反的。一起学习的话应该更容易掌握。
文章
网络协议  ·  JavaScript  ·  前端开发  ·  智能硬件
2023-01-16
前端需要去了解的nodejs知识(net)
对于前端开发,http服务是我们最长接触的通信服务,偶尔也会用到一些类似于聊天框的长链接应用,这些应用都不是基于HTTP开发的,HTTP是是无状态的短连接,说到长连接是不是首先会想到TCP,TCP是有状态的长连接协议。TCP和HTTP都是有连接的意思就是通信前需要建立连接,但是在计算机网络世界还有种无连接的协议UDP,下面我们就来了解下TCP在nodejs中的应用。netTCP(传输控制协议)协议TCP协议的特点如下:TCP是面向连接的传输层协议TCP是可靠的传输方式,可确保数据不会丢失TCP是一对一的连接的TCP可提供全双工通信(通信双方可以任意时候发送数据)TCP数据传输是面向字节流的TCP是三次握手的连接方式,四次挥手的断开连接方式三次握手:客户端发送连接请求,服务端同意连接请问并返回到客户端,客户端建立与服务端的连接四次挥手,TCP释放连接的流程大致如下:Client告诉Server不会再发送数据=》Server告诉Client知道了等我发送完当前数据就关闭=》Server端发送完当前数据释放连接,等待Client确认=》Client确认释放连接,TCP连接关闭TCP应用场合:网页浏览,聊天程序,邮件等需要保证数据准确性的应用nodejs中的net使用Node.js Net 模块提供了一些用于底层的网络通信的小工具,包含了创建服务器/客户端的方法。服务端,主要流程为:创建服务,监听连接,发送数据,连接断开const net = require("net"); /** * 服务端创建连接服务 */ const server = net.createServer((socket) => { //监听关闭客户端连接 socket.on("end", () => { console.log("客户端关闭连接!"); }); //收到的数据是二进制流数据 socket.on("data", (data) => { console.log("data: ", data.toString()); }); //向所有的客户端发送数据 socket.write("hello, I am server!", () => {}); }); // 设置同时最大连接数 server.setMaxListeners = 99; server.on("connection", () => { console.log("新的客户端已接入"); }); server.listen(4000, () => { console.log("server is listening"); });客户端,主要流程为:连接服务,监听服务端数据,向服务端发送数据,连接断开const net = require('net'); const client = net.createConnection(4000,'localhost') //监听服务发来的数据 client.on('data',(data)=>{ console.log('客户端:已成功连接服务端!'); console.log('服务端发来的数据----: ', data.toString()); }) client.on('connect', function(){ console.log('客户端:已经与服务端建立连接'); }); client.on('close', function(data){ console.log('客户端:连接断开'); }); let index = 0; setInterval(()=>{ if(index === 9){ //断开与服务器的连接 client.end('10条数据已经发送完喽!') return } //客户端给服务端发送数据 client.write(`向客户端发送第${index}条数据`) index ++ },1000) // client.end(JSON.stringify({name:"wo shi bao bao a!"}))总结对于TCP协议最常用的应该就是实时聊天系统,另外基于HTTP协议的应用我们都可以认为底层协议是TCP应为HTTP是建立在TCP的基础之上的,理解TCP对于我们前端开发至关重要。
文章
网络协议  ·  JavaScript  ·  前端开发
2023-01-16
前端需要去了解的nodejs知识(http)
http超文本传输协议,稍微有点网络知识的人都晓得这个名词,那nodejs中的http和他有什么关系呢?Nodejs中的http是实现网络传输的基础模块,HTTP协议HTTP(超文本传输协议),是应用层中的数据传输协议,是万维网数据通信的基础。HTTP的协议在应用层的主要特征如下:HTTP协议中必须同时具备客户端和服务端。基于 TCP/IP 通信协议来传递数据。HTTP是无连接(区别于socket),无连接的含义是限制每次连接只处理一个请求,服务器处理完客户的请求,并收到客户的应答后,即断开连接,采用这种方式可以节省传输时间。HTTP 是无状态(需要引入缓存的原因),HTTP对于事务处理是没有记忆能力的,后续的请求是无法获取前面请求的任何信息的。HTTP 是媒体独立的(对于传输的数据是无限制的),只要客户端和服务器知道如何处理的数据内容,任何类型的数据都可以通过HTTP发送。Nodejs http模块网上搜索到一张很形象的图,描述了http和TCP/IP之间的关系,由图可看出HTTP和TCP/IP的整体作用是保证数据在客户端(发起请求方)和服务端(接受请求方)的传输。两者间的区别:TCP/IP传输的报文是字节(二进制数据),HTTP传输的是超文本数据(字符)TCP是作用于传输层的,HTTP是作用于应用层的,HTTP请求时通过 TCP 协议建立起连接服务器的通道HTTP 是无状态的短连接,而 TCP 是有状态的长连接TCP定义的是数据传输和连接方式的规范,HTTP是应用层协议,定义的是传输数据的内容的规范注:这里为何要了解下TCP呢,因为HTTP协议是建立在TCP基础上的,如果对TCP协议没有一定的了解是无法真正的明白HTTP的传输流程的。HTTP的使用HTTP模块主要分为创建服务HTTP.createServer和创建请求HTTP.requestHTTP服务创建:nodejs的http模块能够创建一个http服务,const http = require('http') // createServer可以用回调函数实现对客户端请求对监听,也可以通过request事件的监听来实现 const server = http.createServer((request,response)=>{ }) // 监听request事件 server.on("request",(request,response)=>{ }) // 指定通信端口 server.listen(8080, function () { console.log('server running at http://localhost:8080') })HTTP服务回调函数有request和reponse组成:request:解析客户端的请求常用属性及方法:url(请求路径) method(请求方法)headers(头部)url:请求的路径,可以根据URL设置出路由模式,express的就是基于此设置的methoe:请求的方式分为,post get delete put patchheaders: 请求的头部,客户单的cookie,数据传输的类型等都放在header中data事件:createServer想要获取请求数据体需要监听data事件req.on('data',function(data){ console.log('data: ', data); });response:相应客户端请求,常用属性及方法如下:end:res.end()setHeader(name,content),可以设置单个header属性,可以多次设置destory:取消返回statusCode:设置返回的状态码,如200 404 400 500等statusMessage:设置状态码对应返回的信息writeHead:可以同时设置statusCode statusMessage 和多个header属性res.writeHead(200,"success", {"Content-type" : "text/html"});HTTP请求的创建,Nodejs的http模块不仅仅能作为服务器来接受请求,也能作为客户端来发送请求。const http = require('http'); const options = { port: 3333, hostname: 'localhost', path: '/demo', method: 'POST', headers: { "Content-Type":'text/html' } } const req = http.request(options,(res)=>{ console.log(`statusCode: ${res.statusCode}`); res.on('data', data => { console.log(data) }); }) req.end()HTTP请求主要有请求参数和返回值组成:options:请求参数主要有以下属性method:请求服务端的方法path:请求的路径port:请求的端口hostname:请求的主机名headers:请求时header上的内容response:请求后的返回值data事件监听res.on('data', data => { console.log(data) });总结对于Nodejs HTTP模块的总结就到这里了,此次重新学习了下HTTP的API,对于API的了解是比较简单,只要经常使用能够掌握,但是对于HTTP的传输流程需要我们去查阅许多计算机网络的相关知识,其中TCP/IP是必须要了解的,扩散性学习能够更快的掌握新知识也能从已有的知识的推导出更多相关的知识。
文章
缓存  ·  网络协议  ·  JavaScript  ·  前端开发  ·  API
2023-01-16
学点Linux命令没坏处(网络)
前言本章一起了解下Linux中网络基础,分别从一下几个方面来学习:网络的状态 网络的配置 网络监控 网络连接。Linux中网络命令显示查询,在linux查询网络状态的有以下命令:ifconfig(像是网络信息) route(显示路由表) netstat(显示网络状态) ss(显示网络状态) arp(arp命令用于操作本机的arp缓存区,它可以显示arp缓存区中的所有条目、删除指定的条目或者添加静态的IP地址与MAC地址的对应关系。) nmap(网络探测工具,非内置命令需要安装) nslookup(常用的域名解析查询工具。) dig(域名查询工具) host (域名解析查询工具。)//ifconfig:配置或显示网络接口信息(List of possible hardware types:) [root@localhost ~]# ifconfig #<===查看机器上所有激活的网卡 enp0s25: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.1.10 netmask 255.255.255.0 broadcast 192.168.1.255 inet6 fe80::a9d2:ba42:8306:8177 prefixlen 64 scopeid 0x20<link> inet6 240e:388:8221:2c00:1cd8:fd91:cb44:ec62 prefixlen 64 scopeid 0x0<global> ether 04:7d:7b:39:95:ab txqueuelen 1000 (Ethernet) RX packets 2435833 bytes 535444996 (510.6 MiB) RX errors 2 dropped 0 overruns 0 frame 1 TX packets 2121493 bytes 318310278 (303.5 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 device interrupt 20 memory 0xf4600000-f4620000 #===>ifconfig + 网卡名:显示指定网卡 #===>ifconfig + 网卡名 + up/down:启动、关闭网卡 #===>ifconfig + 网卡名 + ip地址:修改网卡ip地址 #===>ifconfig + 网卡名 + hw + ether + 网卡地址:修改网卡地址 //route 显示或管理路由表,主要管理的是静态路由 [root@localhost demo]# route Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface default gateway 0.0.0.0 UG 100 0 0 enp0s25 192.168.1.0 0.0.0.0 255.255.255.0 U 100 0 0 enp0s25 //netstat 查看网络状态 -r -g -s -n -a(显示处于非监听/监听状态的socket信息) [root@localhost demo]# netstat Active Internet connections (w/o servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 localhost.localdo:27017 121.4.59.78:58206 ESTABLISHED tcp 0 0 localhost.localdo:27017 121.4.59.78:58192 ESTABLISHED .... //netstat命令用于显示本机网络的连接状态、运行端口和路由表等信息。 [root@VM-12-10-centos ~]# netstat -an #<====显示所有的连接信息> Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 127.0.0.1:27017 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN tcp 0 0 10.0.12.10:40340 169.254.0.55:8080 TIME_WAIT ... // 以上命令语句的作用为显示所有TCP和UDP正在监听的连接信息。 [root@VM-12-10-centos ~]# netstat -lntup Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 127.0.0.1:27017 0.0.0.0:* LISTEN 228480/mongod ... //显示路由表 [root@VM-12-10-centos ~]# netstat -rn Kernel IP routing table Destination Gateway Genmask Flags MSS Window irtt Iface 0.0.0.0 10.0.12.1 0.0.0.0 UG 0 0 0 eth0 10.0.12.0 0.0.0.0 255.255.252.0 U 0 0 0 eth0 //ss命令是类似并将取代netstat的工具,它能用来查看网络状态信息,包括TCP、UDP连接、端口等。它的优点是能够显示更多更详细的有关网络连接状态的信息,而且比netstat更快速更高效。 //显示所有socket连接 [root@VM-12-10-centos ~]# ss -an Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process nl UNCONN 0 0 0:981585547 * nl UNCONN 0 0 ... //统计当前的established closed orphaned和waiting的TCP socket数量 [root@VM-12-10-centos ~]# ss -s Total: 219 TCP: 34 (estab 28, closed 0, orphaned 0, timewait 0) Transport Total IP IPv6 RAW 1 0 1 UDP 3 2 1 TCP 34 5 29 INET 38 7 31 ... //arp是查看缓存信息(arp缓存就是IP地址和MAC地址关系缓存列表)的详细信息 详细信息2 //在局域网中,当主机或其它三层网络设备有数据要发送给另一台主机或三层网络设备时,需要知道对方的网络层地址(即IP地址)。但是仅有IP地址是不够的,因为IP报文必须封装成帧才能通过物理网络发送,因此发送方还需要知道接收方的物理地址(即MAC地址),这就需要一个通过IP地址获取物理地址的协议,以完成从IP地址到MAC地址的映射。地址解析协议ARP即可实现将IP地址解析为MAC地址。 //arp:地址解析协议(Address Resolution Protocol),主要功能是根据IP地址获取物理地址 [root@VM-12-10-centos ~]# arp -n Address HWtype HWaddress Flags Mask Iface 10.0.12.1 ether fe:ee:5e:4d:d7:bb C eth0nmap:功能全面的端口扫描工具,此外还具备寻找目标网络中的在线主机文档地址,常用的扫描如下SYN扫描,使用频率最高的扫描选项:SYN扫描,又称为半开放扫描,它不打开一个完全的TCP连接,执行得很快,nmap -sS ***/24ping扫描,用ping的方式检查网络上哪些主机正在运行。 nmap -sP ***/24[root@zz ~]# nmap 192.168.1.10 #<====扫描主机开放的服务> Starting Nmap 6.40 ( http://nmap.org ) at 2022-07-22 19:18 CST Nmap scan report for 192.168.1.10 Host is up (0.000017s latency). Not shown: 996 closed ports PORT STATE SERVICE 22/tcp open ssh 80/tcp open http 3306/tcp open mysql 8080/tcp open http-proxy Nmap done: 1 IP address (1 host up) s [root@zz ~]# nmap -p 8080 192.168.1.10 #<====指定端口扫描 Starting Nmap 6.40 ( http://nmap.org ) at 2022-07-22 19:24 CST Nmap scan report for 192.168.1.10 Host is up (0.00013s latency). PORT STATE SERVICE 8080/tcp open http-proxy Nmap done: 1 IP address (1 host up) scanned in 0.29 seconds [root@zz ~]# nmap -sP 192.168.123.1/24 Starting Nmap 6.40 ( http://nmap.org ) at 2022-07-22 19:30 CST Nmap done: 256 IP addresses (0 hosts up) scanned in 206.24 secondsnslookup dig host这三个都是域名查询工具,区别如下:nslookup可以以交互的方式查询 dig用于测试dns系统(不会查询host)host以更简洁的方式显示查询结果// nslookup交互模式 [root@zz ~]# nslookup > www.baidu.com Server: 192.168.1.1 Address: 192.168.1.1#53 Non-authoritative answer: www.baidu.com canonical name = www.a.shifen.com. Name: www.a.shifen.com Address: 180.101.49.12 Name: www.a.shifen.com Address: 180.101.49.11 [root@zz ~]# nslookup > set type=MX #<==== set用来设置查询方式 MX表示邮件交换记录,邮件交换记录 (MX record)是域名系统(DNS)中的一种资源记录类型> > www.baidu.com Server: 192.168.1.1 Address: 192.168.1.1#53 Non-authoritative answer: www.baidu.com canonical name = www.a.shifen.com. Authoritative answers can be found from: a.shifen.com origin = ns1.a.shifen.com mail addr = baidu_dns_master.baidu.com serial = 2207240004 refresh = 5 retry = 5 expire = 2592000 minimum = 3600 > [root@zz ~]# nslookup www.baidu.com #<====非交互方式查询> Server: 192.168.1.1 Address: 192.168.1.1#53 Non-authoritative answer: www.baidu.com canonical name = www.a.shifen.com. Name: www.a.shifen.com Address: 180.101.49.11 Name: www.a.shifen.com Address: 180.101.49.12 [root@zz ~]# nslookup -ty=ptr 202.96.128.166 #<===反向域名解析 ptr表示反向域名解析> Server: 192.168.1.1 Address: 192.168.1.1#53 Non-authoritative answer: 166.128.96.202.in-addr.arpa name = cache-b.guangzhou.gd.cn. Authoritative answers can be found from: [root@zz ~]# dig www.baidu.com #<====域名解析> ; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el7_9.9 <<>> www.baidu.com ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 31412 ;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;www.baidu.com. IN A ;; ANSWER SECTION: www.baidu.com. 600 IN CNAME www.a.shifen.com. www.a.shifen.com. 600 IN A 180.101.49.11 www.a.shifen.com. 600 IN A 180.101.49.12 ;; Query time: 4 msec ;; SERVER: 192.168.1.1#53(192.168.1.1) ;; WHEN: Sun Jul 24 16:42:34 CST 2022 ;; MSG SIZE rcvd: 90 [root@zz ~]# dig -x 101.200.195.98 #<=== dig -x ip 反向域名解析> ; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el7_9.9 <<>> -x 101.200.195.98 ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 4919 ;; flags: qr aa rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;98.195.200.101.in-addr.arpa. IN PTR ;; AUTHORITY SECTION: 200.101.in-addr.arpa. 300 IN SOA rdns1.alidns.com. dnsmgr.alibaba-inc.com. 2015011391 1800 600 1814400 300 ;; Query time: 24 msec ;; SERVER: 192.168.1.1#53(192.168.1.1) ;; WHEN: Sun Jul 24 16:52:07 CST 2022 ;; MSG SIZE rcvd: 127 [root@zz ~]# host www.baidu.com #<==== host + domain 更简单的显示查询内容> www.baidu.com is an alias for www.a.shifen.com. www.a.shifen.com has address 180.101.49.11 www.a.shifen.com has address 180.101.49.12 //ping命令可用于测试主机之间网络的连通性。执行ping命令会使用ICMP传输协议,发出要求回应的信息,若远端主机的网络功能没有问题,就会回应该信息,因而可得知该主机运作正常。 [root@zz ~]# ping 192.168.1.12 PING 192.168.1.12 (192.168.1.12) 56(84) bytes of data. 64 bytes from 192.168.1.12: icmp_seq=1 ttl=64 time=4.16 ms 64 bytes from 192.168.1.12: icmp_seq=2 ttl=64 time=2.92 ms 64 bytes from 192.168.1.12: icmp_seq=3 ttl=64 time=2.71 ms 64 bytes from 192.168.1.12: icmp_seq=4 ttl=64 time=3.22 ms 64 bytes from 192.168.1.12: icmp_seq=5 ttl=64 time=2.72 ms [root@zz ~]# ping -c 3 -i 3 192.168.1.12 #<==== -c:ping次数 -i:每次ping的间隔 PING 192.168.1.12 (192.168.1.12) 56(84) bytes of data. 64 bytes from 192.168.1.12: icmp_seq=1 ttl=64 time=5.49 ms 64 bytes from 192.168.1.12: icmp_seq=2 ttl=64 time=3.64 ms 64 bytes from 192.168.1.12: icmp_seq=3 ttl=64 time=3.13 ms --- 192.168.1.12 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 6007ms rtt min/avg/max/mdev = 3.139/4.092/5.492/1.012 ms注:ping命令的输出信息中含有TTL值。TTL(Time To Life)称为生存期,它是ICMP报文在网络上的存活时间。不同的操作系统发出的ICMP报文的生存期各不相同,常见的生存期为32、64、128和255等。TTL值反映了ICMP报文所能够经过的路由器数目,每经过一个路由器,路由器都会将其数据包的生存期减去1,如果TTL值变为0,则路由器将不再转发此报文。 traceroute命令用于显示网络数据包传输到指定主机的路径信息,追踪数据传输路由状况。默认数据包大小是60字节(IPv4)或80字节(IPv6),用户可另行设置。它与Windows下的tracert命令类似。[root@zz ~]# traceroute juejin.cn traceroute to juejin.cn (61.174.42.228), 30 hops max, 60 byte packets 1 gateway (192.168.1.1) 7.137 ms 7.088 ms 7.012 ms 2 1.72.65.222.broad.xw.sh.dynamic.163data.com.cn (222.65.72.1) 10.522 ms 10.495 ms 11.113 ms 3 61.152.54.133 (61.152.54.133) 9.409 ms 9.369 ms 9.305 ms 4 101.95.88.142 (101.95.88.142) 9.747 ms 61.152.25.202 (61.152.25.202) 9.198 ms 61 ..... 8 * * *注:记录按序列号从1开始,每个记录就是一跳,每跳表示一个网关,我们看到每行有3个时间,单位是ms,其实就是-q的默认参数值为3。探测数据包向每个网关发送3个数据包之后,网关响应并返回的时间。 有时我们traceroute一台主机时,会看到有一些星号。出现这样的情况,可能是因为网络设备封掉或丢弃了返回的信息,所以我们得不到返回的时间。arping命令是用于发送arp请求到一个相邻主机的工具,arping使用arp数据包检查局域网内所有设备的硬件地 址。[root@zz ~]# arping -f 192.168.1.12 #<=== -f 表示第一次收到返回就结束了 ARPING 192.168.1.12 from 192.168.1.10 enp0s25 Unicast reply from 192.168.1.12 [64:90:C1:35:D0:2E] 5.241ms Sent 1 probes (1 broadcast(s)) Received 1 response(s)配置网络(启用、禁用网络接口、配置路由、激活、禁用),主要有以下命令:ifconfig(配置网络)ifup(激活网络接口) ifdown(禁用网络接口) ip(网络配置工具)//ifup+网卡名:激活网络接口 [root@zz ~]# ifup enp0s25 //ifdown + 网卡名:禁用网络接口 [root@zz ~]# ifdown enp0s25网络监听:tcpdump(监听网络流量)tcpdump命令是一个截获网络数据包的包分析工具。tcpdump可以将网络中传送的数据包的“头”完全截获下来以提供分析。[root@zz ~]# tcpdump #<====查看所有网络流量> tcpdump: ve .... 10 packets captured 11 packets received by filter 0 packets dropped by kernel [root@zz ~]# tcpdump -i enp0s25 port 8080 #<====指定端口监听> tcpdump: verbose output suppressed, use -v or -vtcpdump是一个非常强大并且好用的命令,这是只做简单的介绍,后续还要在实践中多多练习。邮件相关:mail(发送和接收邮件) mailq(显示邮件传输队列),mail命令是命令行的电子邮件发送和接收的工具。mail命令是个软链接,真实的程序文件是mailx: mail命令会默认使用本地postfix(sendmail)发送邮件,这就要求本地的机器必须安装和启动相关服务,这样不仅配置非常麻烦,而且还会带来不必要的资源占用。还有一个问题,很多时候,所发送的邮件会被视为垃圾邮件[root@zhaokai ~]# mailq Mail queue is empty [root@zhaokai ~]# mailq -v postqueue: name_mask: all ... [root@zhaokai postfix]# mail -s "Hello qq" zhaokai1155@outlook.com #<====mail -s指定邮件主题,知否输入邮件内容,按Ctrl + D发送 this is a mail; EOT
文章
域名解析  ·  缓存  ·  监控  ·  网络协议  ·  Linux  ·  网络架构  ·  Windows
2023-01-16
浏览器工作原理总结-页面渲染篇
前言在前段时间的面试中,许多候选人对于浏览器中代码的执行过程都不甚了解,多数是只停留在知道个大概。最近正好在极客时间上拜读了大神的浏览器工作原理,读完对浏览器工作原理有种豁然开朗之感,趁有空余时间就把自己对这块的理解整理了一下,希望对各位小伙伴能有所帮助吧。 相关知识内存空间在浏览器中JavaScript的执行空时的存储空间可分为三种:代码空间、栈空间、堆空间。代码空间:存储可执行代码栈空间:JavaScript代码编译执行时候创建的执行上下文存储位置,主要存储原始类型的数值,以及引用类型的引用。栈帧:是指为一个函数调用单独分配的那部分栈空间。堆空间:在对内存中数据的存储是无序,并且每个存储在堆空间的数据都是具备唯一的索引值的,我们可以根据索引取到其真正的值。例如在js的对象数据类型:我们把对象的引用存储在栈中,这样就不会因为对象占用过大内存导致性能的问题。所以在操作对象时,实际上操作的都是对象的引用(地址指针)。注意:栈的含义有以下几种借鉴畅畅_f7af的文章含义一:数据结构 stack的第一种含义是一组数据的存放方式,特点为LIFO,即后进先出(Last in, first out)。 含义二:代码运行方式 stack的第二种含义是"调用栈"(call stack),表示函数或子例程像堆积木一样存放,以实现层层调用。 含义三:内存区域 stack的第三种含义是存放数据的一种内存区域。程序运行的时候,需要内存空间存放数据。一般来说,系统会划分出两种不同的内存空间:一种叫做stack(栈),另一种叫做heap(堆)JavaScript代码执行调用栈:在JavaScript中由于它是单线程所以在执行函数时候会产生一个调用栈,在JavaScript代码执行时(当调用某一个函数时此函数会进入调用栈)会压入调用栈,执行完成时候会弹出调用栈,这也就是我们JavaScript中函数的一个生命周期。 队列:在JavaScript中我们都了解的事件机制(点击 鼠标移动 dom加载等等),而事件执行的方式肯定不能是采用调用栈的方式来,他实际的结构是队列的方式执行的,即先进先出,后进后出。 浏览器中的进程注:JavaScript执行是单线程的,浏览器是多进程的进程:现在浏览器打开时一般都会执行多个进程,处理主进程外大概有如下几个,插件进程/网络进程/渲染进程。线程:线程是一条执行路径,是程序执行时的最小单位,它是进程的一个执行流,是CPU调度和分派的基本单位,一个进程可以由很多个线程组成,线程间共享进程的所有资源,每个线程有自己的堆栈和局部变量。线程由CPU独立调度执行,在多CPU环境下就允许多个线程同时运行。同样多线程也可以实现并发操作,每个请求分配一个线程来处理。单线程(为何js是单线程的):当浏览器中JS引擎被设计为多线程的,那么DOM之间必然会存在资源竞争,那么语言的实现会变得非常臃肿,在客户端跑起来,资源的消耗和性能将会是不太乐观的,故设计为单线程的形式,另外在浏览器如果是多线程的那用户在交互(操作DOM)时候会页面出现许多意想不到的显示。多线程:在htm5标准中提出了Web Worker多线程的操作,但是这个多线程是受控于主线程的并且不能操作页面上的DOM元素。页面渲染流程浏览器解析URL当我们在浏览器的导航栏中输入一个网站地址或者其他内容后会经历以下几个过程 判断输入是否是一个合法的url规则:通过特点的规则来判断输入的内容是否符合url规则组合成一个合法的url或调用浏览器默认的搜索引擎当前页面触发beforeunload事件:在去请求输入内容时候会触发当前页面的beforeunload事件,在这里我们可以停止浏览器的后续操作。浏览器发送http请求:此时浏览器的网络进程会查找本地缓存是否缓存了该资源。如果有缓存资源,那么直接返回资源给浏览器进程;如果在缓存中没有查找到资源,那么直接发起网络请求流程。在网络请求中浏览器会进行DNS解析以获取真实的服务器ip地址。。服务器返回相关数据响应数据处理进程开始解析响应头:浏览器会获取当前请求的返回状态码如果等于200会继续进行下一步,如果非200则会进行对应的数据处理,例:301/302会进行跳转处理。浏览器解析响应类型:请求状态码为200时候浏览器会去读取响应类型,根据浏览器的响应类型来判断下一步的处理逻辑,如果是text/html则进入准备渲染阶段。进入准备页面渲染阶段页面渲染处理渲染进程启动:浏览器的渲染进程通常是一个tab就会启动一个渲染进程,以下情况时候多个tab会共用一个渲染进程,1.如果从 A 页面打开 B 页面,且 A 和 B 都属于同一站点的话,那么 B 页面复用 A 页面的渲染进程;2.打开多个空白的tab页面 如图所示,此时我的浏览器知识开了两个tab页。渲染进程获取返回的html文件:浏览器主进程会把网络进程获取到的数据通过进行数据通道交给渲染进程(注:此时浏览器还没有刷新),渲染进程接受完之后会告诉浏览器主进程接受完毕,此时开始浏览器主进程开始更新整个页面。页面解析和加载:构建DOM 树=》样式计算=》布局=》分层=》绘制=》分块=》光栅化和合成构建DOM树:样式计算:把 CSS 转换为浏览器能够理解的结构=》转换属性值=》计算DOM中的样式。最终得到的如图所示布局:创建(遍历页面所有DOM节点)=》计算(根据css相关属性计算DOM节点的位置)注:布局的创建和计算非常复杂,对网站的性能消耗也是最大的。分层:我们需要知道浏览器中的页面是分层的,在绘制之前我们应当要理清楚布局树的层级关系 注:此图片来自极客时间绘制:渲染引擎开始绘制DOM图块光栅化和合成:图块转换为位图(这块是美术知识后面打算了解下去)注:本节主要说明基本流程,详细的过程会在下面的章节中分享总结本章节主要介绍了浏览器(chrome)原理的基础知识,希望能帮助大家在去了解浏览器原理时候更容易去看懂。
文章
存储  ·  Web App开发  ·  缓存  ·  JavaScript  ·  前端开发  ·  网络协议  ·  搜索推荐  ·  数据处理  ·  调度  ·  索引
2023-01-16
计算机科学速成课 Crash Course Computer Science 笔记(摘要形式)
计算机科学速成课 Crash Course Computer Science 笔记(摘要形式)计算机早期历史1.公认最早的计算设备是算盘,发明于美索不达米亚平原。存储当前的计算状态,类似于现在的硬盘。2.computer最早是指计算的人。3.1694年莱布尼茨制作步进计算器,计算部分由齿轮构成。可以完成四则运算,流行了三个世纪。4.20世纪以前普通大众中流行计算表,并流行于军队。5.历史学家制作差分机,有了自动计算机的概念,预示了计算机的诞生。6.hollerith将机械计算器电动,IBM成立。电子计算器1.早期计算设备有特定的用途,例如制表机。2.最大的机电计算机哈佛马克一号,大脑为继电器。3.继电器为用电控制的机械开关。有控制线路,上面有电磁铁,可以吸引导线,用来控制电路是开还是关。缺点:机械臂有重量,不能迅速开关,难以处理复杂问题。速度慢有齿轮磨损。继电器越多故障越多。4.1904年,约翰安布罗斯弗莱明开发"热电子管"。电子单向流动是二极管。1906年,发明了第三个控制电极。5.三极真空管成为了无线电,长途电话等的基础。6.计算机由机电转向了电子。7."巨人一号"大规模使用真空管,可以编程了,编程的方法是把几百根电线插入插板,需要配置。8.1946年埃尼阿克诞生,第一个真正的电子计算机。也是真空管计算机。9.1947年发明晶体管,新的计算机时代诞生了。导致产生了更小的计算机,如1957年的IBM 608。布尔逻辑和逻辑门1.机械计算机是10进制,晶体管计算机2进制。2.电路通是真,断是假。3.一些早期计算机是三进制,五进制。状态越多越难区分。4.”与“门是两个晶体管串联,“或”门是两个晶体管并联。5.“异或”简称“XOR”,两个输入一真一假才能输出真。二进制1.二进制中一个“1”或“0”叫一个位bit。2.8位为一个字节Byte,八位机就是计算机里大部分操作都是8位8位这样处理的。3.1Byte=8bit,还有kb千字节,mb兆字节,gb千兆字节。4.现在多为三十二位机和六十二位机。5.32位浮点数中,第一位表示数字的正负,接下来的八位存指数,剩下来的存有效数字。6.ASCII美国信息交换标准代码,ASCII是七位代码,可以存128个不同值,其中包含有换行符,大小写字母数字和标点符号。是比较早的通用标准。缺点是为了英语设计的。7.为了解决不同语言的问题,每个国家都发明了多字编码方案,但是每种都不兼容。会遇到乱码(mojibake)。8.1992年,Unicode诞生,有十六位,超过一百万个位置。所有语言的字符都够用了,甚至有emoji。算术逻辑单元1.算术操作由计算机“算术逻辑单元”处理,简称ALU。2.ALU有两个单元,一个算术单元,一个逻辑单元。3.算术单元负责所有数字操作。4.可以把XOR用作1位加法器。5.半加器6.全加器7.计算八位二进制的全加器叫做“8位行波进位加法器”。如果相加进位至第九位,则溢出(overflow)。寄存器&内存1.锁存器可以存一位,之所以叫“锁存”,是因为它“锁定”了一个值。2.放入数据叫“写入”,拿出数据叫“读取”。3.GATED LATCH门锁连接允许写入线,可以控制是否允许输入。允许写入线输入1时,输出数据与输入数据一致,允许写入线为0时,输出数据不再改变。4.寄存器(register)可以存一个数字,数字的位数叫做“位宽”。5.寄存器中用一根线连接所有的“允许输入线”。6.寄存器位宽足够大时,使用门锁矩阵。7.“多路复用器”可以把地址转成行和列。8.可以将内存不断打包到更大的规模。9.RAM随机存取存储器,记录短期记忆。10.SRAM静态随机存取存储器。CPU1.CPU负责执行程序。2.高层次视角叫“微体系构架”。3.寄存器用来临时存数据和操作数据。4.“指令地址寄存器”追踪程序运行到哪里了,存当前指令的内存地址。5.“指令寄存器”存当前指令。6.CPU的第一阶段“取指令阶段”,首先“指令地址寄存器”连到RAM,RAM返回该地址的值,并复制到“指令寄存器”里。7.不同的指令由不同的逻辑电路解码。例如执行LOAD_A指令:首先“指令地址寄存器”连到RAM,RAM返回该地址的值,并复制到“指令寄存器”里。进入解码阶段,前四位是LOAD_A指令,后四位是RAM的地址。指令由控制单元解码。检查是否为LOAD_A指令的电路,启用寄存器A的”允许写入线。最后,将指令地址寄存器+1,“执行阶段”结束。8.“指令寄存器”,“指令地址寄存器”,解码电路共同构成了“控制单元”,控制单元“指挥”CPU的所有组件。9.0010为LOAD_A指令,0001为LOAD_B指令10.1000为ADD指令,后面两位不是RAM地址而是分别代表两个寄存器,相加结束后,控制单元用一个寄存器暂时保存结果,关闭ALU后,把值存入正确的寄存器。11.0100是STORE_A指令,把寄存器A的值放入内存,让寄存器允许读取,RAM允许写入。12.时钟以精确的间隔,触发电信号,控制单元用这个信号,推进CPU的内部操作。13.赫兹用来表示频率,1赫兹表示一秒1个周期。14.计算机超频是通过修改时钟速度,加快CPU的速度。15.芯片制造商往往会给CPU留一点余地,让CPU超频,过多超频会让CPU过热,或者产生乱码,因为信号跟不上时钟。16.降频可以省电。17.RAM独立于CPU之外,用“地址线”,“数据线”和“允许读写线”连接。指令和程序1.CPU是可编程的。2.执行ADD指令时,寄存器的顺序很重要,决定结果放在哪里。3.SUB减法指令4.JUMP跳转指令,可以改变指令顺序,跳过一些指令。5.JUMP_NEG只在ALU的“负数标志”为真时,进行JUMP。就是结果是负数时跳过。条件跳转还有JUMP IF EQUAL和JUMP IF GREATER。6.HALT,能区分指令和数据。7.现在指令长度不断增加。8.还有一种解决方法是“可变指令长度”。高级CPU设计1.早期计算机的提速方法是减少晶体管的切换时间。2.现代处理器有专门电路来处理图形操作,解码压缩视频,加密文档等。3.CPU和RAM传递数据的线叫做“总线”。4.解决CPU读取RAM信息延迟的方法给CPU是加一点RAM,叫缓存(cache)。缓存一般只有kb或mb。5.缓存离CPU近,一个时钟周期就能给数据。6.CPU想要的数据已经在缓存,叫“缓存命中(cache hit)”。不在缓存,叫“缓存未命中(cathe miss)”。7.缓存可以存中间值。方便存储方便进一步读取计算。8.缓存中的每块空间,都有一个特殊标记,叫”脏位“(DIRTY RIT)。9.清理缓存时,先检查”脏位“。如果”脏“,把数据写入RAM。10.”指令流水线“,取值—解码—执行,让每一个步骤同时进行来提高效率。11.”指令流水线“有一定的问题例1:读取某个数据时,正在执行的指令会修改这个数据。所以必要时会停止流水。例2:条件跳转会改变顺序。遇到JUMP也会暂停流水,直到JUMP出来结果,继续流水。高端CPU会猜测哪种可能性更大,然后提前放入指令,进行”推测执行“。如果猜错,清空流水线。还有”分支预测“,可以减少猜错。12.同时运行多个指令流也可以提供性能。增加CPU的核数,或者增加CPU数量。用大量的CPU可以做超级计算机。早期的编程方式1.早期汇总机不能编程。2改良的汇总机用插线板编程。3.”存储程序计算机“,可以存储程序。4.”冯诺依曼结构“的程序和数据都存在一个地方,早期冯诺依曼结构计算机用穿孔卡片编程。5.1980年代以前,面板编程比较常见。编程语言发展史1.机器语言2.对程序的高层次描述是“伪代码”。3.1940-1950年,使用助记符,“助记符”后面紧跟数据,形成完整指令。4.通过写二进制程序使电脑可以读懂文字指令,自动转成二进制指令,这种程序是“汇编器”。可以读取汇编语言。5.汇编语言不用固定跳转地址,而是插入了可跳转的标签。6.汇编语言只是修饰了机器语言,一般来说,一条汇编指令对应一条机器指令。程序员需要思考用什么寄存器和内存地址。7.“算术语言版本0”,简称“A-0”。8.高级语言不用管寄存器和内存地址。9.“FORTRAN”主宰来早期编程。10.数据系统语言委员会开发了“普通面向商业语言”,简称COBOL。11.60年代,有ALGOL,LISP,BASIC等语言。12.70年代有Pascal,C和Smalltalk。13.80年代有C++,Objective-C和Perl。14.90年代有Phthon,Java和Ruby。15.新千年Swift,C#,Go在崛起。编程原理-语句和函数1.控制语句流。2.可以把代码打包成函数。算法入门1.记载最多的算法是排序sorting例如冒泡排序2.算法复杂度用大O表示法。冒泡排序的复杂度高,不适合处理大量数据3.归并排序4.图搜索改进后复杂度为O(nlog n+l),n为节点数目,l是线条数目。导航找最佳路线用到图搜索。数据结构1.基本的一种数据结构:数组(ARRAYS),在有些编程语言里也叫列表(list)或者(Vector)。2.下标(index),下标从零开始。3.字符串(string)。4.数组以NULL结尾。5.strcat连接两个数组。6.数组可以有多个下标7.多个变量打包在一起叫结构体。8.一种结构体叫节点(node),存一个变量一个指针。9.用节点可以做链表,链表是一种灵活的数据结构,可以存很多节点(node)。每一个节点指向下一个节点。10.链表可以是循环列表,也可以不循环,最后一个值是0。11.链表很容易重新排序,两端缩减,分割,倒序。12.复杂的数据结构用链表,例如队列(queue)和栈(stack)。13.结构体中放一个变量,两个指针构成了变量类型“树”。有根节点和子节点。“树'是单向的。14.如果要随意连接,就构成了“图”(chart)。15.还有“红黑树”和“堆”更多的类型。艾伦图灵1.图灵机(Turing Machines)是一台理论计算设备。2.“图灵完备”(Turing Complete),微波炉和恒温器的小电脑都是“图灵完备”。黑客与攻击1.“NANA镜像”,物理接触到电脑,往内存上接几根线,复制整个内存。2.常见的漏洞利用叫“缓存区溢出”。用“边界检查”可以解决。4.可以在缓存区留一些位置,跟踪里面的值,看是否发生变化,来识别是否有入侵者。这些内存空间就做“金丝雀”(CANARIRS),因为以前金丝雀下矿会警告危险。5.另一种手段叫“代码注入”常用于攻击用数据库的网站。6.软件制造者不知道的新漏洞叫“零日漏洞”。7.有足够多的电脑有漏洞,让恶意程序在电脑间互相传播,叫“蠕虫“。8.黑客攻下足够多的电脑,可以组成“僵尸网络”。可以发起“拒绝服务攻击”简称DDoS,攻击服务器。加密1.系统架构师会部署“多层防御”(defense in depth)。2.计算机安全中常见的防御形式是密码学(cryptography)。3.“加密”和“解密”。4.“替换加密”,缺点是不会改变数据的频率信息。熟练的密码破译师可以从统计数据中发现规律,进而破译密码。5.“移位加密”6.2001年出了:高级加密标准(AES)。7.防止密钥被截获,解决办法是“密钥交换”。编程语言发展史1.机器语言2.对程序的高层次描述是“伪代码”。3.1940-1950年,使用助记符,“助记符”后面紧跟数据,形成完整指令。4.通过写二进制程序使电脑可以读懂文字指令,自动转成二进制指令,这种程序是“汇编器”。可以读取汇编语言。5.汇编语言不用固定跳转地址,而是插入了可跳转的标签。6.汇编语言只是修饰了机器语言,一般来说,一条汇编指令对应一条机器指令。程序员需要思考用什么寄存器和内存地址。7.“算术语言版本0”,简称“A-0”。8.高级语言不用管寄存器和内存地址。9.“FORTRAN”主宰来早期编程。10.数据系统语言委员会开发了“普通面向商业语言”,简称COBOL。11.60年代,有ALGOL,LISP,BASIC等语言。12.70年代有Pascal,C和Smalltalk。13.80年代有C++,Objective-C和Perl。14.90年代有Phthon,Java和Ruby。15.新千年Swift,C#,Go在崛起。编程原理-语句和函数1.控制语句流。2.可以把代码打包成函数。算法入门1.记载最多的算法是排序sorting例如冒泡排序2.算法复杂度用大O表示法。冒泡排序的复杂度高,不适合处理大量数据3.归并排序4.图搜索改进后复杂度为O(nlog n+l),n为节点数目,l是线条数目。导航找最佳路线用到图搜索。数据结构1.基本的一种数据结构:数组(ARRAYS),在有些编程语言里也叫列表(list)或者(Vector)。2.下标(index),下标从零开始。3.字符串(string)。4.数组以NULL结尾。5.strcat连接两个数组。6.数组可以有多个下标7.多个变量打包在一起叫结构体。8.一种结构体叫节点(node),存一个变量一个指针。9.用节点可以做链表,链表是一种灵活的数据结构,可以存很多节点(node)。每一个节点指向下一个节点。10.链表可以是循环列表,也可以不循环,最后一个值是0。11.链表很容易重新排序,两端缩减,分割,倒序。12.复杂的数据结构用链表,例如队列(queue)和栈(stack)。13.结构体中放一个变量,两个指针构成了变量类型“树”。有根节点和子节点。“树'是单向的。14.如果要随意连接,就构成了“图”(chart)。15.还有“红黑树”和“堆”更多的类型。艾伦图灵1.图灵机(Turing Machines)是一台理论计算设备。2.图灵机是一台理论计算设备3.组成:无限长的纸带(纸带可以存储符号),读写头,状态变量(保存当前状态),一组规则4.规则是根据 当前状态+读写头看到的符号,决定机器做什么(在纸带上写入一个字符,或者读写头移动一格,或者都执行)5.“图灵完备”(Turing Complete),微波炉和恒温器的小电脑都是“图灵完备”。6.有足够的时间和内存,图灵机可以执行任何计算7.停机问题是无法解决的8.丘奇和图灵证明了计算机的能力有极限,无论有多少时间和内存,有些问题是计算机无法解决的起步了可计算性理论——“丘奇-图灵论题”9.“图灵测试”是智能测试的基础软件工程1.把大项目分解成小函数,可以让多人同时工作,不用关心整个项目2.把函数打包成层级,把相关代码都放在一起,打包成对象(objects)3.把函数打包成对象的思想叫“面向对象编程”4.需要制作文档,以及定义好的“程序编程接口”,简称API可以帮助不同程序员合作,不用知道具体细节5.面向对象的编程语言可以指定函数是public或private,来设置权限6.“面向对象编程”的核心是隐藏复杂度,选择性公布功能7.集成开发环境IDE,提供实时检查,可以编译和运行代码8.程序员需要给代码写文档,存在一个叫READER的文档里9.文档可以提高复用性,其他程序员可以用代码解决自己的问题10.源代码管理,也叫“版本控制”,把代码放在中心服务器上源代码管理可以跟踪所有变化,发现bug,可以回滚到之前的稳定版11.测试统称为“质量保证测试”,简称QA12.beta版本是软件基本完成,但没有100%通过,有些公司将这个版本向公众发布13.alpha版本是错误很多的粗糙的版本集成电路&摩尔定律1.1940年代~1960年代中期,计算机由独立部件组成,叫“分立元件”问题:“数字暴政”2.晶体管是分立元件,晶体管标志着“计算2.0时代”到来3.集成电路IC,思路是封装复杂性,采用了半导体4.印刷电路板PCB,通过蚀刻金属线的方式5.IC和PCB结合使用,可以大幅减少独立组件和电线6.光刻技术(用光把复杂图案印到材料上),7.在硅片顶部加一层氧化层,作为保护层,上面再加一层“光刻胶”(被光照射后变得可溶,可以用特殊化学药剂洗掉)上面加一层“光掩膜”8.用光照射,使氧化层被溶解,再用一种化学物质,洗掉氧化层露出的部分,蚀刻到硅层,再洗掉光刻胶9.改变硅露出来的部分,用化学过程改变,叫“掺杂”,用高温气体来做,渗透进硅,改变电学性质10.摩尔定律:每两年左右,材料和制造技术发展,同样大的空间,能塞进两倍数量的晶体管11.晶体管越小,耗电越少,信号延迟越小12.1970年,VLSI来自动生成芯片设计13.用“逻辑综合”技术,可以放一整个高级组件,比如内存缓存14.摩尔定律会终结光掩模把图案弄到晶圆上,由于光的波长,精度已达极限量子隧穿效应操作系统1.“操作系统”是为了让计算机自动运作2.“操作系统”也是程序,有操作硬件的特殊权限,可以操作管理其他程序,开机第一个启动的程序3.“批处理”4.计算机连接其他”外部设备“5.操作系统提供软件和硬件的媒介,操作系统提供API来抽象硬件,叫“设备驱动程序”6.Atlas让多个程序同时进行,操作系统的这种能力叫“多任务处理”需要给每个程序分配内存7.“虚拟内存”,隐藏物理内存8.“动态内存分配”使得内存大小可以灵活增减9.内存保护10.分时操作系统11.Unix首先是操作系统的核心功能,叫内存管理,多任务的输入/输出处理,这叫“内核”,第二部分是有用的工具12.“内核恐慌”内存&存储介质1.写入存储器(Storage)的数据,数据会一直存着,断电也不会丢失2.最早的内存是打孔纸带3.延迟线存储器,也叫“顺序存储器”或“循环存储器”等待一个特定的bit,需要等待它从循环中出现4.“磁致伸缩延迟存储器”5.“磁芯存储器”每个磁芯收到电流磁化,电流不同,磁化方向不同,可以存储1和0。一个磁芯存1位,列成矩阵可以存大量数据。可以访问任意一位。6.磁带,用电流磁带每部分磁化方向不同,在不破坏地读取磁性磁带是连续的,必须倒带或者快进才能到特定位置7.“磁鼓存储器”8.磁盘,寻道时间较短9.软盘10.激光盘11.光盘,光盘表面有很多小坑,造成光的不同反射,光学传感器捕获解码为1和012.硬盘,U盘里面是集成电路文件系统1.“文件格式”txt 文本文件wave文件,读取数据前需要知道码率,单声道还是立体声Bitmap 后缀.bmp,用来存图片2.关于数据的数据叫“元数据”,存在文件开头,在实际数据前面,叫文件头Header3.文件连续存储,目录文件存在开头,目录文件还存文件信息属于“平面文件系统”4.现代文件系统把空间分成一块块,导致一些“预留空间”方便改动5.删除文件只是删除了记录,在写入其他文件数据前原来数据还存在6.增删减文件会导致碎片,不可避免7.碎片整理,可以清理碎片8.所有文件和目录都在根目录下压缩1.压缩会让文件更小,用更少的位来表示数据2.减少重复信息,最简单的方法是游程编码(Run-Length Encoding)3.另一种方法是“用更紧凑的表示方法”“霍夫曼树”,每次选频率最低的两个,放在一起,并记录总频率属性:按频率排列每个分支用0和1表示可以制作字典,将数据按字典中的二进制保存4.游程编码和字典编码都是无损压缩,压缩时不会丢失信息,解压后,数据和之前完全一样5.有些文件丢掉一些数据没关系,大多数有损压缩技术都用到了这点比如声音文件中的超声波6.删掉人类无法感知的数据的方法,叫“感知编码”7.时间冗余,找出帧和帧之间相似的补丁,用简单的效果实现,比如移动和旋转,变亮和变暗命令行界面1.“人机交互”学科2.大型计算机能同时支持多个程序和多个用户,叫做“多任务”和“分时系统”3.QWERTY键盘布局不是通用的,法国AZERTY布局,中欧常见QWERTZ布局4.十字打字,“十指盲打”,专业打字员每分钟100字以上5.电传打字机6.电传交互界面在1960~1970很常见,输入一个命令,按下回车,然后计算机会输出来,这叫“命令行界面”7.1970年,屏幕代替电传打字机8.交互文字游戏 Zork压缩1.压缩会让文件更小,用更少的位来表示数据2.减少重复信息,最简单的方法是游程编码(Run-Length Encoding)3.另一种方法是“用更紧凑的表示方法”“霍夫曼树”,每次选频率最低的两个,放在一起,并记录总频率属性:按频率排列每个分支用0和1表示可以制作字典,将数据按字典中的二进制保存4.游程编码和字典编码都是无损压缩,压缩时不会丢失信息,解压后,数据和之前完全一样5.有些文件丢掉一些数据没关系,大多数有损压缩技术都用到了这点比如声音文件中的超声波6.删掉人类无法感知的数据的方法,叫“感知编码”7.时间冗余,找出帧和帧之间相似的补丁,用简单的效果实现,比如移动和旋转,变亮和变暗命令行界面1.“人机交互”学科2.大型计算机能同时支持多个程序和多个用户,叫做“多任务”和“分时系统”3.QWERTY键盘布局不是通用的,法国AZERTY布局,中欧常见QWERTZ布局4.十字打字,“十指盲打”,专业打字员每分钟100字以上5.电传打字机6.电传交互界面在1960~1970很常见,输入一个命令,按下回车,然后计算机会输出来,这叫“命令行界面”7.1970年,屏幕代替电传打字机8.交互文字游戏 Zork屏幕&2D图形显示1.文本图形和文字图形最早是分开的,屏幕不清晰2.早期屏幕的典型用途:跟踪程序的运行情况(比如寄存器的值)3.阴极二极管,电子路径由磁场控制,将电子变换方向打在屏幕上引导电子束描绘形状,叫“矢量扫描”按固定路径来,一行一行来,从上向下,从左到右,不断重复,叫“光栅扫描”4.屏幕上显示清晰的点叫“像素”5.液晶显示器LCD,采用光栅扫描6.早期计算机不用像素,像素占太多内存7.早期计算机不存像素存字符8.“字符生成器”从内存读取字符,转换成光栅图形9.ROM只读存储器,存着每个字符的图形,叫“点阵图案”10.“字符显示器”会访问屏幕缓冲区11.有人用字符模仿图形界面12.可以用“矢量指令”画“矢量图形”13.Sketchpad是一个交互式图形界面,用途是计算机辅助设计CAD用了输入设备光笔可以让线条完美平行,长度相同,完美垂直90度,动态缩放是人机交互的转折点14.真正像素的计算机和显示器出现在1960年代末,用内存中的位对应屏幕上的像 素,叫位图显示,早期存在“帧缓存区”,早期时,这些数据存在高速视频内存 里,简称VRAM冷战和消费主义1.二战促进了计算机发展2.美国国家科学基金会负责给研究提供资金3.贝尔获得了晶体管的授权4.苏联计算机发展比较落后5.真空管和晶体管无法适应太空环境,NASA采用了集成电路6.军事洲际导弹推动了集成电路大规模生产7.日本半导体在60年代靠低利润率占领了消费者市场,导致美国公司倒闭8.英特尔把精力转向处理器9.廉价的微处理器催生了新的产品,不如街机游戏个人计算机革命1.单芯片CPU强大,体积小,便宜2.成本小,性能提高导致个人电脑出现3.解释器4.Altair8800有Basic解释器,催生了更多的计算机爱好者5.苹果公司选择了“封闭架构”,自己设计一切,用户无法加新硬件到计算机中图形用户界面1.早期的交互式图形程序是一次性项目,没有良好的体验2.施乐奥托有图形界面3.Alto团队用窗口,图标,菜单和指针来做,叫WIMP界面4.GUI是“事件驱动编程”,不是自上而下执行,代码可以在任意事件执行,以影响事件5.1981年发布了施乐之星系统6.Windows 95有“多任务”和‘’受保护内存“7.Microsoft Bob页面不够简洁,失败3D图形1.图形算法负责把3D坐标拍平显示到2D屏幕上,叫3D投影2.正交投影透视投影3.填充图形的经典算法叫扫描线渲染,进行填充像素4.减轻锯齿的方法是抗锯齿,多边形里面的像素直接填充,边上的填充浅颜色的5.3D中存在遮挡从远到近排序,先填远的深度缓冲:将多边形的距离对比,记录小的,如果距离一样,结果不可预测6.背面剔除:忽略多边形背边,减少一半运算7.明暗处理:考虑多边形面对的方向,他们面对的方向叫“表面法线“,根据其余光源的关系确定明暗8.纹理纹理映射:查询纹理,取平均颜色,并填充多边形9.图形的专门处理器GPU“图形处理单元”,在显卡上,周围有RAM,有多个核心计算机网络1.第一个网络在1950~1960年诞生,“球鞋网络”可以共享存储器和硬件设备2.1970年前计算机大多是单独工作的计算机近距离构成的小型网络叫局域网,简称LAN最成功的是“以太网”以太网需要计算机有唯一的媒体访问控制地址,简称MAC地址这个唯一的地址放在头部,作为数据的前缀发送到网络中计算机只需要监听以太网电缆多台电脑共享一个传输媒介,这种方法叫“载波侦听多路访问”,简称“CSMA”载体传输数据的速度叫“带宽”4.计算机能够监听电线中的信号检测冲突,停止传送信息但是很多计算机都会抢停顿间隔,导致越来越多的冲突可以分配不同的等待时间,并进行指数退避5.载体和其中设备总称“冲突域”collision domain6.可以拆分冲突域,交换机位于两个更小的网络之间,必要时才在两个网络间传数据7.把电路连接到正确的目的地叫“电路交换”。8.路由"报文交换",消息会经过多个站点。可以用不同路由,使通信更可靠更能容错9.消息沿着路由跳转的次数叫“跳数”hop count跳数可以记录是否出错,如果某条消息跳数很高,就知道路由肯定哪里出错了,这叫“跳数限制”10.报文交换的缺点之一是报文有时比较大,会堵塞网络解决办法是将大报文分成很多小块,叫“数据包”,每个数据包都有目标地址报文的具体格式由“互联网协议”定义,简称IP11.每台电脑需要一个IP地址12.路由器会平衡与其他路由器之间的负载,叫“阻塞控制”13.IP上的TCP/IP可以解决乱序问题14.“分组交换”互联网1.计算机首先要连接到局域网LAN局域网再连接到广域网WAN,WAN的路由器一般属于你的“互联网服务提供商”简称ISP2.用Windows,Mac OS Linux系统,可以用traceroute来看跳了几次3.IP是基础的协议,数据包的头部只有目标地址,头部存“关于数据的数据”,也叫元数据4.需要更高级的协议,最简单的叫“用户数据报协议”简称UDP,头部包括有用的信息,信息之一是端口号,每个想访问网络的程序,都要向操作系统申请一个端口号还包括“校验和”,会将数据加起来,超过16位时,舍弃低位5.IP负责把数据包送到正确的计算机,UDP负责把数据包送到正确的程序6.所有数据必须到达,就要用“传输控制协议”,简称TCP,TCP有“端口号”和“校验和”TCP数据包有序号,所以可以解决乱序问题TCP要求接收方的电脑收到数据包并且校验和检查无误后,给对方发一个确认码ACK,代表收到了,一定时间没有收到确认码,会再发一次收件方可以删除重复数据包TCP可以调整同时发包数量,解决拥堵问题7.“域名系统”,简称DNS,顶级域名在最顶部,比如.com,下一层是二级域名,比如google.com,再下一层是子域名万维网(WORLD WIDE WEB)1.传输数据最多的程序是万维网2.万维网的最基本单位是单个页面页面有内容,也有去往其他页面的链接,这些链接叫“超链接”3.文字超链接也叫“超文本”超文本指向的通常是另一个网页4,为了使网页能够互相连接,每个网页需要一个唯一的地址,这个地址叫“统一资源定位器”URL5.“超文本传输协议”HTTP6.超文本标记语言HTML,有18种HTML指令7.层叠样式表(CSS)和JavaScript8.搜索引擎有三个部分爬虫,一个跟着链接到处跑的软件,每当看到新链接,就加进自己的列表里不断扩张的索引,记录访问过的网页上,出现过哪些词查询索引的搜索算法9.网络中立性应该平等对待所有的数据包计算机安全1.需要网络安全减少虚拟世界中的犯罪2.计算机安全可以看成是保护系统和数据的:保密性,完整性和可用性3.保密性是只有有权限的人才能读取计算机系统和数据4.完整性是只有有权限的人才能使用和修改系统和数据5.可用性是有权限的人应该随时可以访问系统和数据6.DDOS(拒绝访问攻击)是黑客发大量的假请求到服务器,让网络很慢或者挂掉,这是攻击可用性7.安全专家会从抽象层面想象“敌人”可能是谁,这叫“威胁模型分析”8.安全问题可以总结为两个问题:1.你是谁?2.你能访问什么?9.为了区分谁是谁,我们用“身份认证”(authentication)1.你知道什么2.你有什么3.你是什么10.暴力攻击(brute force attack):试遍一切可能一般系统会限制次数但是利用僵尸网络控制很多电脑可以多次尝试11.“双因素”或“多因素”认证12.身份验证后,来到了“访问控制”,访问权限通过”权限或“访问控制列表(ACL)来实现13.只能向上读,不能向下写的方法叫Bell-LaPadula模型14.系统级安全“安全内核”构建安全内核的挑战在于:决定内核应该有什么,代码越少越好15.“独立安全检查和质量验证”16“隔离”减少攻破后的损失黑客与攻击1.“NANA镜像”,物理接触到电脑,往内存上接几根线,复制整个内存。2.常见的漏洞利用叫“缓存区溢出”。用“边界检查”可以解决。4.可以在缓存区留一些位置,跟踪里面的值,看是否发生变化,来识别是否有入侵者。这些内存空间就做“金丝雀”(CANARIRS),因为以前金丝雀下矿会警告危险。5.另一种手段叫“代码注入”常用于攻击用数据库的网站。6.软件制造者不知道的新漏洞叫“零日漏洞”。7.有足够多的电脑有漏洞,让恶意程序在电脑间互相传播,叫“蠕虫“。8.黑客攻下足够多的电脑,可以组成“僵尸网络”。可以发起“拒绝服务攻击”简称DDoS,攻击服务器。加密1.系统架构师会部署“多层防御”(defense in depth)。2.计算机安全中常见的防御形式是密码学(cryptography)。3.“加密”和“解密”。4.“替换加密”,缺点是不会改变数据的频率信息。熟练的密码破译师可以从统计数据中发现规律,进而破译密码。5.“移位加密”6.2001年出了:高级加密标准(AES)。7.防止密钥被截获,解决办法是“密钥交换”。机器学习&人工智能1.机器学习算法让计算机可以从数据中学习,然后自行做出预测和决定2.大多数计算机科学家会说,机器学习是为了实现人工智能这个更宏大目标的技术之一3.做分类算法的算法叫“分类器”把数据简化为特征,“特征是用来帮助”分类“的值为了做出更好的判断,需要“训练数据”4.“决策边界”5.“混淆矩阵”可以记录正确数和错误数6.机器算法的目的是最大化正确分类+最小化错误分类7.“决策树”,生成决策树的机器学习算法需要选择用什么特征来分类8.“支持向量机”9.机器学习面临的问题:特征增多时,上千维度的决策空间,给超平面找出一个方程10.“支持向量机”和“决策树”来源于统计学11.人工神经网络,计算机模拟时不用化学信号电信号,而是利用数字。两个神经元最兴奋的是分类结果12.有输入层,输出层和隐藏层隐藏层负责把输入变成输出干分类这个重活13.神经元有激活函数,也叫传递函数,应用于输出,对结果执行最后一次数学修改14.加权,求和,偏置,激活函数,会应用于一层中每个神经元15.隐藏层可能不只有一层,可以有很多层,“深度学习”因此得名16.这种AI叫“弱AI”或“窄AI“,只能做特定的任务17.真正通用的,是像人类一样聪明的AI,叫“强AI”,目前为止没有做出来“强AI”18.有人认为强AI不能被做出来计算机视觉1.图像是像素的网格,每个像素的颜色,通过三种基色定义:红蓝绿2.记录下球的颜色,保存中心像素的RGB值,用算法检索每一帧每一个像素,最贴近的是球3.“核”或“过滤器”4.把核应用于像素块,这种操作叫“卷积”,“核”能锐化图像,能像饼干模具一样,匹配特定的形状5.这两个边缘增强的核叫“Prewitt算子”6.如今的热门算法是“卷积神经网络”,神经网络有多个神经元,神经网络可以用用来学习核来识别图像中的特征7.“卷积神经网络”用一堆神经元处理图像数据,“卷积神经网络”一般会有很多层,来识别复杂的物体和场景8.生物识别,跟踪标记点可以理解肢体行为9.抽象是构建复杂系统的关键自然语言处理1.“自然语言处理”NLP2.NLP的一个早期基本问题是怎么把句子切成一块块3.“短语结构规则”4.“分析树”5.数据块更小更容易处理6.“知识图谱”7.聊天机器人甚至可以发展出自己的语言8.“语音识别”,9.波形到频率的转换用快速傅立叶变换FFT10.构成单词的声音片段叫“音素”,英语有44种音素11.语音合成机器人-ROBOTS1.机器人时代已经到来2.机器人由计算机控制,可以执行一系列动作的机器3.有时叫虚拟人物“机器人”,叫“bot”和“agent”更合适4.来源robota(强迫劳动)斯拉夫语5.没有电肯定没有电子部件的机器,叫“自动机”6.“土耳其行棋傀儡”,像机械的人工智能,机器里有人控制7.第一台计算机控制的机器出现在1940年代晚期,计算机数控的机器简称CNC8.负反馈电路9.实际器件可能有惯性,不能精确的随时停止10.自然界中有外力,为了处理外力,需要更复杂的控制逻辑11.有个使用广泛的机制,有控制回路和反馈机制,叫“比例-积分-微分控制器”,一般简称“PID控制器”,以前是机械,现在是软件12.“比例值”,就是“实际值”和“理想值”差多少,偏差越多,越用力,是比例控制的。算积分值,就是一段时间内误差的总和,不够会继续用力,最后是“导数值”,是期望值与实际值之间的变化率,用来解决未来的变化,有时也叫“预期控制”三个值一起用,有不同的权重这些值由更高层次的软件而来应用比如车里面的巡航控制13.“无人驾驶”有智力并且能杀人的机器叫“致命自主武器”lethal autonomous weapons14.艾萨克阿西莫夫写了“机器人三定律”,之后又加了“定律0”计算机心理学1.理解人类的认知系统能帮助我们设计更好的界面2.分块是指把信息分成更小,更有意义的块3.人类的短期记忆能记住5到9个东西,,保守一点,分组一般是5个或更少,所以电话号一般分组4.“直观功能”为如何操作物体提供线索应该直观的知道怎么使用而不是加一些说明比如看到按钮就想到点击这是图形界面比命令行更容易用的原因之一5.与直观功能相关的一个心理学概念是”认出与回想“用感觉来触发记忆6.与心理学相冲突的是“专业知识”,建立如何高效完成事情的“心理模型”7.情绪会影响日常生活,比如学习,沟通和决策8.得到的数据会与计算模型结合使用,模型写明人类如何表达情感9.比起面对面交流,人们更愿意在网上透露自己的信息10.如果想说服,讲课,引起注意,眼神注视非常重要11.“增强凝视”,比如纠正摄像头的位置12.人机交互HRI,研究人机交互的领域,比如人类如何感受机器人的不同形式和不同行为13.类人机器人,这个“几乎像人类”和“真的人类”之间的小曲线,叫“恐怖谷”教育科技1.可以倍速暂停2.“大型开放式在线课程”MOOC3.缺点:没有好的反馈4.“智能辅导系统”5.“判断规则“加选择算法,组合在一起成为”域模型“6.智能辅导系统负责创建和维护学生模型7.“贝尔斯知识追踪”奇点,天网,计算机的未来1.“普适计算”的愿景2.人工智能3.智能科技失控性发展叫“奇点”4.“复杂度刹车”,随着复杂度的增加,发展减慢5.“技术性失业”6.从生物体变成数字体,可能是下一次进化跨越
文章
机器学习/深度学习  ·  存储  ·  缓存  ·  人工智能  ·  安全  ·  算法  ·  网络协议  ·  机器人  ·  程序员  ·  数据安全/隐私保护
2023-01-16
ZYNQ裸板:AXIDMA篇(简单模式)
前言  DMA(Direct Memory Access,直接存储器访问)是计算机科学中的一种内存访问技术。它允许某些计算机内部的硬件子系统可以独立地直接读写系统内存,而不需中央处理器( CPU)介入处理。 DMA 是一种快速的数据传送方式, 通常用来传送数据量较多的数据块  使用 DMA时, CPU 向 DMA 控制器发出一个存储传输请求, 这样当 DMA 控制器在传输的时候, CPU 执行其它操作,传输操作完成时 DMA 以中断的方式通知 CPU。  为了发起传输事务, DMA 控制器必须得到以下数据:• 源地址 — 数据被读出的地址• 目的地址 — 数据被写入的地址• 传输长度 — 应被传输的字节数DMA 存储传输的过程如下:为了配置用 DMA 传输数据到存储器,处理器发出一条 DMA 命令DMA 控制器把数据从外设传输到存储器或从存储器到存储器,而让 CPU 腾出手来做其它操作。数据传输完成后,向 CPU 发出一个中断来通知它 DMA 传输可以关闭了。ZYNQ 提供了两种 DMA,一种是集成在 PS 中的硬核 DMA,另一种是 PL 中使用的软核 AXI DMA IP。在 ARM CPU 设计的过程中,已经考虑到了大量数据搬移的情况,因此在 CPU 中自带了一个 DMA 控制器 DAMC,这个 DAMC 驻留在 PS 内,而且必须通过驻留在内存中的 DMA 指令编程,这些程序往往由CPU 准备,因此需要部分的 CPU 参与。 DMAC 支持高达 8 个通道,所以多个 DMA 结构的核可以挂在单个DMAC 上。 DAMC 与 PL 的连接是通过 AXI_GP 接口,这个接口最高支持到 32 位宽度,这也限制了这种模式下的传输速率,理论最高速率为 600MB/s。这种模式不占用 PL 资源,但需要对 DMA 指令编程,会增加软件的复杂性。为了获取更高的传输速率,可以以空间换时间,在 PL 中添加 AXI DMA IP 核,并利用 AXI_HP 接口完成高速的数据传输。原子将各个接口方式的比较做了表格,很是详细  可见通过 PL 的 DMA 和 AXI_HP 接口的传输适用于大块数据的高性能传输,带宽高。  下面我们简单的介绍下 PL 的 DMA,即 AXI DMA IP 核。  AXI Direct Memory Access( AXI DMA) IP 内核在 AXI4 内存映射和 AXI4-Stream IP 接口之间提供高带宽直接储存访问。其可选的 scatter gather 功能还可以从基于处理器的系统中的中央处理单元( CPU)卸载数据移动任务。初始化、 状态和管理寄存器通过 AXI4-Lite 从接口访问。核心的功能组成如下图所示:  AXI DMA 用到了三种总线, AXI4-Lite 用于对寄存器进行配置, AXI4 Memory Map 用于与内存交互,又分为 AXI4 Memory Map Read 和 AXI4 Memory Map Write 两个接口,一个是读一个是写。 AXI4 Stream 接口用于对外设的读写,其中 AXI4 Stream Master( MM2S, Memory Map to Stream)用于对外设写, AXI4-Stream Slave(S2MM, Stream to Memory Map)用于对外设读。总之,在以后的使用中需要知道 AXI_MM2S 和AXI_S2MM 是存储器端映射的 AXI4 总线,提供对存储器( DDR3)的访问。 AXIS_MM2S 和 AXIS_S2MM是 AXI4-streaming 总线,可以发送和接收连续的数据流,无需地址。  AXI DMA 提供 3 种模式,分别是 Direct Register 模式、 Scatter/Gather 模式和 Cyclic DMA 模式,这里我们简单的介绍下常用的 Direct Register 模式和 Scatter/Gather 模式。  Direct Register DMA 模式也就是 Simple DMA。 Direct Register 模式提供了一种配置,用于在 MM2S 和S2MM 通道上执行简单的 DMA 传输,这需要更少的 FPGA 资源。 Simple DMA 允许应用程序在 DMA 和Device 之间定义单个事务。它有两个通道:一个从 DMA 到 Device,另一个从 Device 到 DMA。应用程序必须设置缓冲区地址和长度字段以启动相应通道中的传输。  Scatter/Gather DMA 模式允许在单个 DMA 事务中将数据传输到多个存储区域或从多个存储区域传输数据。它相当于将多个 Simple DMA 请求链接在一起。 SGDMA 允许应用程序在内存中定义事务列表,硬件将在应用程序没有进一步干预的情况下处理这些事务。在此期间,应用程序可以继续添加更多工作以保持硬件工作。用户可以通过轮询或中断来检查事务是否完成。 SGDMA 处理整个数据包( 被定义为表示消息的一系列数据字节)并允许将数据包分解为一个或多个事务。例如,采用以太网 IP 数据包,该数据包由 14 字节的报头后跟 1 个或多个字节的有效负载组成。使用 SGDMA,应用程序可以将 BD( Buffer Descriptor, 用于描述事务的对象) 指向报头,将另一个 BD 指向有效负载,然后将它们作为单个消息传输。这种策略可以使TCP / IP 堆栈更有效,它允许将数据包标头和数据保存在不同的内存区域,而不是将数据包组装成连续的内存块。  在此次的工程中暂时用不到SG模式,如果用sata这些的话估计得用到了,正常情况下简单模式还是够用的下面做一个简单的AXIDMA初始化和收发demo测试头文件如下#ifndef SRC_XDMA_DRIVER_H_ #define SRC_XDMA_DRIVER_H_ #include "xaxidma.h" #include "xparameters.h" #include "xil_exception.h" #include "xdebug.h" #ifdef XPAR_UARTNS550_0_BASEADDR #include "xuartns550_l.h" /* to use uartns550 */ #endif #ifdef XPAR_INTC_0_DEVICE_ID #include "xintc.h" #else #include "xscugic.h" #endif #include "xgpiops.h" /************************** Constant Definitions *****************************/ /* * Device hardware build related constants. */ #define DMA_DEV_ID XPAR_AXIDMA_0_DEVICE_ID #ifdef XPAR_AXI_7SDDR_0_S_AXI_BASEADDR #define DDR_BASE_ADDR XPAR_AXI_7SDDR_0_S_AXI_BASEADDR #elif XPAR_MIG7SERIES_0_BASEADDR #define DDR_BASE_ADDR XPAR_MIG7SERIES_0_BASEADDR #elif XPAR_MIG_0_BASEADDR #define DDR_BASE_ADDR XPAR_MIG_0_BASEADDR #elif XPAR_PSU_DDR_0_S_AXI_BASEADDR #define DDR_BASE_ADDR XPAR_PSU_DDR_0_S_AXI_BASEADDR #endif #ifndef DDR_BASE_ADDR #warning CHECK FOR THE VALID DDR ADDRESS IN XPARAMETERS.H, \ DEFAULT SET TO 0x01000000 #define MEM_BASE_ADDR 0x01000000 #else #define MEM_BASE_ADDR (DDR_BASE_ADDR + 0x1000000) #endif #ifdef XPAR_INTC_0_DEVICE_ID #define RX_INTR_ID XPAR_INTC_0_AXIDMA_0_S2MM_INTROUT_VEC_ID #define TX_INTR_ID XPAR_INTC_0_AXIDMA_0_MM2S_INTROUT_VEC_ID #else //#define RX_INTR_ID XPAR_FABRIC_AXIDMA_0_S2MM_INTROUT_VEC_ID //#define TX_INTR_ID XPAR_FABRIC_AXIDMA_0_MM2S_INTROUT_VEC_ID #endif #define TX_BUFFER_BASE (MEM_BASE_ADDR + 0x00100000) #define TX_BUFFER_BASE1 (MEM_BASE_ADDR + 0x00101000) #define TX_BUFFER_BASE2 (MEM_BASE_ADDR + 0x00102000) #define TX_BUFFER_BASE3 (MEM_BASE_ADDR + 0x00103000) #define RX_BUFFER_BASE (MEM_BASE_ADDR + 0x00300000) #define RX_BUFFER_BASE1 (MEM_BASE_ADDR + 0x00301000) #define RX_BUFFER_BASE2 (MEM_BASE_ADDR + 0x00302000) #define RX_BUFFER_BASE3 (MEM_BASE_ADDR + 0x00303000) #define RX_BUFFER_HIGH (MEM_BASE_ADDR + 0x004FFFFF) #ifdef XPAR_INTC_0_DEVICE_ID #define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID #else #define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID #endif #ifdef XPAR_INTC_0_DEVICE_ID #define INTC XIntc #define INTC_HANDLER XIntc_InterruptHandler #else #define INTC XScuGic #define INTC_HANDLER XScuGic_InterruptHandler #endif extern XAxiDma AxiDma; /* Instance of the XAxiDma */ extern XAxiDma AxiDma1; /* Instance of the XAxiDma */ extern XAxiDma AxiDma2; /* Instance of the XAxiDma */ extern XAxiDma AxiDma3; /* Instance of the XAxiDma */ /* Timeout loop counter for reset */ #define RESET_TIMEOUT_COUNTER 10000 #define TEST_START_VALUE 0xC /* * Buffer and Buffer Descriptor related constant definition */ #define MAX_PKT_LEN 0x100 #define NUMBER_OF_TRANSFERS 10 static XGpioPs Gpio; /* The Instance of the GPIO Driver */ /* The interrupt coalescing threshold and delay timer threshold * Valid range is 1 to 255 * * We set the coalescing threshold to be the total number of packets. * The receive side will only get one completion interrupt for this example. */ /************* Type Definitions ******************/ /***** Macros (Inline Functions) Definitions **********/ /************* Function Prototypes **************/ #ifndef DEBUG extern void xil_printf(const char *format, ...); #endif #ifdef XPAR_UARTNS550_0_BASEADDR void Uart550_Setup(void); #endif static int CheckData(int Length, u8 StartValue); //static void TxIntrHandler(void *Callback); //static void RxIntrHandler(void *Callback); int dma_init(void); int dma_8_10b_send(XAxiDma* AxiDmaIns,u8 *wBuffer , unsigned int length); unsigned int dma_8_10b_recv(XAxiDma* AxiDmaIns,u8 *rBuffer); static int SetupIntrSystem(INTC * IntcInstancePtr, XAxiDma * AxiDmaPtr, u16 TxIntrId, u16 RxIntrId); static void DisableIntrSystem(INTC * IntcInstancePtr, u16 TxIntrId, u16 RxIntrId); int SetupInterruptSystem(XScuGic *GicInstancePtr, XGpioPs *Gpio, u16 GpioIntrId); static void TxIntrHandler(AxiDma); static void RxIntrHandler(AxiDma); /************** Variable Definitions ****************/ /* * Device instance definitions */ static INTC Intc; /* Instance of the Interrupt Controller */ /* * Flags interrupt handlers use to notify the application context the events. */ volatile int TxDone; volatile int DMA0RxDone; volatile int DMA1RxDone; volatile int DMA2RxDone; volatile int DMA3RxDone; volatile int Error; #endif /* SRC_XDMA_DRIVER_H_ */ 驱动文件如下#include "xdma_driver.h" XAxiDma AxiDma; /* Instance of the XAxiDma */ XAxiDma AxiDma1; /* Instance of the XAxiDma */ XAxiDma AxiDma2; /* Instance of the XAxiDma */ XAxiDma AxiDma3; /* Instance of the XAxiDma */ #ifdef XPAR_UARTNS550_0_BASEADDR /*****************************************************************************/ /* * * Uart16550 setup routine, need to set baudrate to 9600 and data bits to 8 * * @param None * * @return None * * @note None. * ******************************************************************************/ extern void Uart550_Setup(void) { XUartNs550_SetBaud(XPAR_UARTNS550_0_BASEADDR, XPAR_XUARTNS550_CLOCK_HZ, 9600); XUartNs550_SetLineControlReg(XPAR_UARTNS550_0_BASEADDR, XUN_LCR_8_DATA_BITS); } #endif /*****************************************************************************/ /* * * This function checks data buffer after the DMA transfer is finished. * * We use the static tx/rx buffers. * * @param Length is the length to check * @param StartValue is the starting value of the first byte * * @return * - XST_SUCCESS if validation is successful * - XST_FAILURE if validation is failure. * * @note None. * ******************************************************************************/ int CheckData(int Length, u8 StartValue) { u8 *RxPacket; int Index = 0; u8 Value; RxPacket = (u8 *) RX_BUFFER_BASE; Value = StartValue; /* Invalidate the DestBuffer before receiving the data, in case the * Data Cache is enabled */ #ifndef __aarch64__ Xil_DCacheInvalidateRange((UINTPTR)RxPacket, Length); #endif for(Index = 0; Index < Length; Index++) { if (RxPacket[Index] != Value) { xil_printf("Data error %d: %x/%x\r\n", Index, RxPacket[Index], Value); return XST_FAILURE; } Value = (Value + 1) & 0xFF; } return XST_SUCCESS; } /*****************************************************************************/ /* * * This is the DMA TX Interrupt handler function. * * It gets the interrupt status from the hardware, acknowledges it, and if any * error happens, it resets the hardware. Otherwise, if a completion interrupt * is present, then sets the TxDone.flag * * @param Callback is a pointer to TX channel of the DMA engine. * * @return None. * * @note None. * ******************************************************************************/ //static void TxIntrHandler(void *Callback) static void TxIntrHandler(XAxiDma *AxiDma) { u32 IrqStatus; int TimeOut; //XAxiDma *AxiDmaInst = (XAxiDma *)Callback; /* Read pending interrupts */ IrqStatus = XAxiDma_IntrGetIrq(AxiDma, XAXIDMA_DMA_TO_DEVICE); /* Acknowledge pending interrupts */ XAxiDma_IntrAckIrq(AxiDma, IrqStatus, XAXIDMA_DMA_TO_DEVICE); /* * If no interrupt is asserted, we do not do anything */ if (!(IrqStatus & XAXIDMA_IRQ_ALL_MASK)) { return; } /* * If error interrupt is asserted, raise error flag, reset the * hardware to recover from the error, and return with no further * processing. */ if ((IrqStatus & XAXIDMA_IRQ_ERROR_MASK)) { Error = 1; /* * Reset should never fail for transmit channel */ XAxiDma_Reset(AxiDma); TimeOut = RESET_TIMEOUT_COUNTER; while (TimeOut) { if (XAxiDma_ResetIsDone(AxiDma)) { break; } TimeOut -= 1; } return; } /* * If Completion interrupt is asserted, then set the TxDone flag */ if ((IrqStatus & XAXIDMA_IRQ_IOC_MASK)) { TxDone = 1; } } /*****************************************************************************/ /* * * This is the DMA RX interrupt handler function * * It gets the interrupt status from the hardware, acknowledges it, and if any * error happens, it resets the hardware. Otherwise, if a completion interrupt * is present, then it sets the RxDone flag. * * @param Callback is a pointer to RX channel of the DMA engine. * * @return None. * * @note None. * ******************************************************************************/ //static void RxIntrHandler(void *Callback) static void RxIntrHandler(XAxiDma *AxiDmaIns ) { u32 IrqStatus; int TimeOut; //XAxiDma *AxiDmaInst = (XAxiDma *)Callback; /* Read pending interrupts */ IrqStatus = XAxiDma_IntrGetIrq(AxiDmaIns, XAXIDMA_DEVICE_TO_DMA); /* Acknowledge pending interrupts */ XAxiDma_IntrAckIrq(AxiDmaIns, IrqStatus, XAXIDMA_DEVICE_TO_DMA); /* * If no interrupt is asserted, we do not do anything */ if (!(IrqStatus & XAXIDMA_IRQ_ALL_MASK)) { return; } /* * If error interrupt is asserted, raise error flag, reset the * hardware to recover from the error, and return with no further * processing. */ if ((IrqStatus & XAXIDMA_IRQ_ERROR_MASK)) { Error = 1; /* Reset could fail and hang * NEED a way to handle this or do not call it?? */ XAxiDma_Reset(AxiDmaIns); TimeOut = RESET_TIMEOUT_COUNTER; while (TimeOut) { if(XAxiDma_ResetIsDone(AxiDmaIns)) { break; } TimeOut -= 1; } return; } /* * If completion interrupt is asserted, then set RxDone flag */ if ((IrqStatus & XAXIDMA_IRQ_IOC_MASK)) { if(AxiDmaIns == &AxiDma) { DMA0RxDone = 1; } else if(AxiDmaIns == &AxiDma1) { DMA1RxDone = 1; } else if(AxiDmaIns == &AxiDma2) { DMA2RxDone = 1; } else if(AxiDmaIns == &AxiDma3) { DMA3RxDone = 1; } } } /*****************************************************************************/ /* * * This function setups the interrupt system so interrupts can occur for the * DMA, it assumes INTC component exists in the hardware system. * * @param IntcInstancePtr is a pointer to the instance of the INTC. * @param AxiDmaPtr is a pointer to the instance of the DMA engine * @param TxIntrId is the TX channel Interrupt ID. * @param RxIntrId is the RX channel Interrupt ID. * * @return * - XST_SUCCESS if successful, * - XST_FAILURE.if not succesful * * @note None. * ******************************************************************************/ static void IntrHandler(void *CallBackRef, u32 Bank, u32 Status) { XGpioPs *Gpio = (XGpioPs *)CallBackRef; u32 DataRead = 0;; /* Push the switch button */ //DataRead = XGpioPs_ReadPin(Gpio, Input_Pin); DataRead = XGpioPs_Read(Gpio, 2); xil_printf("0x%x IntrHandler\r\n",DataRead); if ((DataRead & 0x1) == 0x01) { TxIntrHandler(&AxiDma); } if((DataRead & 0x2) == 0x02) { RxIntrHandler(&AxiDma); } if ((DataRead & 0x4) == 0x04) { TxIntrHandler(&AxiDma1); // xil_printf("data 4t\r\n"); } if((DataRead & 0x8) == 0x08) { RxIntrHandler(&AxiDma1); // xil_printf("data 4r\r\n"); } if ((DataRead & 0x10) == 0x010) { TxIntrHandler(&AxiDma2); } if((DataRead & 0x20) == 0x20) { RxIntrHandler(&AxiDma2); } if ((DataRead & 0x40) == 0x40) { TxIntrHandler(&AxiDma3); } if((DataRead & 0x80) == 0x080) { RxIntrHandler(&AxiDma3); } else { } } /*****************************************************************************/ /** * * This function sets up the interrupt system for the example. It enables falling * edge interrupts for all the pins of bank 0 in the GPIO device. * * @param GicInstancePtr is a pointer to the XScuGic driver Instance. * @param GpioInstancePtr contains a pointer to the instance of the GPIO * component which is going to be connected to the interrupt * controller. * @param GpioIntrId is the interrupt Id and is typically * XPAR_<GICPS>_<GPIOPS_instance>_VEC_ID value from * xparameters.h. * * @return XST_SUCCESS if successful, otherwise XST_FAILURE. * * @note None. * ****************************************************************************/ int SetupInterruptSystem(XScuGic *GicInstancePtr, XGpioPs *Gpio, u16 GpioIntrId) { xil_printf("SetupInterruptSystem\r\n"); int Status; XScuGic_Config *IntcConfig; /* Instance of the interrupt controller */ Xil_ExceptionInit(); /* * Initialize the interrupt controller driver so that it is ready to * use. */ IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID); if (NULL == IntcConfig) { return XST_FAILURE; } Status = XScuGic_CfgInitialize(GicInstancePtr, IntcConfig, IntcConfig->CpuBaseAddress); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Connect the interrupt controller interrupt handler to the hardware * interrupt handling logic in the processor. */ Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, GicInstancePtr); /* * Connect the device driver handler that will be called when an * interrupt for the device occurs, the handler defined above performs * the specific interrupt processing for the device. */ Status = XScuGic_Connect(GicInstancePtr, GpioIntrId, (Xil_ExceptionHandler)XGpioPs_IntrHandler, (void *)Gpio); if (Status != XST_SUCCESS) { return Status; } /* Enable falling edge interrupts for all the pins in bank 0. */ XGpioPs_SetIntrType(Gpio, 2, 0x00, 0xFFFFFFFF, 0x00); /* Set the handler for gpio interrupts. */ XGpioPs_SetCallbackHandler(Gpio, (void *)Gpio, IntrHandler); /* Enable the GPIO interrupts of Bank 2. */ XGpioPs_IntrEnable(Gpio, 2, 0xFF); /* Enable the interrupt for the GPIO device. */ XScuGic_Enable(GicInstancePtr, GpioIntrId); /* Enable interrupts in the Processor. */ Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ); return XST_SUCCESS; } /*****************************************************************************/ /** * * This function disables the interrupts for DMA engine. * * @param IntcInstancePtr is the pointer to the INTC component instance * @param TxIntrId is interrupt ID associated w/ DMA TX channel * @param RxIntrId is interrupt ID associated w/ DMA RX channel * * @return None. * * @note None. * ******************************************************************************/ static void DisableIntrSystem(INTC * IntcInstancePtr, u16 TxIntrId, u16 RxIntrId) { #ifdef XPAR_INTC_0_DEVICE_ID /* Disconnect the interrupts for the DMA TX and RX channels */ XIntc_Disconnect(IntcInstancePtr, TxIntrId); XIntc_Disconnect(IntcInstancePtr, RxIntrId); #else XScuGic_Disconnect(IntcInstancePtr, TxIntrId); XScuGic_Disconnect(IntcInstancePtr, RxIntrId); #endif } int dma_init(void) { int Status; XAxiDma_Config *Config; XAxiDma_Config *Config1; XAxiDma_Config *Config2; XAxiDma_Config *Config3; XGpioPs_Config *ConfigPtr; u8 *RxBufferPtr = (u8 *)RX_BUFFER_BASE; u8 *RxBufferPtr1 = (u8 *)RX_BUFFER_BASE1; u8 *RxBufferPtr2 = (u8 *)RX_BUFFER_BASE2; u8 *RxBufferPtr3 = (u8 *)RX_BUFFER_BASE3; memset(RxBufferPtr,0,MAX_PKT_LEN); memset(RxBufferPtr1,0,MAX_PKT_LEN); memset(RxBufferPtr2,0,MAX_PKT_LEN); memset(RxBufferPtr3,0,MAX_PKT_LEN); xil_printf("\r\n--- Entering dma init() --- \r\n"); Config = XAxiDma_LookupConfig(0); if (!Config) { xil_printf("No config found for 0\r\n"); return XST_FAILURE; } Config1 = XAxiDma_LookupConfig(1); if (!Config1) { xil_printf("No config found for 1\r\n"); return XST_FAILURE; } Config2 = XAxiDma_LookupConfig(2); if (!Config2) { xil_printf("No config found for 2\r\n"); return XST_FAILURE; } Config3 = XAxiDma_LookupConfig(3); if (!Config3) { xil_printf("No config found for 3\r\n"); return XST_FAILURE; } /* Initialize DMA engine */ Status = XAxiDma_CfgInitialize(&AxiDma, Config); if (Status != XST_SUCCESS) { xil_printf("Initialization 0 failed %d\r\n", Status); return XST_FAILURE; } Status = XAxiDma_CfgInitialize(&AxiDma1, Config1); if (Status != XST_SUCCESS) { xil_printf("Initialization 1 failed %d\r\n", Status); return XST_FAILURE; } Status = XAxiDma_CfgInitialize(&AxiDma2, Config2); if (Status != XST_SUCCESS) { xil_printf("Initialization 2 failed %d\r\n", Status); return XST_FAILURE; } Status = XAxiDma_CfgInitialize(&AxiDma3, Config3); if (Status != XST_SUCCESS) { xil_printf("Initialization 3 failed %d\r\n", Status); return XST_FAILURE; } /* Initialize the Gpio driver. */ ConfigPtr = XGpioPs_LookupConfig(0); if (ConfigPtr == NULL) { return XST_FAILURE; } XGpioPs_CfgInitialize(&Gpio, ConfigPtr, ConfigPtr->BaseAddr); /* Set the direction for the specified pin to be input */ XGpioPs_SetDirectionPin(&Gpio,54,0); XGpioPs_SetDirectionPin(&Gpio,55,0); XGpioPs_SetDirectionPin(&Gpio,56,0); XGpioPs_SetDirectionPin(&Gpio,57,0); XGpioPs_SetDirectionPin(&Gpio,58,0); XGpioPs_SetDirectionPin(&Gpio,59,0); XGpioPs_SetDirectionPin(&Gpio,60,0); XGpioPs_SetDirectionPin(&Gpio,61,0); /* * Setup the interrupts such that interrupt processing can occur. If * an error occurs then exit. */ Status = SetupInterruptSystem(&Intc, &Gpio, XPAR_XGPIOPS_0_INTR); if (Status != XST_SUCCESS) { return XST_FAILURE; } XAxiDma_IntrDisable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,XAXIDMA_DMA_TO_DEVICE); XAxiDma_IntrDisable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,XAXIDMA_DEVICE_TO_DMA); XAxiDma_IntrEnable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,XAXIDMA_DMA_TO_DEVICE); XAxiDma_IntrEnable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,XAXIDMA_DEVICE_TO_DMA); XAxiDma_IntrDisable(&AxiDma1, XAXIDMA_IRQ_ALL_MASK,XAXIDMA_DMA_TO_DEVICE); XAxiDma_IntrDisable(&AxiDma1, XAXIDMA_IRQ_ALL_MASK,XAXIDMA_DEVICE_TO_DMA); XAxiDma_IntrEnable(&AxiDma1, XAXIDMA_IRQ_ALL_MASK,XAXIDMA_DMA_TO_DEVICE); XAxiDma_IntrEnable(&AxiDma1, XAXIDMA_IRQ_ALL_MASK,XAXIDMA_DEVICE_TO_DMA); XAxiDma_IntrDisable(&AxiDma2, XAXIDMA_IRQ_ALL_MASK,XAXIDMA_DMA_TO_DEVICE); XAxiDma_IntrDisable(&AxiDma2, XAXIDMA_IRQ_ALL_MASK,XAXIDMA_DEVICE_TO_DMA); XAxiDma_IntrEnable(&AxiDma2, XAXIDMA_IRQ_ALL_MASK,XAXIDMA_DMA_TO_DEVICE); XAxiDma_IntrEnable(&AxiDma2, XAXIDMA_IRQ_ALL_MASK,XAXIDMA_DEVICE_TO_DMA); XAxiDma_IntrDisable(&AxiDma3, XAXIDMA_IRQ_ALL_MASK,XAXIDMA_DMA_TO_DEVICE); XAxiDma_IntrDisable(&AxiDma3, XAXIDMA_IRQ_ALL_MASK,XAXIDMA_DEVICE_TO_DMA); XAxiDma_IntrEnable(&AxiDma3, XAXIDMA_IRQ_ALL_MASK,XAXIDMA_DMA_TO_DEVICE); XAxiDma_IntrEnable(&AxiDma3, XAXIDMA_IRQ_ALL_MASK,XAXIDMA_DEVICE_TO_DMA); /**************************************************************************/ // Status = XAxiDma_ReadReg(XPAR_AXI_DMA_0_BASEADDR,0x58); // xil_printf(" RX length is 0x%x\r\n",Status); // Status = XAxiDma_ReadReg(XPAR_AXI_DMA_0_BASEADDR,0x28); // xil_printf("TX length is 0x%x\r\n",Status); /**************************************************************************/ Status = XAxiDma_SimpleTransfer(&AxiDma,(UINTPTR) RxBufferPtr, MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA); if (Status != XST_SUCCESS) { return XST_FAILURE; } Status = XAxiDma_SimpleTransfer(&AxiDma1,(UINTPTR) RxBufferPtr1, MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA); if (Status != XST_SUCCESS) { return XST_FAILURE; } Status = XAxiDma_SimpleTransfer(&AxiDma2,(UINTPTR) RxBufferPtr2, MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA); if (Status != XST_SUCCESS) { return XST_FAILURE; } Status = XAxiDma_SimpleTransfer(&AxiDma3,(UINTPTR) RxBufferPtr3, MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* Initialize flags before start transfer test */ TxDone = 0; DMA0RxDone = 0; DMA1RxDone = 0; DMA2RxDone = 0; DMA3RxDone = 0; Error = 0; } int dma_8_10b_send(XAxiDma* AxiDmaIns,u8 *wBuffer , unsigned int length) { int Status; u8 *TxBufferPtr; if((AxiDmaIns == NULL)||(wBuffer == NULL)) { xil_printf("send Pointer err\r\n"); return XST_FAILURE; } if (AxiDmaIns == &AxiDma) TxBufferPtr = (u8 *)TX_BUFFER_BASE ; else if(AxiDmaIns == &AxiDma1) TxBufferPtr = (u8 *)TX_BUFFER_BASE1 ; else if(AxiDmaIns == &AxiDma2) TxBufferPtr = (u8 *)TX_BUFFER_BASE2 ; else if(AxiDmaIns == &AxiDma3) TxBufferPtr = (u8 *)TX_BUFFER_BASE3 ; else { xil_printf("para err\r\n"); return XST_FAILURE; } memset(TxBufferPtr,0,length); memcpy(TxBufferPtr,wBuffer,length); Xil_DCacheFlushRange((UINTPTR)TxBufferPtr, MAX_PKT_LEN); Status = XAxiDma_SimpleTransfer(AxiDmaIns,(UINTPTR) TxBufferPtr, length, XAXIDMA_DMA_TO_DEVICE); // xil_printf("status is %d",Status); if (Status != XST_SUCCESS) { return XST_FAILURE; } return XST_SUCCESS; } unsigned int dma_8_10b_recv(XAxiDma* AxiDmaIns,u8 *rBuffer) { int Status; int i; int Length = 0 ; u8 *RxBufferPtr; Length = XAxiDma_ReadReg(AxiDmaIns->RegBase,0x58); if((AxiDmaIns == NULL)||(rBuffer == NULL)) { xil_printf("recv Pointer err\r\n"); return XST_FAILURE; } if (AxiDmaIns == &AxiDma) RxBufferPtr = (u8 *)RX_BUFFER_BASE ; else if(AxiDmaIns == &AxiDma1) RxBufferPtr = (u8 *)RX_BUFFER_BASE1 ; else if(AxiDmaIns == &AxiDma2) RxBufferPtr = (u8 *)RX_BUFFER_BASE2 ; else if(AxiDmaIns == &AxiDma3) RxBufferPtr = (u8 *)RX_BUFFER_BASE3 ; else { xil_printf("para err\r\n"); return XST_FAILURE; } Xil_DCacheInvalidateRange(RxBufferPtr,MAX_PKT_LEN); for(i = 0; i < Length; i++) { rBuffer[i] = RxBufferPtr[i]; } Status = XAxiDma_SimpleTransfer(AxiDmaIns,(UINTPTR) RxBufferPtr, MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA); if (Status != XST_SUCCESS) { return XST_FAILURE; } return Length; }Demo部分如下void Xdma_demo() { int Status; int Length; u8 rBuffer[256] = {0}; u8 wBuffer[256] = {0}; int i; dma_init(); for(i=0;i<256;i++) { wBuffer[i]=i+1; } dma_8_10b_send(&AxiDma,wBuffer,4); for(i=0;i<256;i++) { wBuffer[i]=i+2; } dma_8_10b_send(&AxiDma1,wBuffer , 16); for(i=0;i<256;i++) { wBuffer[i]=i+3; } dma_8_10b_send(&AxiDma2,wBuffer , 32); for(i=0;i<256;i++) { wBuffer[i]=i+4; } dma_8_10b_send(&AxiDma3,wBuffer , 32); while(1) { if(DMA0RxDone == 1) { // Status = XAxiDma_ReadReg(XPAR_AXI_DMA_0_BASEADDR,0x58); // xil_printf("length2 is 0x%x\r\n",Status); // Status = XAxiDma_ReadReg(XPAR_AXI_DMA_0_BASEADDR,0x28); // xil_printf("TX length2 is 0x%x\r\n",Status); Length = dma_8_10b_recv(&AxiDma,rBuffer); xil_printf("length DMA0 is 0x%x\r\n",Length); xil_printf("DATE: "); for(i=0; i<33; i++) { xil_printf("%x ",rBuffer[i]); } xil_printf("\r\n"); DMA0RxDone = 0; } if(DMA1RxDone == 1) { Length = dma_8_10b_recv(&AxiDma1,rBuffer); xil_printf("length DMA1 is 0x%x\r\n",Length); xil_printf("DATE: "); for(i=0; i<33; i++) { xil_printf("%x ",rBuffer[i]); } xil_printf("\r\n"); DMA1RxDone = 0; } if(DMA2RxDone == 1) { dma_8_10b_recv(&AxiDma2,rBuffer); xil_printf("DATE: "); for(i=0; i<33; i++) { xil_printf("%x ",rBuffer[i]); } xil_printf("\r\n"); DMA2RxDone = 0; } if(DMA3RxDone == 1) { dma_8_10b_recv(&AxiDma3,rBuffer); xil_printf("DATE: "); for(i=0; i<33; i++) { xil_printf("%x ",rBuffer[i]); } xil_printf("\r\n"); DMA3RxDone = 0; } } }  dma_8_10b_send()为封装后的发送函数,将宏定义的四路TXBUFFER和DMA匹配,实现DMA向设备发送数据的功能,并通过Xil_DCacheFlushRange()函数清理缓存  dma_8_10b_recv()为封装后的接收函数,将宏定义的四路RXBUFFER和DMA匹配,实现DMA接收设备发送的数据的功能,数据长度通过读取DMA长度寄存器获得,这样的话更具有普遍性,同样通过Xil_DCacheFlushRange()函数清理缓存  XAxiDma_SimpleTransfer是其原型,最后一个参数表示了传输方向收发的处理函数基本上是AXIDMA例程里的,仅对多余的接收完成标志位做了补充(多余的应该没了,也能在导入一个工程比较一下)哦对了很奇怪的一点是初始化的时候需要提前做一次接受的transfer,还没发现原因,在之后的挂载操作系统时也有一次类似的操作,当然linux下的transfer不是官方提供的,可能和裸板有些许差异,而且不提前做也没法从0x58的长度寄存器读取实际搬移数据的长度,另说了  初始化部分是结合了之前章节讲的GPIO中断,没有用例程中的中断方式先写这么多了,目前只了解到这些,SG模式的用法后续有机会更新吧参考:芯片手册 原子开发手册 CSDN Xilinx社区等网络资源
文章
存储  ·  缓存  ·  网络协议  ·  Linux  ·  芯片  ·  异构计算  ·  Perl
2023-01-16
[WUSTCTF2020]level4题解
[WUSTCTF2020]level4题解1.查壳NOT Win EXE - .o - ELF executable [ 64bit obj. Exe file - CPU : AMD x86-64 - OS: unspecified ]是64位机上面的ELF文件,ELF可以在Linux上运行2.  拖入Kali Linux运行一下拖入kali linux运行获得六行输出Practice my Data Structure code.....Typing....Struct.....char....*left....*right............emmmmm...OK!Traversal!Traversal type 1:2f0t02T{hcsiI_SwA__r7Ee}Traversal type 2:20f0Th{2tsIS_icArE}e7__wTraversal type 3:    //type3(&x[22]);   No way!、观察获取一下信息:1. Data Structure是数据结构,发现*left *right,有左右两个指针,常用数据结构中使用right和left指针的数据结构很可能是一个二叉树(Binary tree)2.Traversal是遍历,三种遍历方式3.看到了{},感觉像是乱序的flag Definition for a binary tree node. struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) {} };emmm,很可能是二叉树的前序遍历,中序遍历和后序遍历如果可以猜到这个程度的话,我们知道根据中序遍历和前序遍历或者中序遍历和后续遍历可以重建二叉树那么我们可以尝试一下所有情况,可能就能解出flag三分逆向七分猜还可以继续观察一下20f0Th{2tsIS_icArE}e7__w的结尾是w,如果他是后序遍历的话,另一个已知的就是中序遍历那么未知的前序遍历的第一个字符就是w,这个比赛是WUSTCTF,flag第一个字符应该是w那么可以尝试用后序遍历20f0Th{2tsIS_icArE}e7__w和中序遍历2f0t02T{hcsiI_SwA__r7Ee}来求前序遍历,试着解一下flag根据后序遍历和中序遍历求前序遍历的脚本:def PreOrder(Postorder,Inorder): length = len(Postorder) if length == 0: return 0 root = Postorder[length-1] for i in range(length): if root == Inorder[i]: break print(root,end="") PreOrder(Postorder[0:i],Inorder[0:i]) PreOrder(Postorder[i:length-1],Inorder[i+1:length]) PreOrder("20f0Th{2tsIS_icArE}e7__w","2f0t02T{hcsiI_SwA__r7Ee}") 运行结果为wctf2020{This_IS_A_7reE}flag{This_IS_A_7reE}如果没有猜到这个程度的话,继续使用IDA分析3.拖入64位IDA分析一下拖入64位IDA找到main函数,按下F5反编译观察一下除了puts,printf这些输出函数注意观察一下init(),type1(),type2()函数4.依次观察这几个函数init()发现一个字符串赋值操作,字符串为I{_}Af2700ih_secTS2Et_wrtype1()type2()type1,type2是两个递归函数,为了详细了解这两个函数的功能,采取动态调试5.实现ELF动态调试1.找到Linux附带的组件IDA附带一些组件在dbgsrv文件夹下面linux_server和linux_server642.将linux_server和要调试的文件拖入Linux当中所调试的是32位机的二进制文件拖入linux_server64位机拖入linux_server64可以直接将文件拖拽到linux当中在linux当中运行这个组件3.在windows中的IDA选择IDA debugger注意此方法直接打开IDA即可,不要把调试的文件拖入IDA当中,要调试的文件在远程连接的Linux虚拟机上点击Go进入IDA选择Remote Linux DebuggerApplication:你要调试的二进制文件的完整路径Directory:对于远程调试,此字段表示远程目录。Parameters:传递给进程的命令行参数Hostname:远程调试服务器主机或IP地址。Port:远程调试服务器监听的TCP端口号。Password:远程调试服务器所需的密码。Application是/root/attachmentDirectory是/root这个程序没有命令行参数,不需要填写Parameters用ifconfig查看IP,填入HostnameHostname是192.168.195.129password不需要填确保linux_server开始运行之后,可以按下OK进入动调界面
文章
网络协议  ·  Linux  ·  Go  ·  数据安全/隐私保护  ·  Windows
2023-01-16
网络划分的方法
1.A类IP地址 一个A类IP地址是指,在IP地址的四段号码中,第一段号码为网络号码,剩下的三段号码为本地计算机的号码。如果用二进制表示IP地址的话,A类IP地址就由1字节的网络地址和3字节主机地址组成,网络地址的最高位必须是“0”。A类IP地址中网络的标识长度为7位,主机标识的长度为24位,A类网络地址数量较少,可以用于主机数达1600多万台的大型网络。 2.B类IP地址 一个B类IP地址是指,在IP地址的四段号码中,前两段号码为网络号码,剩下的两段号码为本地计算机的号码。如果用二进制表示IP地址的话,B类IP地址就由2字节的网络地址和2字节主机地址组成,网络地址的最高位必须是“10”。B类IP地址中网络的标识长度为14位,主机标识的长度为16位,B类网络地址适用于中等规模规模的网络,每个网络所能容纳的计算机数为6万多台。 3.C类IP地址 一个C类IP地址是指,在IP地址的四段号码中,前三段号码为网络号码,剩下的一段号码为本地计算机的号码。如果用二进制表示IP地址的话,C类IP地址就由3字节的网络地址和1字节主机地址组成,网络地址的最高位必须是“110”。C类IP地址中网络的标识长度为21位,主机标识的长度为8位,C类网络地址数量较多,适用于小规模的局域网络,每个网络最多只能包含254台计算机。 除了上面三种类型的IP地址外,还有几种特殊类型的IP地址,TCP/IP协议规定,凡IP地址中的第一个字节以“lll0”开始的地址都叫多点广播地址。因此,任何第一个字节大于223小于240的IP地址是多点广播地址;IP地址中的每一个字节都为0的地址(“0.0.0.0”)对应于当前主机;IP地址中的每一个字节都为1的IP地址(“255.255.255.255”)是当前子网的广播地址;IP地址中凡是以“llll0”的地址都留着将来作为特殊用途使用;IP地址中不能以十进制“127”作为开头,该类地址中数字127盇舾锒嫌茫?27.1.1.1用于回路测试,同时网络ID的第一个6位组也不能全置为“0”,全“0”表示本地网络。 |-page-| 三、IP的寻址规则 1.网络寻址规则 A、 网络地址必须唯一。 B、 网络标识不能以数字127开头。在A类地址中,数字127保留给内部回送函数。 C、 网络标识的第一个字节不能为255。数字255作为广播地址。 D、 网络标识的第一个字节不能为“0”,“0”表示该地址是本地主机,不能传送。 2.主机寻址规则 A、主机标识在同一网络内必须是唯一的。 B、主机标识的各个位不能都为“1”,如果所有位都为“1”,则该机地址是广播地址,而非主机的地址。 C、主机标识的各个位不能都为“0”,如果各个位都为“0”,则表示“只有这个网络”,而这个网络上没有任何主机。 四、IP子网掩码概述 1.子网掩码的概念 子网掩码是一个32位地址,用于屏蔽IP地址的一部分以区别网络标识和主机标识,并说明该IP地址是在局域网上,还是在远程网上。 2.确定子网掩码数 用于子网掩码的位数决定于可能的子网数目和每个子网的主机数目。在定义子网掩码前,必须弄清楚本来使用的子网数和主机数俊? 定义子网掩码的步骤为: A、确定哪些组地址归我们使用。比如我们申请到的网络号为 “210.73.a.b”,该网络地址为c类IP地址,网络标识为“210.73”,主机标识为“a.b”。 B、根据我们现在所需的子网数以及将来可能扩充到的子网数,用宿主机的一些位来定义子网掩搿1热缥颐窍衷谛枰?2个子网,将来可能需要16个。用第三个字节的前四位确定子网掩码。前四位都置为“1”,即第三个字节为“11110000”,这个数我们暂且称作新的二进制子网掩码。 C、把对应初始网络的各个位都置为“1”,即前两个字节都置为“1”,第四个字节都置为“0”,则子网掩码的间断二进制形式为:“11111111.11111111.11110000.00000000” D、把这个数转化为间断十进制形式为:“255.255.240.0” 这个数为该网络的子网掩码。 3.IP掩码的标注 A、无子网的标注法 对无子网的IP地址,可写成主机号为0的掩码。如IP地址210.73.140.5,掩码为255.255.255.0,也可以缺省掩码,只写IP地址。 B、有子网的标注法 有子网时,一定要二者配对出现。以C类地址为例。 1.IP地址中的前3个字节表示网络号,后一个字节既表明子网号,又说明主机号,还说明两个IP地址是否属于一个网段。如果属于同一网络区间,这两个地址间的信息交换就不通过路由器。如果不属同一网络区间,也就是子网号不同,两个地址的信息交换就要通过路由器进行。例如:对于IP地址为210.73.140.5的主机来说,其主机标识为00000101,对于IP地址为210.73.140.16的主机来说它的主机标识为00010000,以上两个主机标识的前面三位全是000,说明这两个IP地址在同一个网络区域中。 2.掩码的功用是说明有子网和有几个子网,但子网数只能表示为一个范围,不能确切讲具体几个子网,掩码不说明具体子网号,有子网的掩码格式(对C类地址):主机标识前几位为子网号,后面不写主机,全写0。 五、IP的其他事项 1.一般国际互联网信息中心在分配IP地址时是按照网络来分配的,因此只有说到网络地址时才能使用A类、B类、C类的说法; 2.在分配网络地址时,网络标识是固定的,而计算机标识是可以在一定范围内变化的,下面是三类网络地址的组成形式: A类地址:73.0.0.0 B类地址:160.153.0.0 C类地址:210.73.140.0 上述中的每个0均可以在0~255之间进行变化。 3.因为IP地址的前三位数字已决定了一个IP地址是属于何种类型的网络,所以A类网络地址将无法再分成B类IP地址,B类IP地址也不能再分成C类IP地址。 4.在谈到某一特定的计算机IP地址时不宜使用A类、B类、C类的说法,但可以说主机地址是属于哪一个A类、B类、C类网络了。  
文章
网络协议  ·  网络架构
2023-01-16
1
...
7 8 9 10 11 12
...
20
跳转至:
开发与运维
5597 人关注 | 131348 讨论 | 299146 内容
+ 订阅
  • 别让你的服务器(vps)沦为肉鸡(ssh暴力破解),密钥验证、双向因子登录值得拥有
  • 锁对象
  • 销撤销
查看更多 >
云计算
21775 人关注 | 59318 讨论 | 55391 内容
+ 订阅
  • 阿里云国际站:阿里云启用第三座日本数据中心,加快海外市场扩展
  • ECS使用有感
  • 《阿里云异构计算平台》电子版地址
查看更多 >
安全
1179 人关注 | 23942 讨论 | 80523 内容
+ 订阅
  • 别让你的服务器(vps)沦为肉鸡(ssh暴力破解),密钥验证、双向因子登录值得拥有
  • 销撤销
  • 阿里云国际站代理商:美国和香港服务器怎么配置采购?
查看更多 >
人工智能
2779 人关注 | 11272 讨论 | 95937 内容
+ 订阅
  • 基于Python3(Autosub)以及Ffmpeg配合GoogleTranslation(谷歌翻译)为你的影片实现双语版字幕(逐字稿)
  • Python算法之动态规划(Dynamic Programming)解析:二维矩阵中的醉汉(魔改版leetcode出界的路径数)
  • 算法——冒泡排序及实现
查看更多 >
IoT
122848 人关注 | 2886 讨论 | 23579 内容
+ 订阅
  • Cannot read property 'echarts' of undefined
  • 《看见新力量第四期》电子版地址
  • 《物联网开发实战(上)》电子版地址
查看更多 >