VRRP是一种选择协议,它可以把一个虚拟路由器的责任动态分配到局域网上的 VRRP 路由器中的一台。控制虚拟路由器 IP 地址的 VRRP 路由器称为主路由器,它负责转发数据包到这些虚拟 IP 地址。一旦主路由器不可用,这种选择过程就提供了动态的故障转移机制,这就允许虚拟路由器的 IP 地址可以作为终端主机的默认第一跳路由器。是一种LAN接入设备备份协议。一个局域网络内的所有主机都设置缺省网关,这样主机发出的目的地址不在本网段的报文将被通过缺省网关发往三层交换机,从而实现了主机和外部网络的通信。 VRRP是一种路由容错协议,也可以叫做备份路由协议。一个局域网络内的所有主机都设置缺省路由,当网内主机发出的目的地址不在本网段时,报文将被通过缺省路由发往外部路由器,从而实现了主机与外部网络的通信。当缺省路由器down掉(即端口关闭)之后,内部主机将无法与外部通信,如果路由器设置了VRRP时,那么这时,虚拟路由将启用备份路由器,从而实现全网通信。
在VRRP协议中,有两组重要的概念:VRRP路由器和虚拟路由器,主控路由器和备份路由器。VRRP路由器是指运行VRRP的路由器,是物理实体;虚拟路由器是指VRRP协议创建的,是逻辑概念。一组VRRP路由器协同工作,共同构成一台虚拟路由器。该虚拟路由器对外表现为一个具有唯一固定的IP地址和MAC地址的逻辑路由器。处于同一个VRRP组中的路由器具有两种互斥的角色:主控路由器和备份路由器,一个VRRP组中有且只有一台处于主控角色的路由器,可以有一个或者多个处于备份角色的路由器VRRP协议从路由器组中选出一台作为主控路由器,负责ARP解析和转发IP数据包,组中的其他路由器作为备份的角色并处于待命状态,当由于某种原因主控路由器发生故障时,其中的一台备份路由器能在瞬间的时延后升级为主控路由器,由于此切换非常迅速而且不用改变IP地址和MAC地址,故对终端使用者系统是透明的。
依旧备忘用
<script> $.ajax({ type: "delete", url: url, success: function (response,status,xhr) { console.log(response); //服务器返回的信息 console.log(status); //服务器返回的信息 console.log(xhr.status); //状态码, 要看其他的直接 输出 xhr 就行 console.log(xhr.getAllResponseHeaders()); //响应头部 }, error: function () { console.log("请求失败"); } }); </script>
# 停止docker服务 service docker stop # 用ip命令使docker0网卡down掉 ip link set dev docker0 down
# 删除网卡 brctl delbr docker0
转载于:https://www.cnblogs.com/zxcnn/p/11101814.html
2019.6.26日深夜
晚上在床上准备休息,一个同跟我聊天说自己大学荒废了,突然有很多感想想写一写。我觉得自己大学也是得过且过地过着的,不过虽然充满艰辛和不满意,但还是挺充实的。
先自我介绍一下,本人大二,是南京工程学院自动化院机器人工程专业的一名17级本科生。我的学校不是知名211、985的高校,这个专业我自认为也只是图个鳌头,并没有实际涉及到很多关于机器人的知识,其实说白了就是自动化。所以可以说自己是一个完完全全的自动化的本科生,但是作为有梦想的青年,当然不会局限于学校里讲的课程,作为一名已经大二即将步入大三的学长,我想通过这篇博客向那些虽然不在好大学但仍然有梦想的学弟学妹们和同伴提供一点建议。
这里和大家聊聊大学经历,如果嫌烦可以直接跳最后哦。
1.个人经历 先说说学校吧 我们学校虽然不是什么好本科,但是我很爱和感谢我的学校。我自己是高考考砸了来了这里,甚至暑假中一度准备复读,刚进大学时满心的不甘和不屑,对老师同学都非常鄙视。但是经历了一阵子磨合期,我发现这个大学有很多我没发现的闪光点,包括有很多优秀的学长和老师,也有很多可爱的小伙伴。学习伙食不错,生活和住宿也挺满意,学校还有新球场可以打球,虽然大学打球的伙伴很少。学校风景很美,也是南京最美的高校之一,有闻名南京的天印湖,学校的冬天下雪也特别美。
学校的冬天
再说一说个人经历吧。 大一时第一次进校园,可以说是对大学一无所知。经过军训之后,报了学校的学习部和水中机器人实验室。很幸运两个都进了,但是我也从中认清了部门社团和实验室之间的区别。可以真实地告诉大家,部门和社团确确实实是一个浪费时间的地方,我在申请时以为学习部是一群一起学习考研的小伙伴组成的学习团队,但实际并不是,这只是一个查课做表、帮院里面辅导员打杂的部门。可以说对部门非常失望,浪费了很多时间。相反,实验室可以说是将大学生活用到极致的好地方,所以建议大家尽量报一个实验室!对大学生活有很大的帮助,可以说我大学的生活和学习完全是围绕着实验室展开的。
大一上刚进实验室时,因为自己是真的小白,所以是从C语言的基础学起的。我花了整整半学期时间精通C语言,可以说有所得有所失。因为第一次学编程,花了太多时间学这种基础,所以大一上学期没太大进展。
在大一寒假留校期间学习了51单片机并和实验室的小伙伴们做了一辆基于51单片机循迹小车。在留校结束后又回家学了些51单片机的知识,包括中断、串口通信什么的。
基于51单片机的循迹小车
大一下学期我买了一本C Primer Plus,对C语言进行了深入学习。我花了一学期读完了800多页的这本书,虽然了解了队列、指针、二叉树等算法,但是个人觉得在平常的编程生活中其实用处不是特别大,至少在这个专业中用不到这么复杂的C语言算法。同时自己学了Arduino,做了些小项目。但是反观实验室其他同学,都学了一些比较特别的东西,比如STM32、C++等,所以这一段时间那些同学都有学长给的项目做,而我啥都没有,在这一阵子学习特别低落。
大一暑假参加了实验室的国际水中机器人大赛的垃圾清理组的比赛,负责arduino程序的编写。但是因为自己能力有限,几乎留校一个月都在装船和王者中度过,可以说是真的很浪费时光,现在回头想都特别后悔。中途还参加了省电赛,拿了省二。最后自己水平问题并没有到青岛参加比赛,机器也因为荡机导致只拿了三等奖。在留校结束后的一个月里,我学了C#。但是并没有了解过多,可以说8月份完完全全浪费了。
电赛的无线充电小车
大一的下学期到大二上学期实验室第一次开会之间,我可以说自己完完全全在大学的迷茫期之中。中间充斥着各种压力,感情、学习还有目标都遭受了各种挫折,可以说天天到床上第一件事就是流眼泪。我和室友吵架,做什么事都提不起劲,天天就是游戏睡觉。
大二是改变的开始,我在这半年里感觉到了前所未有的动力。
大二第一次实验室开会,我理所当然成了背锅侠,被学长老师训斥了一顿,我开始重新寻找方向。我开始接触树莓派,花了一个多月学了一些基础的知识,并接手了学长的项目,参加了江苏省机器人大赛,但是最后只拿了省三。看着实验室其他同学都是冠军或者一等奖,其实挺失落的。在比赛结束后我经过思考开始学习python,了解基本语法之后写了个飞机大战的代码,但之后我并没有选择深入学习python的其他知识比如爬虫之类的,我选择基于python学习opencv。在大二上学期我学习了opencv的基本知识,并参加了学校的一些小比赛,做了基于图像识别的分拣传送带等项目。
江苏省机器人大赛现场(右上角拿旗的是我)
基于图像处理的分拣传送带
在大二寒假里留校的两周里,我通过Opencv写了二维码识别的代码,可以说是自己真正花尽心血写的大项目。在留校结束回家后我继续学习,做了车牌识别,又学习了tensorflow机器学习,写了基于tensorflow的人脸识别的代码。同时学习了PyQt,编写了不少ui窗口的代码,并结合opencv实现了两者的共同开发。
寒假留校时写代码到深夜的晚上
大二下学期到现在,我参加了学校捷配的电赛选拔赛,做了之前文章里写的可见光和滚球装置,也把自己寒假做的人脸识别报了学校的科创并做了进一步完善。同时今年暑假再次参加国际水中机器人大赛,并作为组长参加深水黄鱼管道巡检项目。这学期我还学了很多树莓派的使用知识,也接触并学习了STM32,熟悉了PID等控制算法,也是为黄鱼比赛和电赛国赛打下基础。
在暑假里除了10号的比赛和电赛国赛,我打算用中间两个月的时间学习视觉SLAM和激光SLAM,学习C++并熟悉ubuntu系统,准备专利申报和论文发表,并准备中国机器人大赛水下rov的比赛,参加rov项目。
大三个人准备专心考研,除了实验室一些比赛,将所有精力花在考研上,争取实现我上东南南大的梦,完成高三时的梦想。
学习方向建议: 对于一个大一的自动化新生,要在大一时就选好方向,是准备考研还是准备大学毕业工作。 对于考研的学生,我建议将学习方向放在算法研究上。在学习某一样东西时,不能只会应用,不懂原理。所以学习时尽量摸清算法的原理和算法,了解算法的数学原理以及分析,这是对一个未来即将成为研究生的学生来说极其重要的能力。学东西切忌不能浮躁,别人的代码拿过来也不能直接照搬,要懂原理懂思路,要有耐心了解知识的来龙去脉,从数学方法的推导到算法的实现,都要进行细致的了解。
进大一前的暑假先学习C语言(没把握好进大学前的暑假我很后悔)和一些MCU的知识,为大学进实验室做准备
建议在大一上学期挑一个自己感兴趣的实验室,学习精通C语言,之后在大一下选择一个自己感兴趣的方向,个人建议不要选硬件,因为这些通常比不过许多专升本的专科生,且要在硬件上有所提高难上加难,尽量去研究深度的算法,比如图像处理(视觉SLAM,OpenCV等)、数学建模、MCU(建议stm32)、嵌入式系统(linux等)、ui窗口文件编写(C#、QT),temsorflow机器学习等比较先进比较新的技术,这些技术都是适合自动化学生学习的,因为大学大多讲的是落后的旧技术,很难凭借这些旧技术立足于现在这个社会。多去了解一些不要拘泥于自己的专业,而要基于自己的专业和兴趣选择。
大二就在保证各科成绩优良的情况下努力学自己想要的知识,记住要专攻一个方向,千万不能一心二用,学完一个技术再学下一个,一定要踏实。同时在大二参加足够多的比赛,比赛的奖状可以在研究生面试时加分甚至免复试,很关键!
在大三时可以根据自己学习的方向进行考研准备,大四考研之后顺利毕业去自己的下一所学校。在研究生阶段在进行更加深入的学习。
对于准备工作的,我建议将精力放在学习应用上。在学习过程中精通应用,能把所学知识迅速转换为产品,建议也学习以上建议的一些知识。我们学校毕业的本科生中,有第一年年薪三四十万的,也有月薪两三千的,区别就在于掌握的知识的多少,尽量学的广,学的精。大学什么都不学的本科生,出去最多是到工厂里当工人,不管是985、211还是本二本三的学生,自动化专业的行情就这样,最多的是去企业操控机床、加工产品,学历造成的不过是工资有小几千的差距罢了。鉴于我现在了解的行情,一位精通C++以及opencv原理的工程师,月薪可以达到1万到2万,但如果你会机器学习,那工资更会翻倍。如果你又会编写ui窗口、会写TCP协议和通信,工资又会有很大的提升。所以基于一个已经学习的方向进行深度发掘和拓展,并通过这个主干进行延伸,学习其他新知识是非常重要的。
同时建议大家培养口才和演讲能力,一个优秀的工科生要拥有非凡的口才能力,即吹牛逼。我见过很多学长虽然实力差不多,但是在面试时口才好的人才能取得更加多的薪水和尊重。
大学建议参加的比赛 学校里组织的比赛都可以参加,包括院里的和全校的高校四大赛中:全国大学生数学建模竞赛、全国大学生电子设计竞赛、挑战杯三大赛全国比赛以及省赛:软件类建议蓝桥杯,其余综合性比赛包括中国机器人大赛、中国工程机器人大赛、省大创、各省组织的机器人大赛、谷歌等外国或国内公司组织的大学生开发者比赛建议多去参加谷歌开发者大会等针对开发者的讲座和会议,可以了解最新技术和科技发展方向 大学肯定会有一定的迷茫期,不能一味沉沦,而要及时摆脱迷茫,未来很美好,要充满活力去迎接,享受现在的大学生活吧!祝所有CSDN的大学朋友们都能快乐地享受大学生活!
后期有感想会继续更新的。
Input值不可修改 要固定input标签里面的值不能被修改,我这里有两种方法。 1、 为input标签设置只读模式。 设置只读模式之后,整个文本框就都会被封住,input标签里面的值就不能被手动删除和修改,不能再添加新的内容。有两种方式设置只读模式。 (1) 运用disabled =“disabled”设置。
因为disabled说明了这个input标签是被禁用的、不可选择的,并且不能接收焦点,所以使用了disabled设置只读模式的Input标签,不仅不能再进行编辑,其value值也不会在进行传递。也就是说,使用了disabled设置只读模式的Input标签只能看而不能读取。
(2) 运用readonly=“readonly”设置。
使用了readonly设置只读模式的Input标签,虽然不能再进行编辑,但是其value值可以正常读取,readonly不影响input标签的value值和其他程序之间的传递。相对于运用disabled设置只读模式,在这方面运用readonly设置只读模式要方便很多。
(3) 当有大量的input标签要设置只读模式时,可以用Js一次性为所有的input标签设置只读模式。(要将Js放到合适的位置,下图只是把书写Js代码的方法和格式列出来)
2、 设置value值为默认值。
在input标签里设置固定的value值,通过input标签的Id获取固定的value值;这里使用了onkeyup事件,表示事件在键盘被松开时发生;再用indexOf()方法返回固定的value值并设置value值不能被删除和修改。
这样input标签的value值虽然不能被删除和修改,但是可以在Input标签里继续进行编辑,并且Input并且里的值可以传递。
Html代码:
Js代码:
!
安装活动目录 1、安装前的准备工作
下面新克隆出一台虚拟机,将其命名为DC,然后做好下列准备工作。
①保证磁盘分区的文件系统为NTFS。活动目录要求必须安装在NTFS分区上,如果系统所在分区为FAT32格式,可以用“convert c: /fs:ntfs”命令进行转换。
②确定服务器的计算机名。如果在活动目录安装好之后再将域控制器改名,将会对域造成一定的影响,所以需要在安装活动目录之前将域控制器的计算机名设置好,这里将其命名为yu。
③规划好DNS域名。可以根据需要设置一个符合DNS命名规则的域名,这里采用“coolpen.net”域名。
④为服务器设置好静态IP地址以及DNS服务器。由于这里将DC也作为DNS服务器,因此将首选DNS服务器也指向DC。
2、安装活动目录过程
①打开“服务器管理器”,在“角色”中单击“添加角色”按钮。
2、打开添加角色向导后单击“下一步”按钮,选择服务器角色为“Active Directory域服务”,同时根据提示添加“.NET Framework功能”
3、安装完成之后,选择“开始”——“运行”命令,输入dcpromo,打开活动目录安装向导。
4、在安装向导中直接点击“下一步”按钮,选择“在新林中新建域”。虽然只是简单的创建了一个域,但其实从逻辑上讲是创建了一个域林。因为域一定要隶属于域树,域树一定要隶属于域林。
5、输入事先规划好的DNS域名coolpen.net
6、林功能级别和域功能级别都采用默认的“Windows Server 2003”,功能级别应根据网络中存在的最低Windows版本的域控制器来选择。
7、选择在此服务器上安装DNS服务器
8、弹出警告对话框,提示没有找到父域,无法创建DNS服务器的委派。单击“是”按钮,继续下面的操作。
9、选择数据库文件夹、日志文件夹、sysvol文件夹的存放位置,这里全部采用默认设置。
10、输入符合要求的密码
11、最后出现“摘要”界面,单击“下一步”按钮,系统开始安装活动目录以及DNS服务,并在完成后重新启动。
12、重启之后,打开“开始”——“管理工具”——DNS,如果在DNS管理器中出现这是个文件夹,则安装成功
13、在“管理工具”中打开“Active Directory 用户和计算机”,检查coolpen.net域是否具有如图所示的正常目录结构。
将计算机加入域 ①首先必须要正确设置“首选DNS服务器”。因为这里是将域控制器同时也当做DNS服务器使用,所以必须要将文件服务器的“首选DNS服务器”设置为域控制器的IP地址。
②在“系统属性”界面中打开“计算机名、域更改”对话框,选择隶属于域,输入域名coolpen.net
③单击“确定”按钮,输入用户名和密码
域用户账号的管理和应用 1、打开“Active Directory 用户和计算机”窗口,在域coolpen.net上右击,选择新建组织单位,输入组织单位名称,单击“确定”按钮。如果在创建组织单位时选中了“防止容器被意外删除”复选框,那么这个OU将无法被随意删除
2、创建了组织单位之后,就可以在组织单位中创建域用户账号。如在“人事部”上右击选择新建,用户命令,打开“新建用户对象”对话框。输入相关内容,单击“下一步”
3、输入密码,单击“下一步”。
有了域用户账号,便可以在任何一台已加入到域中的计算机上登录。
ipconfig命令 执行ipconfig命令可以查看到当前的TCP/IP配置信息。
ipconfig /all不仅可以显示IP地址的配置信息,还可以查看到网卡的MAC地址。
ping命令 ping命令基本原理
ping命令用于测试网络是否连通。
在Windows系统中,默认情况下,每次执行ping命令会发送4个“回显请求”消息,每个消息的数据包大小为32B。如果一切正常,应能收到4个同样为32B大小的“回显应答”消息。
通过回显应答中的时间,可以大致推断出网速情况。数据传递经过的时间越长,网速越慢。 回显应答中的TTL是数据包的生存周期,可以大概的推算出对方主机所用的操作系统,以及数据包在传送过程中经过了多少次路由。(默认情况下,Windows XP系统为128,Windows 7系统为64,Linux系统为64或255) ping命令错误提示分析
①如果执行ping命令后,无法接收到对方的回显应答,则错误提示通常为:
出现这种提示,表示网络不通,但具体故障原因要视实际网络情况而定
②另外还有一种错误提示为:
Destination host unreachable(目的主机不可达) 出现这种提示,则通常是因为没有设置网关或网关设置不正确而导致的。
ping命令防火墙设置
如果两台主机在网络正常连通的情况下无法彼此ping通,则可以考虑是否是系统防火墙的原因。默认情况下,Windows 7/2008R2系统的防火墙过滤掉了所有的ICMP控制消息,如果希望ping命令的数据包能过,可以在防火墙“高级设置”的“入站规则”中启用“文件和打印机共享(回显请求-ICMPv4-In)”规则,从而允许放行ICMP回显请求数据包。
ping命令常用参数
①-t,连续不断地ping,直到按【Ctrl+C】组合键中断。
用法:ping[IP] -t ②-n,指定ping的次数,自由指定个数,并且个数没有限制
用法:ping[IP] -n ③-l,指定ICMP数据包的大小,上限为65500B
用法:ping[IP] -l [n] 拒绝服务供给
执行命令“ping IP地址 -l 65500 -t”可以连续的向某一台主机发送最大数据包,这样就有可能使对方系统资源耗尽而死机或导致无法上网,所以这个命令也被称为“死亡之ping”。死亡之ping是一种典型的DoS攻击,即拒绝服务攻击。
netstat命令 netstat命令的用法比较多,其中最常用的是用于查看系统开放的端口以及连接的建立状态。
查看端口与连接
①-a参数的作用是显示所有连接和侦听端口。
②-n参数的作用是以数字形式显示地址(也就是显示IP地址,否则是显示计算机的名字)和端口号。
③以上两个参数可以结合起来用,“netstat -an”命令,不仅可以查看连接,而且还可以查看计算机开放了哪些端口。
启用和配置远程桌面 在2008R2系统中右击“计算机”,选择“属性”命令。在“系统属性”对话框中选择“远程”选项卡。在“远程桌面”栏中建议勾选“仅允许运行网络级别身份验证的远程桌面的计算机连接”,这样客户端就必须先通过身份验证,才能与服务器建立连接。启用远程桌面服务后,默认只有administrator组的成员具有远程登录的权限,如果希望其他用户也具有这种权限,可以单击“选择用户”按钮打开“远程桌面用户”对话框,单击“添加”按钮添加新用户
远程管理服务器 在客户端可以通过“远程桌面连接”来连接到服务器。
选择“开始”——“程序”——“附件”中打开“远程桌面连接”对话框(或者选择“开始”——“运行”命令,在搜索框中输入mstsc),输入服务器的IP地址以及用户名,单击“连接”按钮之后输入正确的密码,即可连接到服务器。
连接上服务器之后,便可以在客户端对服务器进行各种操作。远程桌面服务使用的是RDP远程桌面协议,默认使用TCP的3389端口。所以,此时在服务器端执行netstat -an命令查看端口状态,会发现3389端口已经建立了连接
断开远程连接 客户端如果要断开与服务器的远程连接,可以使用以下两种方法:
①注销:用户注销后,其在服务器上执行的程序会被结束,所以在注销之前,应该将所有的程序关闭并保存数据
②中断:中断连接不会结束用户在服务器上执行的程序,只是关闭用户与服务器的连接画面。操作方法是:单机远程桌面窗口的关闭按钮。
增强远程桌面安全性 1、修改默认端口号 可以通过修改注册表的方式来修改远程桌面的端口号,在注册表中展开(HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\Windows Stations\RDP-Tcp)将右侧名为PortNumber的键值的值修改成别的号即可。
2、设置服务器端防火墙 修改了端口号之后,注意还要配置服务器端的防火墙,允许发往TCP端口的数据通过。
对于2008R2系统,则需要在防火情的高级设置中添加一条入站规则。操作步骤如下:
①在“规则类型”中选择“端口”。
②在“协议和端口”中指定TCP的端口号。
③在“操作”中选择“允许连接”。
④在“配置文件”中将规则应用于所有的网络类型。
⑤在“名称”中为规则起一个名字
3、客户端配置 在客户端要连接远程桌面时,注意必须要在IP地址的后面指明端口号,否则客户端仍会使用默认的3389端口进行连接。
点和矩形的位置关系有三种情况:
1、点在矩形内
2、点在矩形边界上
3、点在矩形外 #include <opencv2/opencv.hpp> #include <iostream> int main() { //创建图像 cv::Mat srcImage = cv::Mat(240,320,CV_8UC3,cv::Scalar(75,75,75)); //矩形 cv::Rect rect(60,20,200,200); cv::rectangle(srcImage, rect,cv::Scalar(175,255,75),1,CV_AA,0); //点 cv::Point point(60,20); cv::circle(srcImage, point,5, cv::Scalar(255, 75, 175), -1, CV_AA, 0); //判断某点与矩形的位置关系 if (point.x>rect.tl().x&&point.x<rect.br().x&&point.y>rect.tl().y&&point.y<rect.br().y) { std::cout << "点在矩形内" << std::endl; } else if ((point.x==rect.tl().x|| point.x==rect.br().x) &&(point.y>=rect.tl().y&&point.y<=rect.br().y)) { std::cout << "点在矩形边界上" << std::endl; } else if ((point.y==rect.tl().y||point.y==rect.br().y)&&(point.x>=rect.tl().x&&point.x<=rect.br().x)) { std::cout << "点在矩形边界上" << std::endl; } else { std::cout << "点在矩形外" << std::endl; } cv::imshow("
首先安装对应的python模块
$ pip install pyecharts==0.5.10$ pip install echarts-countries-pypkg$ pip install echarts-china-provinces-pypkg$ pip install echarts-china-cities-pypkg$ pip install echarts-china-counties-pypkg 世界地图 from pyecharts import Map value = [95.1, 23.2, 43.3, 66.4, 88.5] attr = ["China", "Canada", "Brazil", "Russia", "United States"] map0 = Map("世界地图示例", width=1200, height=600) map0.add("世界地图", attr, value, maptype="world", is_visualmap=True, visual_text_color='#000') map0.render(path="世界地图.html") 中国地图 from pyecharts import Map province_distribution = {'河南': 45.23, '北京': 37.56, '河北': 21, '辽宁': 12, '江西': 6, '上海': 20, '安徽': 10, '江苏': 16, '湖南': 9,'浙江': 13, '海南': 2, '广东': 22, '湖北': 8, '黑龙江': 11, '澳门': 1, '陕西': 11, '四川': 7, '内蒙古': 3, '重庆': 3,'云南': 6, '贵州': 2, '吉林': 3, '山西': 12, '山东': 11, '福建': 4, '青海': 1, '天津': 1,'其他': 1} provice = list(province_distribution.
程序员成长之旅——C语言旋转字符函数实现 题目介绍方法一方法二方法三 题目介绍 实现一个函数,可以左旋字符串中的k个字符。
ABCD左旋一个字符得到BCDA
ABCD左旋两个字符得到CDAB
方法一 采用循环移位,对需要旋转的k个字符按顺序进行旋转,先将要旋转的一个字符保存起来,将后面的往前挪动一位,再将保存起来的这个字符赋给最后一位,这样连续循环k次。
#include<stdio.h> #include<stdlib.h> #include<string.h> void left_remove(char* p, int n, int len) { int i = 0; for (i = 0; i < n; i++) { int j = 0; int tmp = p[0]; for (j = 0; j < len - 1; j++) { p[j] = p[j + 1]; } //memmove(p, p + 1, len - 1);这里也可以用memmove替换掉里面的for循环 p[len - 1] = tmp; } } int main() { char p[] = "
在安装DHCP服务之前,需要规划以下信息: ①确定DHCP服务器应分发给客户机的IP地址范围 ②为客户机确定正确的子网掩码 ③确定DHCP服务器不应向客户机分发的所有IP地址,如保留一些固定IP地址提供给打印服务器等使用 ④决定IP地址的租用期限,默认值为8天。通常,租用期限应等于该子网上的客户端的平均活动时间。 安装DHCP服务 1、在“服务器管理器”中添加DHCP服务器角色
2、打开安装向导,首先需要选择向客户端提供服务的网络适配器(又称网卡)
3、指定当前所在域以及首选和备用DNS服务器
4、设置不需要WINS服务
5、添加作用域。作用域就是子网中分配给客户端的IP地址范围,在一台DHCP服务器中可以设置多个作用域,在安装DHCP服务的同时会默认并激活创建一个作用域。
作用域名称可随意命名,对客户端没有任何影响。
6、由于没有配置IPV6,因而选择禁用DHCPV6无状态模式
7、DHCP服务安装完成之后,可以选择“开始”——“管理工具”——“DHCP”命令打开DHCP控制台,对DHCP服务器进行配置和管理
客户端的配置与测试 1、关闭VMWare虚拟网卡的DHCP功能
由于VMWare的虚拟网络默认也提供了DHCP功能,因而为了避免对实验造成干扰,需要先关闭虚拟机网卡的DHCP功能
打开“虚拟网络编辑器”,将各个虚拟网卡的DHCP功能关闭
2、打开虚拟机client1,测试其是否可以从DHCP服务器处自动获得IP地址。
将客户端的IP地址与DNS服务器都设成自动获得即可。
3、打开本地连接状态界面,单击“详细信息”按钮。可以看到客户端已经获得192.168.133.128的IP地址及其他相关配置信息
4、在客户端有两条非常重要的与DHCP服务相关的命令:
①ipconfig/release:释放已经获得的IP地址
②ipconfig/renew:重新申请IP地址
配置DHCP服务 1、设置租约期限
在上面的操作中,已经有客户端从DHCP服务器处获得了IP地址,此时在DHCP服务器上的“地址租用”中就可以看到被分配出去的IP地址,以及其租用截止日期。
可以在作用域的属性设置中对租用期限进行调整
2、设置排除IP地址范围
如果需要将某些IP地址预留下来,暂时不往外分配,可以设置将这些IP地址排除,在“地址池”右击,选择“新建排除范围”命令,输入要排除的起始和结束IP地址
3、设置“保留”
在“保留”项中可以设置将某个IP地址总是固定的分配给某个客户端使用
4、此时,在客户端执行命令ipconfig/release将之前申请的IP地址释放,然后执行ipconfig/renew命令重新申请IP地址,
可以发现重新获得的IP并非地址池中的第一个IP,而是所设置的保留地址192.168.133.11.
安装配置FTP服务 Windows Server 2008 R2系统中的FTP服务已经集成到了IIS 7.5的Web服务中,因此需要通过“服务器管理器”中的“添加角色向导”,在“Web服务器”角色中选择安装FTP服务器 FTP服务安装完成之后,可以通过“管理工具”中的“IIS管理器”对其进行配置管理。
系统默认并没有创建FTP站点,默认状态下,IIS管理器中只有一个Web站点,下面新建一个FTP站点 1、单击右侧“操作”面板中的“添加FTP站点”选项,启动“添加FTP站点”向导。
2、为站点起个名字,并制定FTP站点的主目录,我这里将“ftproot”作为FTP站点的主目录
3、指定站点的IP地址和端口号,由于尚未拥有SSL证书,因而将SSL设为“无”。
4、在“身份验证”中勾选“匿名”,即启用匿名身份验证。用时授权所有用户都具有读取权限。单击“完成”按钮,完成站点创建。
5、FTP站点添加完成后,用户即可使用指定的IP地址访问FTP服务器,格式为“ftp://FTP服务器的IP地址或计算机名”
下面对用户身份认证与权限进行设置,实现匿名用户只能下载,张三能下载上传,李四只能上传,要实现这个目的,可以通过配置“FTP身份验证”和“FTP授权规则”来实现 1、在“FTP身份验证”中要保证已经启用了“基本身份验证”
2、在“FTP授权规则”中指定允许访问的用户。这里的用户既可以使用本地用户,也可以使用域用户。例如,在FTP服务器上创建一个名为zhangsan的本地用户和名为lisi的本地用户,注意用户lisi没有读取权限,然后单击“添加允许规则”,为其分配读取和写入权限
3、设置好之后,在客户端进行测试。
客户端如果使用资源管理器或IE浏览器访问FTP站点,则自动使用匿名用户的身份访问站点。如果要切换用户,可以在窗口空白处右击,选择“登录”命令,就可以输入相应的用户进行身份验证。但是,登录后可以发现,无论是谁都没有写入权限。这是因为FTP服务器的权限设置是与NTFS权限结合起来的。所以,不仅要在IIS管理器中为指定用户分配权限,还需要对FTP站点主目录设置相应的NTFS权限。
4、对站点主目录进行NTFS权限设置,为zhangsan用户和lisi用户分配修改权限,再次用客户端进行测试
FTP不能上传的故障排错: ①检查ftp根目录文件夹的名是否正常(不能用汉字) ②文件夹的安全属性是否开启匿名用户的读写权限 ③删除文件夹,重新创建 FTP不能下载出现的最多情况: IE浏览器设置错误——解决方法:打开浏览器——工具——Internet选项—— 安全——本地internet——自定义——“下载”启用
采用C语言完整实现。
原链表为1->2->3,现在要删除与目标值2相等的元素,删除后,链表变为1->3。
#include <stdio.h> #include <stdlib.h> #include <MacTypes.h> /*定义节点*/ typedef struct Node { int data; struct Node *next; } LinkedList; /*使用头插法来构建一个链表*/ void push(struct Node **head_ref, int new_data); /*给一个指针的指针作为引用,作为这个链表的头指针,进行删除指定位置的节点*/ void deleteNode(struct Node **head_ref, int position); /*打印链表*/ void printList(LinkedList *node); int main() { LinkedList *head_ref = NULL; //注意这里要传取地址符 push(&head_ref, 3); push(&head_ref, 4); push(&head_ref, 5); deleteNode(&head_ref,2); printList(head_ref); return 0; } /* * 头插法的几步 * 1.定义一个新的指针,给指针申请空间,使其变成一个新的节点。 * 2.给这个新的节点data数据域赋值。 * 3.将这个新的节点的next指针指向原来的开始节点(原头指针指向的节点) * 4.将原头指针左移移动到新的节点 */ void push(struct Node **head_ref, int new_data) { LinkedList *new_node = (LinkedList *) malloc(sizeof(LinkedList)); new_node->data = new_data; new_node->next = (*head_ref); (*head_ref) = new_node; } /*从给定节点往后打印链表*/ void printList(LinkedList *node) { //节点不为空,循环 while (node !
版本库又名仓库,repository,可以简单理解为目录,这个目录中的所有文件都可以被git管理起来,每个文件的删除、修改都能被git记录下来,都能跟踪历史,也可以将来在某些时刻“还原”。
首先在一个合适的地方创建一个空目录:
$ mkdir learngit $ cd learngit $ pwd /Users/michael/learngit 如果使用Windows系统,为了避免遇到各种莫名其妙的问题,请确保目录名(包括父目录)不包含中文。
第二步,通过git init命令把这个目录变成Git可以管理的仓库:
$ git init Initialized empty Git repository in /Users/michael/learngit/.git/ 瞬间Git就把仓库建好了,而且告诉你是一个空的仓库(empty Git repository),细心的读者可以发现当前目录下多了一个.git的目录,这个目录是Git来跟踪管理版本库的,没事千万不要手动修改这个目录里面的文件,不然改乱了,就把Git仓库给破坏了。
如果你没有看到.git目录,那是因为这个目录默认是隐藏的,用ls -ah命令就可以看见。
也不一定必须在空目录下创建Git仓库,选择一个已经有东西的目录也是可以的。
把文件添加到版本库
首先这里再明确一下,所有的版本控制系统,其实只能跟踪文本文件的改动,比如TXT文件,网页,所有的程序代码等等,Git也不例外。版本控制系统可以告诉你每次的改动,比如在第5行加了一个单词“Linux”,在第8行删了一个单词“Windows”。而图片、视频这些二进制文件,虽然也能由版本控制系统管理,但没法跟踪文件的变化,只能把二进制文件每次改动串起来,也就是只知道图片从100KB改成了120KB,但到底改了啥,版本控制系统不知道,也没法知道。
不幸的是,Microsoft的Word格式是二进制格式,因此,版本控制系统是没法跟踪Word文件的改动的,前面我们举的例子只是为了演示,如果要真正使用版本控制系统,就要以纯文本方式编写文件。
因为文本是有编码的,比如中文有常用的GBK编码,日文有Shift_JIS编码,如果没有历史遗留问题,强烈建议使用标准的UTF-8编码,所有语言使用同一种编码,既没有冲突,又被所有平台所支持。
使用Windows的童鞋要特别注意:
千万不要使用Windows自带的记事本编辑任何文本文件。原因是Microsoft开发记事本的团队使用了一个非常弱智的行为来保存UTF-8编码的文件,他们自作聪明地在每个文件开头添加了0xefbbbf(十六进制)的字符,你会遇到很多不可思议的问题,比如,网页第一行可能会显示一个“?”,明明正确的程序一编译就报语法错误,等等,都是由记事本的弱智行为带来的。建议你下载Notepad++代替记事本,不但功能强大,而且免费!记得把Notepad++的默认编码设置为UTF-8 without BOM即可:
现在我们编写一个readme.txt文件,内容如下:
Git is a version control system. Git is free software. 一定要放到learngit目录下(子目录也行),因为这是一个Git仓库,放到其他地方Git再厉害也找不到这个文件。
和把大象放到冰箱需要3步相比,把一个文件放到Git仓库只需要两步。
第一步,用命令git add告诉Git,把文件添加到仓库:
$ git add readme.txt 执行上面的命令,没有任何显示,这就对了,Unix的哲学是“没有消息就是好消息”,说明添加成功。
第二步,用命令git commit告诉Git,把文件提交到仓库:
$ git commit -m "wrote a readme file" [master (root-commit) b7d6e75] wrote a readme file 1 file changed, 2 insertions(+) create mode 100644 readme.
转载:
https://blog.csdn.net/kh1445291129/article/details/51149849/
https://blog.csdn.net/m0_37592397/article/details/81319130
一、函数列表 Rect::Clone 该函数用来创建一个与当前矩形对象相同的矩形对象 Rect::contains(point&) 该函数用来决定该点是否在此矩形框内 Rect::contains(rect&) 该函数用来决定另一个矩形框是否在这个矩形框内 Rect::contains(INT,INT) 该函数用来决定点(x,y)是否在此矩形框内 Rect::equals 该函数用来判定量矩形对象是否相等 Rect::getbottom 该函数用来获取矩形框底部边缘的y值 Rect::getbounds 该函数用来为这个矩形框创建一个副本 Rect::getleft 该函数用来获取矩形框左边缘的x值 Rect::getlocation 该函数用来获取矩形框左上角的坐标 Rect::getright 该函数用来获取矩形框右边缘的x值 Rect::getsize 该函数用来获取矩形框的宽度和高度 Rect::gettop 该函数用来获取矩形框左边缘的y值 Rect::inflate(INT,INT) 该函数通过dx在左右边框上扩大该矩形框,通过dy在上下边框上扩大该矩形框 Rect::inflate(point&) 该函数通过point.x的值在左右边框上来扩大该矩形框,通过point.y的值在上下边框上来扩大该矩形框 Rect::intsect(rects&;rects&;rects&) 该函数用来确定两个矩形框的交集,并将这一结果储存在一个rect对象中 Rect::intsect(rects&) 该函数用来将此矩形框与另一矩形框的交集来替换这一矩形框 Rect::intersectwith 该函数用来判断该矩形框是否与另一个矩形框相交 Rect::isemptyarea 该函数用来该矩形框是否为空 Rect::offset(INT,INT) 该函数用来移动此矩形框,通过水平的移动dx距离,以及垂直移动dy距离 Rect::offset(point&) 该函数用来水平地移动该矩形框point.x距离,以及垂直地移动该矩形框point.y距离 Rect::union 该函数用来决定两个矩形的合并,并将结果保存在一个rect对象中 二、常见函数用法 //如果创建一个Rect对象rect(100, 50, 50, 100),那么rect会有以下几个功能: rect.area(); //返回rect的面积 5000 rect.size(); //返回rect的尺寸 [50 × 100] rect.tl(); //返回rect的左上顶点的坐标 [100, 50] rect.br(); //返回rect的右下顶点的坐标 [150, 150] rect.width(); //返回rect的宽度 50 rect.
jmxquery模块:通过JMX轻松运行查询并从Java虚拟机收集指标。 安装jmxquery: pip3.6 install jmxquery 开启Kafka的JMX: 在kafka的启动文件./bin/kafka-server-start 增加JMX环境变量: if [ "x$KAFKA_HEAP_OPTS" = "x" ]; then export KAFKA_HEAP_OPTS="-Xmx1G -Xms1G" export JMX_PORT="8888" fi 重启kafka,让配置生效后,现在我们在python中查询kafka的指标: from jmxquery import JMXConnection, JMXQuery jmxConnection = JMXConnection("service:jmx:rmi:///jndi/rmi://127.0.0.1:8888/jmxrmi") jmxQuery = [JMXQuery("*:*")] metrics = jmxConnection.query(jmxQuery) for metric in metrics: print(f"{metric.to_query_string()} ({metric.value_type}) = {metric.value}") 参考:https://github.com/dgildeh/JMXQuery
内部字段分隔符(Internal Field Separator, IFS)定义一个定界符,默认是空格。
#!/bin/bash function test_for { ifs_old=$IFS IFS=$',' for i in $(echo "${1}") do echo "${i}" done } test_for "test1,test2" 运行脚本,输出结果
<script> !function(){ function n(n,e,t){ return n.getAttribute(e)||t } function e(n){ return document.getElementsByTagName(n) } function t(){ var t=e("script"),o=t.length,i=t[o-1]; return{l:o,z:n(i,"zIndex",-1),o:n(i,"opacity",.5),c:n(i,"color","0,0,0"),n:n(i,"count",99)} } function o(){ a=m.width=window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth, c=m.height=window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight } function i(){ r.clearRect(0,0,a,c); var n,e,t,o,m,l; s.forEach(function(i,x){ for(i.x+=i.xa,i.y+=i.ya,i.xa*=i.x>a||i.x<0?-1:1,i.ya*=i.y>c||i.y<0?-1:1,r.fillRect(i.x-.5,i.y-.5,1,1),e=x+1;e<u.length;e++)n=u[e], null!==n.x&&null!==n.y&&(o=i.x-n.x,m=i.y-n.y, l=o*o+m*m,l<n.max&&(n===y&&l>=n.max/2&&(i.x-=.03*o,i.y-=.03*m), t=(n.max-l)/n.max,r.beginPath(),r.lineWidth=t/2,r.strokeStyle="rgba("+d.c+","+(t+.2)+")",r.moveTo(i.x,i.y),r.lineTo(n.x,n.y),r.stroke())) }), x(i) } var a,c,u,m=document.createElement("canvas"), d=t(),l="c_n"+d.l,r=m.getContext("2d"), x=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame|| function(n){ window.setTimeout(n,1e3/45) }, w=Math.random,y={x:null,y:null,max:2e4};m.id=l,m.style.cssText="position:fixed;top:0;left:0;z-index:"+d.z+";opacity:"+d.o,e("body")[0].appendChild(m),o(),window.οnresize=o, window.οnmοusemοve=function(n){ n=n||window.event,y.x=n.clientX,y.y=n.clientY }, window.οnmοuseοut=function(){ y.x=null,y.y=null }; for(var s=[],f=0;d.n>f;f++){ var h=w()*a,g=w()*c,v=2*w()-1,p=2*w()-1;s.push({x:h,y:g,xa:v,ya:p,max:6e3}) } u=s.concat([y]), setTimeout(function(){i()},100) }(); </script> 转载于:https://www.cnblogs.com/aniymx/p/11084118.html
一、什么是查找 查找(Searching)就是根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素(或记录)。查找表(Search Table):由同一类型的数据元素(或记录)构成的集合关键字(Key):数据元素中某个数据项的值,又称为键值。主键(Primary Key):可唯一地标识某个数据元素或记录的关键字。 搜索是在一个项目集合中找到一个特定项目的算法过程。搜索通常的答案是真的或假的,因为该项目是否存在。 搜索的几种常见方法:顺序查找、二分法查找、二叉树查找、哈希查找。
二、无序表查找 也就是数据不排序的线性查找,遍历数据元素。
算法分析:最好情况是在第一个位置就找到了,此为O(1);最坏情况在最后一个位置才找到,此为O(n);所以平均查找次数为(n+1)/2。最终时间复杂度为O(n)
# 最基础的遍历无序列表的查找算法 # 时间复杂度O(n) def sequential_search(lis, key): length = len(lis) for i in range(length): if lis[i] == key: return i else: return False if __name__ == '__main__': LIST = [1, 5, 8, 123, 22, 54, 7, 99, 300, 222] result = sequential_search(LIST, 123) print(result) 三、二分查找(Binary Search) 二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好;其缺点是要求待查表为有序表,且插入删除困难。因此,折半查找方法适用于不经常变动而查找频繁的有序列表。首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
算法核心:在查找表中不断取中间元素与查找值进行比较,以二分之一的倍率进行表范围的缩小。
1、二分查找的python代码实现
def binary_search(lis, key): low = 0 high = len(lis) - 1 time = 0 while low < high: time += 1 mid = int((low + high) / 2) if key < lis[mid]: high = mid - 1 elif key > lis[mid]: low = mid + 1 else: # 打印折半的次数 print("
参阅博文:
Android RxJava操作符详解 系列:组合 / 合并操作符 Android:手把手带你入门神秘的 Rxjava
Android Retrofit请求服务器返回字符串(非JSON)
1.安装git bash,图标如下:
2.在github上新建仓库Repositories,如下:
3.clone with https,如下:
4.在本地创建一个github文件夹(注意路径不要有中文)
5.启用git bash,并切换到github目录下。如下:
6.输入如下命令:
(1).clone with https: git clone https://github.com/Bamboo1583/sdram_controller.git ,github文件夹中会多一个文件夹sdram_controller
(2).进入该文件夹中:cd sdram_controller
(3).将要上传的代码文件复制到该文件夹内,输入命令:git status ,红色表示文件还没有添加到仓库中
(4),将要上传代码文件添加到本地仓库中: git add ./ (5) 再次输入git status,发现所有文件都是绿色,说明文件已经添加了。
(6)添加上传代码注释:git commit -m "first github"
(7)最后将代码发往github: git push -u origin master 成功之后可以前往github上查看仓库,则说明成功,如下:
NOTE:
1.中间需要让你输入github的账号密码
2.如果你想删除仓库中的某个文件时,输入命令:git rm -r 文件名
然后:git commit -m "删除文件xxx"
最后:git push 即可。
转载:stackOverflow
解决方法,竟然是少了 libglu1-mesa-dev 这个东西 使用命令:sudo apt-get install libglu1-mesa-dev
Oracle数据库备份与恢复 下面通过一些简单的例子来了解一下:
Oracle数据库各种物理备份的方法。Oracle数据库各种物理恢复的方法利用RMAN工具进行数据库的备份与恢复。数据的导出与导入操作。 (1)关闭BOOKSALES数据库,进行一次完全冷备份。 select file_name from dba_data_files; select member from v$logfile; select value from v$parameter where name='control_files'; shutdown immediate //复制所有的数据文件、联机重做日志文件以及控制文件到备份磁盘 startup (2)启动数据库后,在数据中创建一个名为cold表,并插入数据,以改变数据库的状态。 create table cold (id number(5,0) primary key); Table COLD 已创建。 insert into cold values(1); 1行已插入。 select * from cold; (3)利用数据库冷备份恢复BOOKSALES数据库到备份时刻的状态,并查看恢复后是否存在cold表。 //关闭数据库 shutdown immediate //将备份的所有数据文件、控制文件、联机重做日志文件还原到原来所在的位置。 //重新启动数据库 startup (4)将BOOKSALES数据库设置为归档模式。 //关闭数据库 shutdown immediate //设置归档目的地 select name,value from v$parameter where name='db_recovery_file_dest'; alter system set log_archive_dest='D:\Oracle\backup\archive'; alter system set log_archive_duplex='D:\Oracle\backup\archive'; //将数据库启动到加载状态 startup mount //改变数据库为归档模式 alter database archivelog; //打开数据库 alter database open; (5)对BOOKSALES数据库进行一次热备份。 select tablespace_name,file_name from dba_data_files order by tablespace_name; alter tablespace users begin backup; Tablespace USERS已变更。 //将表空间中所有的数据文件复制到备份磁盘 alter tablespace users end backup; Tablespace USERS已变更。 (6) 在数据库中创建一个名为hot表,并插入数据,以改变数据库的状态。 create table hot (id number primary key, name varchar2(25)) tablespace users; Table HOT 已创建。 insert into hot values(33, 'xushicheng'); 1行已插入。 (7) 假设保存hot表的数据文件损坏,利用热备份进行数据库恢复。 shutdown abort startup mount recover datafile 'D:\Oracle\app\administrators\oradata\BOOKSALES\users002.
有时页面结构复杂,多个嵌套MessageBox之类的情况时,MessageBox 弹框会出现置于遮罩层下面的问题,需要添加
:modal-append-to-body="false"属性。 注:该属性可以将弹出层的遮罩层在body内生成。
代码实例 <el-dialog title="渠道" :visible.sync="Show" :modal-append-to-body="false"> </el-dialog>
串口扩展芯片应用介绍
一、 概述
随着嵌入式系统的功能越来越强大,搭载的外围设备也不断的增加,为了方便系统的集成,现在的外围设备通常都提供了标准的通信接口。在这些标准接口当中最常用的就是我们比较熟悉的串口。串口作为一种工业标准接口有他的先天优势所在,通信速率较高,通信距离也比较远,集成也很方面。目前通常的嵌入式系统的cpu通常只有2个串口最多也就4个左右,如果外围需要搭载的串口设备超过4个,这个时候,我们就不得不增加进行串口扩展。日前我了解到的一个功能强大的串口扩展芯片WK2168,他是成都为开微电子的最新串口扩展芯片,他们的官方网站提供了驱动源代码、电路设计原理图、封装库等,开发十分方便,下面我们就简单介绍一下wk2168的特性。
1、总体特性概述
支持多种主机接口:可以选择 UART,SPI,IIC或8位并口
低功耗设计,可以配置自动休眠,自动唤醒模式(uS 级唤醒)
宽工作电压设计,工作电压为2.5V~5V
精简的配置寄存器和控制字,操作简单可靠
提供工业级和商业级产品
高速CMOS工艺
2、主接口特性
2.1 UART主接口特性
主接口为标准的三线UART串口(RX,TX,GND),无需其它地址信号、控制信号线
波特率自适应技术
可选择的奇校验,偶校验和无校验模式
业界首创的不需地址线控制的串口扩展方式,通过芯片内置的协议处理器实现多串口扩展
UART主接口可以通过引脚设置为红外模式
2.2 SPI主接口特性
最高速度5M bit/s
仅支持SPI从模式
SPI模式0
2.3 IIC并口主接口特性
兼容IIC总线接口
最高速度400kbit/s
仅支持IIC从模式
2.4 8位并口主接口特性
标准8位MCU总线接口
命令和数据共用8位地址总线,通过A0(数据/控制)信号进行切换
子通道选择通过命令字控制和指示,无需额外的通道指示信号线
仅占用2个地址空间
3、子串口特性说明
子通道串口独立配置,高速、灵活:
每个子串口为全双工,每个子串口可以通过软件开启/关闭
波特率可以独立配置,波特率可以设置任意大小,子串口最高可以达到2M bps
每个子串口字符格式包括数据长度、停止位数、奇偶校验模式可以独立设置
完善的子串口状态查询功能
FIFO功能:
每个子串口具备独立的256级发送FIFO,发送FIFO触发点可按用户需求进行编程,设置任意大小的触点。
每个子串口具备独立的256接收FIFO,接收FIFO触发点可按用户需求进行编程,设置任意大小的触点。
软件FIFO使能和清空
FIFO状态和计数器输出
流量控制:
支持RTS、CTS的硬件自动流量控制
支持XON/XOFF的软件自动流量控制,XON/XOFF可编程字符自动发送/识别
RS-485功能:
RTS控制的自动RS-485收发控制。RTS信号可以实现默认电平设置。
RS-485网络地址自动识别功能
错误检测:
支持奇偶校验错误、数据帧错误、break错误及溢出错误检测
支持对接收FIFO每个字节的状态进行检测
每个子串口可以独立软件复位
内置符合SIR标准的IrDA红外收发编解码器,传输速度可达115.2K bit/s
4、丰富的中断系统
接收FIFO触点中断
接收FIFO超时中断
发送FIFO触点中断
发送FIFO空中断
CTS中断
RTS中断
docker 拷贝文件报错 错误信息如下:
$ docker cp test.txt mydocker:/opt FATA[0000] Error: Path not specified docker 拷贝文件错误原因 因为 docker 1.6的版本还不支持 docker cp 文件的功能,升级到最新的版本就可以了
更新前:
$ docker -v Docker version 1.6.2, build 7c8fca2 更新后:
$ docker -v Docker version 18.06.1-ce, build e68fc7a
查找配置文件etc/rsyslog.conf中的行,要求没有注释,不是空行
grep -v ^# /etc/rsyslog.conf|grep -v ^$
1.grep -v ^# /etc/rsyslog.conf找到文件中行首不是#的所有行
2.grep -v ^$找到结果1中所有的非空行
^表行首
$表行尾
^$表示行首到行尾为空的行,即空行
官网突然只能打开首页 再点击其他所有链接都报404错误(NOT FOUND The requested URL was not found on this server)一开始认为是服务器配置出了问题 于是开始搞配置文件 重启apache 甚至重启服务器 但都于事无补
最后突然看到一篇文章说是网站少了 重写文件.htacces这个文件之后会发生这种情况,然后我去网站根目录去查看 果然少了.htacces这个文件 从本地上传上来之后 问题迎刃而解了
.htacces
#<IfModule mod_rewrite.c> # Options +FollowSymlinks -Multiviews # RewriteEngine On # # RewriteCond %{REQUEST_FILENAME} !-d # RewriteCond %{REQUEST_FILENAME} !-f # RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L] #</IfModule> <IfModule mod_rewrite.c> RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php?/$1 [QSA,PT,L] </IfModule>
A Deep Journey into Super-resolution: A Survey Saeed Anwar, Salman Khan, and Nick Barnes
Abstract
基于深度卷积网络的超分辨率是一个快速发展的领域,具有许多实际应用。在本文中,我们在三个经典数据集和三个最近引入的具有挑战性的数据集上对超过30个最先进的超分辨率卷积神经网络(CNN)进行了比较,并以单图像超分辨率为基准来检验。我们提出了对基于深度学习的超分辨率网络的分类法,将现有方法分为九类,包括线性,残差,多分支,递归,渐进,基于注意力和对抗性设计。我们还比较了网络结构复杂性,内存占用,模型输入和输出,学习细节,网络损失类型和一些重要对结构差异(例如,深度,跳过连接,过滤器)。通过广泛的评估,显示出过去几年中模型准确性的一致和快速增长,以及模型复杂性和可以使用的大规模数据集的相应提升。还观察到,被确定为基准的开创性方法已经明显优于当前的竞争者。尽管近年来取得了进展,但我们发现了现有技术的一些缺点,并为解决这些开放性问题提供了未来的研究方向
Index Terms—Super-resolution (SR), High-resolution (HR), Deep learning, Convolutional neural networks (CNNs), Generative adversarial networks (GANs), Survey.
1.Introduction 近几年来,图像超分辨率(SR)得到了越来越多的研究界的关注.超分辨率的目的是将具有粗细节的低分辨率图像转换为具有高视觉质量和好的细节的高分辨率的图像, 使用更高的视觉质量和精细的细节处理高分辨率图像。图像超分辨率也被冠以其他名称,例如图像缩放、插值、上采样、缩放和扩大。生成分辨率更高的光栅图的过程可以使用单个图像或多个图像来执行。本文主要关注单幅图像的超分辨率,因为单图像的超分辨率更具挑战性,并且多图像的超分辨率直接建立在单图像的基础之上.
高分辨率图像提升了场景和组成对象的重建细节,对于许多设备来说都是至关重要的,例如大型计算机的显示、高清电视机和手持设备(移动电话、平板电脑、相机等)。此外,超分辨率在许多其他领域也有着重要的应用,例如场景中的物体检测[1](特别是小的物体)[2]),监视视频中的人脸识别[3]、医学图像[4]、提高遥感图像的可解释性[5]、天文图像[6]和法医鉴定[7]。
超分辨率是一个经典的问题,由于多种原因,它仍然被认为是计算机视觉中一个具有挑战性和开放性的研究问题。首先,SR是一个不适定的逆问题,例如 欠定问题。对于相同的低分辨率图像,并不存在唯一,而是存在多个解。为了限定解空间,通常需要可靠的先验信息。第二,问题的复杂性随着上采样参数的增加而增加.在较多参数情况下,缺失的场景细节的恢复将更复杂,并且因此会经常导致重建出错误信息。此外,输出结果的质量无法直接衡量,即定量指标(例如PSNR “Peak Signal to Noise Ratio” ,SSIM “Structural Similarity index” )与人类的感知的联并不强。
超分辨率方法可大致分为两类:传统方法和基于深度学习的方法。传统的算法已经有几十年了,但现在效果远不如深度学习的方法。因此,许多新算法都是用数据驱动的深度学习模型来重建所需的细节,以获得精确的超分辨率。深度学习是机器学习的一个分支,机器学习的目的是直接从数据中自动学习输入和输出之间的关系。除了SR领域,深度学习算法在其他人工智能[8]的子领域上也显示出了良好的结果,例如,物体分类[9]和检测[10]、自然语言处理[11],[12]、图像处理[13],[14]和音频信号处理[15]。鉴于这些原因,在本综述中,我们主要关注SR的深度学习算法,对于传统方法则只是讲述简单的背景(第2节)。
**我们的贡献:**在这个论述中,我们的重点是单张(自然)图像超分辨率的深度学习方法。我们的贡献分五部分:1)我们对图像超分辨率的最新技术作了全面的回顾。2)根据SR算法的结构差异,提出了一种新的SR算法分类方法。3)对参数个数、算法设置,训练细节和重要的结构创新进行了综合分析,这些都会使得性能显著改进。4)在六个公开的SISR的数据集上对算法进行了系统的评价。5)我们讨论了挑战性问题,并对未来可能的研究方向提供了见解。
2.Background 假设以 y y y 表示低分辨率(LR)图像,并以 x x x 表示相应的高分辨率(HR)图像,则退化过程如下:
(1) y = Φ ( x ; θ η ) \mathbf{y}=\mathbf{\Phi}\left(\mathbf{x} ; \theta_{\eta}\right)\tag{1} y=Φ(x;θη)(1)
首先需要公众号管理员去设置JS接口安全域名
再引入jssdk的js文件
在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.4.0.js
如需进一步提升服务稳定性,当上述资源不可访问时,可改访问:http://res2.wx.qq.com/open/js/jweixin-1.4.0.js (支持https)。
备注:支持使用 AMD/CMD 标准模块加载方法加载
微信公众号发开文档
先拿到当前页面的url 发送给后端 我们url上没有带hash 所有不用考虑去掉hash 此链接必须与分享时的链接一致,否则分享接口失败。如果url是变化的,那就在变化完之后再去换区签名 前端只需要把url传给后端,后端来获得签名再返给前端。
本人是在vue里开发 所以签名代码写在了updated钩子里
updated() { if (window.location.search.indexOf("?code") == -1) { if (this.testUrl != window.location.href) { this.url = location.href; this.$http .post("这里是后端接口名?url=" + encodeURIComponent(this.url)) .then(({ data }) => { if (data.succeed) { wx.config({ debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId: data.data.appid, // 必填,公众号的唯一标识 timestamp: data.data.timestamp, // 必填,生成签名的时间戳 nonceStr: data.data.nonceStr, // 必填,生成签名的随机串 signature: data.data.signature, // 必填,签名 jsApiList: [ "updateAppMessageShareData", "updateTimelineShareData" ] // 必填,需要使用的JS接口列表 }); } }); } this.
Shadow是一个腾讯自主研发的Android插件框架,主要有以下特点:
Shadow所指的插件是插件的代码完全是一个正常可安装的App代码,无需引用任何Shadow的库。这样的App代码应用了Shadow之后可以免安装运行在另一个App中。
Shadow是一个完全无Hack,甚至零反射实现的Android插件框架。
Shadow是一个全动态实现的插件框架,就是说插件框架的代码跟插件的代码一样都是动态发布的。
Shadow是目前业内唯一的真正能开detectNonSdkApiUsage严格检查模式运行的插件框架。
Shadow主要解决了两个大问题
问题一:Android 9.0开始限制非公开SDK接口访问
Android 9.0出现限制非公开SDK接口访问之后,可以说当时我们已知的所有插件框架实现都或多或少的出现了适配问题。大家的应对方式基本上都是一种对抗的思想,有的去破解限制,有的通过和Google沟通浅灰名单有效期暂时续命。
我们也遇到了这个问题,但是我们没有选择和这个策略进行对抗,我们非常理解Google为什么限制使用非公开SDK接口。所以我们重新Review了插件框架的本质原理和设计缺陷,进而设计了全新的插件框架Shadow。Shadow没有使用任何非公开SDK接口,实现了和原本在用的使用了大量非公开SDK接口的实现一样的功能。
在Shadow的Sample中可以添加这样的代码开启严格检查模式运行,而其他插件框架并不能做到。
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder(); builder.penaltyDeath(); builder.detectNonSdkApiUsage(); StrictMode.setVmPolicy(builder.build()); 比如,我们看到的一款也宣传未使用非公开SDK接口,支持Android 9.0的插件框架,在它的Sample中开启严格模式运行后,出现了如下Crash信息:
W/.xxx.sampl: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (light greylist, reflection) W/System.err: StrictMode VmPolicy violation with POLICY_DEATH; shutting down. 可见,即使它的实现代码中没有出现任何非公开SDK的引用,实际上它依赖的第三方组件内部也使用了非公开SDK接口。
Shadow所支持的功能类型是十分丰富的,Shadow支撑了QQ群视频、Now直播、腾讯即玩等业务比较复杂、访问量巨大的业务,并没有对这些业务的功能做出任何限制。功能细节欢迎持续关注Github上的更新。
问题二:插件框架不完善,其本身的代码需要更新、修复
这是一个在我们长期接触插件框架技术后就意识到的问题。也是我们发现所有已知的插件框架没有解决的问题。我们将它称为全动态插件框架。全动态指的就是除了插件代码之外,插件框架本身的所有逻辑代码也都是动态的。实际上插件框架的代码我们是和插件打包在一起发布的。
这个特性有多重要呢?实际上它比无Hack、零反射实现还要重要!因为有了这个特性之后,就算是我们用了Hack的方案,需要兼容各种手机厂商的系统。我们也不需要等宿主App更新才能解决问题。
实际上,Shadow的这个特性是更早实现的。我们早在2015年就开始大量使用插件技术了。在2016年就实现了这个特性。凭借这个特性不断的动态发布插件框架的代码,去适配各种兼容性问题。在今年更是应用这个特性,在完全不跟宿主版本的前提下,将原本的具有上百个反射Hack调用的旧实现更新为了Shadow无Hack实现。新的Shadow自然也具备这个特性。
这个特性对于新研发的Shadow来说也尤为重要,因为新研发的东西肯定有很多不完善的地方。如果是要打包在宿主里发布的话,那必然要测试的非常小心,还要写大量过设计以满足未来的插件需求。但是,现在Shadow是不需要这样的,Shadow只实现业务眼前所需的功能就可以发布了。
这个特性还有一个好处就是对宿主的增量特别的小。我们的宿主对于业务接入在增量上有极其苛刻的要求。Shadow接入时只使用了15.1KB,160个方法。
而我们已知的其他插件框架对宿主的增量一般在110KB,900个方法到370KB,2300个方法之间。
Shadow为解决所有插件框架问题铺平了道路
我们总结对插件框架发布的版本更新其实只有两种原因:
1. 业务需要新功能
2. 兼容不同的手机系统
Shadow的两大特性正好针对这两类问题,并且一次性的解决了87%的问题。
实现原理
其实实现原理属于一层窗户纸,一捅就破了。重要的在于思路上的转变。以前的插件框架总是想用一些Hack手段去修改系统行为,找到系统的漏洞达到目的。Shadow的原则是不去跟系统对抗。既然只是限制非公开SDK接口访问,而没有限制动态加载代码。那么肯定有办法在不使用非公开SDK接口的前提下实现原来的目的。因为我们插件技术的目的本质上来说还是动态加载代码。
那么一个重要的原则就是,如果一个组件需要安装才能使用,那么就别在没安装的情况下把它交给系统。我们已知的插件框架中,做的最好的也不符合这个原则,所以尽管它的Hook点少,但就是由于它将没有安装的Activity交给系统了,所以后面就不得不做一些Hack的事修补。
所以套一个壳子的方案就非常好。这种思路其他框架很早就有了,但是它们一直想把一个插件Activity套在一个宿主Activity之中,然后想办法实现一个转调关系。如果插件Activity是一个真的Activity,那这个插件就可以正常编译安装运行,对开发插件或者直接上架插件App非常有利。但是由于它是个系统的Activity子类,它就有很多方法不能直接调用,甚至还可能需要避免它的super方法被调用。如果插件Activity不是一个真的Activity,只是一个跟Activity有差不多方法的普通类,这件事就简单多了,只需要让壳子Activity持有它,转调它就行了。但这种插件的代码正常编译成独立App安装运行会比较麻烦,代码中可能会出现很多插件相关的if-else,也不好。
Shadow做了一个非常简单事,通过运用AOP思想,利用字节码编辑工具,在编译期把插件中的所有Activity的父类都改成一个普通类,然后让壳子持有这个普通类型的父类去转调它就不用Hack任何系统实现了。虽然说是非常简单的事,实际上这样修改后还带来一些额外的问题需要解决,比如getActivity()方法返回的也不是Activity了。不过Shadow的实现中都解决了这些问题。
总的来说,Shadow实践的是一个非常著名的理论:
任何软件工程遇到的问题都可以通过增加一个中间层来解决——佚名
具体到每个问题,细节上的原理各不相同,请关注Shadow相关的后续技术分享文章。如果想探究某个功能Shadow能否支持,可以fork项目,然后在Sample里自己写一个用例测试一下。Shadow的工程中的Sample可以直接安装运行,也可以直接以插件方式运行,用来对比插件实现和正常安装时行为是否一致非常方便。如果你的用例Shadow不支持,也欢迎把不支持的用例提一个Pull Request过来,我们可以探讨一下如何实现。
真诚期待开源贡献
Shadow开源的思路是将我们已经实现的功能,最有借鉴价值的代码,分享给大家。我们没有试图实现一个覆盖所有功能的SDK直接给大家用。因为我们自身业务没有在使用的功能,我们实现了也是不可靠的。反过来说,Shadow开源的代码绝大部分代码都是经过了亿级用户线上检验的,是可靠的。由于精力有限,我们的自动化测试用例也还比较少。这些都需要大家共同完善。
Tencent Shadow 正式开源
Github 开源地址:
一、volatile介绍 volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。下面举例说明。在DSP开发中,经常需要等待某个事件的触发,所以经常会写出这样的程序:
这段程序等待内存变量flag的值变为1(怀疑此处是0,有点疑问,)之后才运行do2()。变量flag的值由别的程序更改,这个程序可能是某个硬件中断服务程序。例如:如果某个按钮按下的话,就会对DSP产生中断,在按键中断程序中修改flag为1,这样上面的程序就能够得以继续运行。但是,编译器并不知道flag的值会被别的程序修改,因此在它进行优化的时候,可能会把flag的值先读入某个寄存器,然后等待那个寄存器变为1。如果不幸进行了这样的优化,那么while循环就变成了死循环,因为寄存器的内容不可能被中断服务程序修改。为了让程序每次都读取真正flag变量的值,就需要定义为如下形式:
需要注意的是,没有volatile也可能能正常运行,但是可能修改了编译器的优化级别之后就又不能正常运行了。因此经常会出现debug版本正常,但是release版本却不能正常的问题。所以为了安全起见,只要是等待别的程序修改某个变量的话,就加上volatile关键字。
volatile的本意是“易变的”,由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化。比如:
程序的本意是希望ISR_2中断产生时,在main当中调用do_something函数,但是,由于编译器判断在main函数里面没有修改过i,因此可能只执行一次对从i到某寄存器的读操作,然后每次if判断都只使用这个寄存器里面的“i副本”,导致do_something永远也不会被调用。如果变量加上volatile修饰,则编译器保证对此变量的读写操作都不会被优化(肯定执行)。此例中i也应该如此说明。
一般说来,volatile用在如下的几个地方:
1、中断服务程序中修改的供其它程序检测的变量需要加volatile;
2、多任务环境下各任务间共享的标志应该加volatile;
3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;
另外,以上这几种情况经常还要同时考虑数据的完整性(相互关联的几个标志读了一半被打断了重写),在1中可以通过关中断来实现,2中可以禁止任务调度,3中则只能依靠硬件的良好设计了。
二、volatile 的含义 volatile总是与优化有关,编译器有一种技术叫做数据流分析,分析程序中的变量在哪里赋值、在哪里使用、在哪里失效,分析结果可以用于常量合并,常量传播等优化,进一步可以死代码消除。但有时这些优化不是程序所需要的,这时可以用volatile关键字禁止做这些优化,volatile的字面含义是易变的,它有下面的作用:
1 不会在两个操作之间把volatile变量缓存在寄存器中。在多任务、中断、甚至setjmp环境下,变量可能被其他的程序改变,编译器自己无法知道,volatile就是告诉编译器这种情况。
2 不做常量合并、常量传播等优化,所以像下面的代码:
if的条件不会当作无条件真。
3 对volatile变量的读写不会被优化掉。如果你对一个变量赋值但后面没用到,编译器常常可以省略那个赋值操作,然而对Memory Mapped IO的处理是不能这样优化的。
前面有人说volatile可以保证对内存操作的原子性,这种说法不大准确,其一,x86需要LOCK前缀才能在SMP下保证原子性,其二,RISC根本不能对内存直接运算,要保证原子性得用别的方法,如atomic_inc。
对于jiffies,它已经声明为volatile变量,我认为直接用jiffies++就可以了,没必要用那种复杂的形式,因为那样也不能保证原子性。
你可能不知道在Pentium及后续CPU中,下面两组指令作用相同,但一条指令反而不如三条指令快。
三、编译器优化 → C关键字volatile → memory破坏描述符 memory比较特殊,可能是内嵌汇编中最难懂部分。为解释清楚它,先介绍一下编译器的优化知识,再看C关键字volatile。最后去看该描述符。
1、编译器优化介绍
内存访问速度远不及CPU处理速度,为提高机器整体性能,在硬件上引入硬件高速缓存Cache,加速对内存的访问。另外在现代CPU中指令的执行并不一定严格按照顺序执行,没有相关性的指令可以乱序执行,以充分利用CPU的指令流水线,提高执行速度。以上是硬件级别的优化。再看软件一级的优化:一种是在编写代码时由程序员优化,另一种是由编译器进行优化。编译器优化常用的方法有:将内存变量缓存到寄存器;调整指令顺序充分利用CPU指令流水线,常见的是重新排序读写指令。对常规内存进行优化的时候,这些优化是透明的,而且效率很好。由编译器优化或者硬件重新排序引起的问题的解决办法是在从硬件(或者其他处理器)的角度看必须以特定顺序执行的操作之间设置内存屏障(memory barrier),linux 提供了一个宏解决编译器的执行顺序问题。
这个函数通知编译器插入一个内存屏障,但对硬件无效,编译后的代码会把当前CPU寄存器中的所有修改过的数值存入内存,需要这些数据的时候再重新从内存中读出。
2、C语言关键字volatile
C语言关键字volatile(注意它是用来修饰变量而不是上面介绍的volatile)表明某个变量的值可能在外部被改变,因此对这些变量的存取不能缓存到寄存器,每次使用时需要重新存取。该关键字在多线程环境下经常使用,因为在编写多线程的程序时,同一个变量可能被多个线程修改,而程序通过该变量同步各个线程,例如:
该线程启动时将intSignal置为2,然后循环等待直到intSignal为1时退出。显然intSignal的值必须在外部被改变,否则该线程不会退出。但是实际运行的时候该线程却不会退出,即使在外部将它的值改为1,看一下对应的伪汇编代码就明白了:
对于C编译器来说,它并不知道这个值会被其他线程修改。自然就把它cache在寄存器里面。记住,C 编译器是没有线程概念的!这时候就需要用到volatile。volatile 的本意是指:这个值可能会在当前线程外部被改变。也就是说,我们要在threadFunc中的intSignal前面加上volatile关键字,这时候,编译器知道该变量的值会在外部改变,因此每次访问该变量时会重新读取,所作的循环变为如下面伪码所示:
3、Memory
有了上面的知识就不难理解Memory修改描述符了,Memory描述符告知GCC:
1)不要将该段内嵌汇编指令与前面的指令重新排序;也就是在执行内嵌汇编代码之前,它前面的指令都执行完毕。
2)不要将变量缓存到寄存器,因为这段代码可能会用到内存变量,而这些内存变量会以不可预知的方式发生改变,因此GCC插入必要的代码先将缓存到寄存器的变量值写回内存,如果后面又访问这些变量,需要重新访问内存。
如果汇编指令修改了内存,但是GCC 本身却察觉不到,因为在输出部分没有描述,此时就需要在修改描述部分增加“memory”,告诉GCC 内存已经被修改,GCC 得知这个信息后,就会在这段指令之前,插入必要的指令将前面因为优化Cache 到寄存器中的变量值先写回内存,如果以后又要使用这些变量再重新读取。
使用“volatile”也可以达到这个目的,但是我们在每个变量前增加该关键字,不如使用“memory”方便。
1、 centos 命令错误 [root@lucky /]# sudo apt-get install samba
sudo: apt-get: command not found
改为:
sudo yum install samba
2 、命令执行到最后出现 Error downloading packages:
samba-4.8.3-4.el7.x86_64: [Errno 256] No more mirrors to try.
pytalloc-2.1.13-1.el7.x86_64: [Errno 256] No more mirrors to try.
samba-libs-4.8.3-4.el7.x86_64: [Errno 256] No more mirrors to try.
samba-common-tools-4.8.3-4.el7.x86_64: [Errno 256] No more mirrors to try.
需要执行:
1.yum clean all
2.yum makecache
3.yum update 3 执行 yum makecache 出现如下错误 静态ip配置问题
网站快做完了,突然发现不知道为什么出现一个大问题:用户名密码输入错误也能登陆。这尼玛不是让我的ajax白做了吗?
经过仔细查找,发现xmlhttp.responseText 返回的是Html代码,然后在网上一通百度之后发现了原因,原来是我的Servlet中在response.getWriter().write(statusInfo);之前画蛇添足写了一个跳转语句。这里直接返回一个信息给ajax就可以了,跳转让js代码去跳转即可。
多了一句 request.getrequestdispatcher(“XXX.jsp”).forward(request,response);
原文地址:
https://blog.csdn.net/qq_36518259/article/details/78582081
package day05; public class Add{ public static void main(String[] args) { int a =0; int b=0; int c =a++; int d =++b; System.out.println(c); System.out.println(a); System.out.println(d); System.out.println(b); } 运行结果如下
a++和++a 都属于自增运算符,区别是对变量a的值进行自增的时机不同。
a++是先进行取值,后进行自增。++a是先进行自增,后进行取值;
一般采样速率fs等于符号速率Rb;
采样速率表示采样的快慢,现有N个采样点;
类似于路程(N)除以速度(fs)等于时间(Tb);
采样一个点所需时间Tb = N/fs;
即一个子载波持续时间为Tb = N/fs;
那么子载波间隔用频率表示为fc = 1/Tb = fs/N;
典型的有fs = 30.72MHz, N= 2048, fc = 15kHz。
转载于:https://www.cnblogs.com/achangchang/p/11048264.html
企业CA与独立CA的区别 ①企业CA:要求域环境,负责为域中的用户和计算机颁发证书;由于域用户在登录过程中已经进行了身份验证,因而域用户向企业CA申请证书时,证书会自动颁发,无需管理员操作。
②独立CA:不要求域环境,即可以为企业内网中的用户,也可以为互联网上的用户颁发证书;证书颁发必须要由管理员操作。
架设独立CA服务器 1、打开“服务器管理器”,点击“添加角色”
2、点击“下一步”
3、勾选“证书服务”,点击“下一步”
4、点击“下一步”
5、勾选“证书颁发机构web注册”,在添加角色向导中点击“添加所需的角色服务”
6、点击“下一步”
7、选择“独立”,点击“下一步”
8、选择“根”,点击“下一步”(其中,根CA是CA信任体系结构的最高层,它一般负责整个CA体系的管理,为下属的子CA签发并管理证书,而不直接为用户签发证书。根以下的各级CA都称为子CA,负责为本辖区的用户颁发和管理证书)
9、选择“新建私钥”,点击“下一步”,点击“下一步”
10、“公用名称”可以修改,点击“下一步”,点击“下一步”,点击“下一步”,点击“下一步”
11、根据自己的需求添加功能,点击“下一步”
12、点击“安装”,安装成功点击“关闭”
13、在[开始]——管理工具——打开“证书颁发机构”,在此可以进行证书的管理
14、用浏览器访问证书(## 格式:主机IP地址/certsrv)
若访问时出现此警示框,点击“添加”即可
opencv实现人脸检测** 小白学习图像处理,最近日常小练习,欢迎各位光临指导
1.静态图像中的人脸检测 def StaticDetect(filename):
# 创建一个级联分类器 加载一个 .xml 分类器文件. 它既可以是Haar特征也可以是LBP特征的分类器.
# face_cascade = cv2.CascadeClassifier(‘d:/haarcascade_frontalface_alt_tree.xml’)
model_file = ‘D:/Software/python/Lib/site-packages/cv2/data/haarcascade_frontalface_default.xml’
import os
if not os.path.exists(model_file):
print(‘not good’)
return
face_cascade = cv2.CascadeClassifier(‘D:/Software/python/Lib/site-packages/cv2/data/haarcascade_frontalface_default.xml’)
# 加载图像 img = cv2.imread(filename) # 转换为灰度图 gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 进行人脸检测,传入scaleFactor,minNegihbors,分别表示人脸检测过程中每次迭代时图像的压缩率以及 # 每个人脸矩形保留近似数目的最小值 # 返回人脸矩形数组 # faces = face_cascade.detectMultiScale(gray_img,2,5) faces = face_cascade.detectMultiScale(gray_img, scaleFactor=1.04, minNeighbors=5, minSize=(5, 5) ) for (x, y, w, h) in faces: # 在原图像上绘制矩形 img = cv2.
转载:使用Navicat查看数据表的ER关系图
plsql:
动手学深度学习 - 5.2. 填充和步幅 动手学深度学习 - Dive into Deep Learning
Aston Zhang, Zachary C. Lipton, Mu Li, and Alexander J. Smola
https://zh.d2l.ai/
5.2. 填充和步幅 在上一节的例子里,我们使用高和宽为 3 的输入与高和宽为 2 的卷积核得到高和宽为 2 的输出。一般来说,假设输入形状是 n h × n w n_h\times n_w nh×nw,卷积核窗口形状是 k h × k w k_h\times k_w kh×kw,那么输出形状将会是
( n h − k h + 1 ) × ( n w − k w + 1 ) . (n_h-k_h+1) \times (n_w-k_w+1).
由于在Python numpy库中没有直接对Matrix求RREF的方法,度娘了好久发现在另一个科学计算包sympy中可以利用A.rref()的方法对Matrix直接求RREF,但是有另一个问题,大家一般常用的是numpy,而sympy和numpy使用的是不同的数据类型,numpy中声明Matrix一般使用array(),sympy中声明Matrix则使用Matrix()方法,所以需要先将array()类型的矩阵转换为Matrix()类型求RREF,然后再转回array()类型。
1. sympy Matrix类型与numpy array类型的相互转换 array -> Matrix 直接使用sympy Matrix(np.array())方法构造一个matrix
Matrix -> array 查看了sympy官方文档其提供了两种Matrix convert to array的方法:
(1) sympy.matrices.dense.matrix2numpy(m, dtyp=<'class object'>)
- 其对于sympy Matrix类型返回一个numpy array类型
这里要注意的是不能忘了数据转换的对象类型type,如果没有指定类型那么会出现“未定义数据类型”的提示
(2) tolist()
- 其对于sympy Matrix类型返回一个嵌套的python列表
使用这种方法需要注意的是,若不加处理直接使用tolist()方法,其返回的数据类似于“列表的索引”,在Spyder中查看数据是这样的:
所以需要对数据进行处理,即通过np.array(Matrix.tolist()).astype()操作将其转换为对应的numpy类型
2. 使用sympy库计算Matrix的最简行阶梯矩阵 sympy库中提供了rref()方法将Matrix通过初等行变换,转化为简化行阶梯矩阵。rref()将返回的是一个元组,包括两个值,第一个是简化行阶梯矩阵,第二个是主元位置的列表。注意:返回的元组第一个类型是Matrix,第二个是list
所以对于numpy array()的matrix求最简行阶梯矩阵,先转为symbol Matrix计算rref,再转回numpy类型
代码实现 # Python 3.7 from sympy import Matrix from sympy.matrices import dense # Matrix convert to array A_mat = Matrix([[1, 2, 1, 1], [2, 1, -2, -2], [1, -1, -4, 3]]) A_arr1 = np.
作为一个硬件从业人员,虽然不是从事物理网行业的,但是多少得了解一些,以下是笔者最近学习Zigbee的笔记,包含了Zigbee基本知识,正确的学习方法。
Zigbee无线传感网络
先搞清楚IEEE802.15.4协议。
这个协议必须搞清楚,搞不定这个协议,Zigbee永远吃不透。其实学习这个很简单,如果学过TCP/ip的话,大家知道,我们要去掌握整个tcp/ip核心的话,我们要掌握以太网底层的一些协议,比如我们做驱动,我们做开发,如果说不懂的话,是没有办法做项目的,更直白一点,没法在工作中去解决实际的问题。对于老板来说,老板招人过来,就是要解决问题的,如果没有解决问题的能力,那在职场中是没有竞争力的。
ZIGBEE是什么?
在传统的无线网络当中,大家耳熟能详的就是两种,蓝牙和wifi。在物联网的世界,也存在物与物之间存在信息沟通的桥梁,也是通过无线技术,最经典的就是ZIGBEE技术,还有ZWAVE技术,不过ZWAVE在中国还是用得很少的。
为什么要引入zigbee呢?
有了Zigbee之后,全球才有了一个物联网的概念,Zigbee号称我们商用的第一个无线传感网络。
到目前为止,无论是国内还是全球,Zigbee是商用最多的,Zigbee做出来的产品是很多的,在国内,最典型的Zigbee应用是在智能家居领域,目前在国内推出的只能家居,绝对是Zigbee,为什么呢?
zigbee出来比较早,大概是在03年,Zigbee整个协议的这个技术现在变得很成熟。真正可商用化的产品,一定会选一个成熟的技术方案。
Zigbee能够干什么?
Zigbee主要用于构建无线局域网,如果这个无线局域网用于传感器的数据收集和监控,这个网络就叫做无线传感器网络(WSN:Wirelss Sensor Network),是无线局域网的具体应用。
Zigbee是属于无线传感网络的一种。
图中Sink node叫做集中器,负责整个Zigbee网络的管理和接入的,同时还负责和外围交互,可以和PC,互联网进行连接。
单纯的一个Zigbee是没有实际的应用场景的,现在使用的各种的物联网终端,最起码有一个app,需要用来观看无线传感网络中的信息,需要保证这个Sink node接入到我们的物联网当中来。
Zigbee特点
低功耗:6个月-2年,为什么是一个比较大的范围呢?任何一个低功耗的传感网络,首先需要问工作方式是什么,比如多长时间获取一次数据,多长时间发送一次数据,才能得到具体的使用时间。
高可靠性:用tcp/ip来解释,在tcp/ip协议中,有两种经典协议,TCP和UDP,一个是面向连接的,一个是无连接的,一个是可靠传输的,一个是不可靠传输的。无线连接本身存在不可靠性,zigbee针对这个做了一些高可靠性的机制。
低成本:开源,免专利费
碰撞避免机制,交互确认的机制,保证可靠通信
低延时:设备搜索时延30ms,休眠激活时延典型值是15ms,活动设备信道接入时延为15ms
低数据量:Zigbee每个网络模块射频前端的数据传输为250kbps
网络容量大:Zigbee可以采用星形,树形,网形的结构组网,而且可以通过任一节点组成更大的网络结构,从理论上讲,其可连接的节点多达65535个,其实就是一个16bit的数。实际应用中并没有这么多,实际受限于硬件资源。所谓的硬件资源就是芯片的ram,flash,是否能够容纳这么多的节点,是否能够管理。
高保密性:Zigbee提供了基于循环冗余校验(CRC)的数据包完整性检验和鉴权的功能,加密算法采用AES-128,同时各个应用可以灵活确定其安全属性。----所有的无线传输,都是通过一个射频的物理通道,任何人都可以利用zigbee协议开放特性,通过射频芯片发送数据包。但是与互联网一样,我们访问网站的时候,为什么要用https,是因为安全机制,个人网络不希望被人攻击,这个时候需要考虑网络的健壮性,保密性。Zigbee采用AES-128,并需要硬件支持
全球的通用性和完好的开发性:由于Zigbee标准协议,因此不同厂家芯片利用Zigbee通信将是轻而易举的事情。如ti的方案,恩智浦的方案,只要都满足Zigbee,互相通信将不是问题。
Zigbee学习模式
单片机+Zigbee=学习模式
只花20%的实际学习单片机的外设,编程。要花80%的时间放在Zigbee协议栈。只有这样才能用Zigbee来做项目,但是很多书籍都是大篇介绍单片机的使用,各种外设的使用。
学Zigbee其实学的是网络编程。Zigbee的代码量其实是挺大的,不要一上来就分析代码,要明白整个协议的设计,才能明白代码,才能读懂代码。
抓包分析:如果没有抓包能力,传输的数据就没法知道是上面什么意思,当网络不通的时候就没法分析。如果掌握抓包能力,发的任何信息都能知道是上面意思,这样才能把Zigbee掌握透彻。
Zigbee联盟
Zigbee协议标准的一个协会。
Zigbee硬件平台
TI,Jennic,Silicon Labs
不同厂家都有自己硬件上的芯片,都有自己软件的协议栈。
Zigbee协议栈
Zigbee协议实现的代码库
Zigbee协议栈,有一个分层的概念。不管是软件还是硬件项目,达到一定规模之后,都要进行分层,不分层的话,项目的管理,可扩展性等等效率问题解决不了。
Zigbee分层
最下面是IEEE802.15.4是一个标准,它规定了协议的物理层和MAC层,再上面是Zigbee的网络层Zigbee NWK(network)和应用层。网络层和应用层又分很多模块,为什么呢?
首先网络分层以后,要有加密特性(Security),再往上是一个Zigbee应用支持的子层,在网络层和应用层之间又开辟了一个子层(Zigbee Application Support Subplayer(APS))这个层起到承上启下的作用。承上指的是给整个Zigbee应用的框架。
Zigbee会根据不同的场景(Application Object),比如智能家居,能源,工业等等不同的场景,有一个库的概念。
针对设备终端的管理,又有单独的一个层,Zigbee Device object。
学习Zigbee就是学些Zigbee层与层之间的实现,或者说掌握层与层之间的交互,只有把各个功能模块之间了解清楚,Zigbee才有可能吃透。
IEEE802.15.4协议
Zigbee学习第一个要搞明白的就是Zigbee的物理层和Mac层,为什么呢?我们学习单片机,其实就是和硬件打交道,Zigbee通讯也是建立在硬件的基础之上的,硬件基础指的就是射频,要搞清楚这个无线射频到底是怎么来通讯的。如果说底层搞不清的话,应用层也是很难理解,因为它很抽象。-----所以说要搞清楚802.15.4这个协议。
Zigbee是由Zigbee联盟所主导的标准,定义了网络层,安全层和应用层,以及各种应用的产品架构;而由IEEE所制定的802.15.4标准,则是定义了物理和MAC层。
Zigbee协议,Zibgee联盟和IEEE组织都参与制定。
Zigbee网络分层
下面是MAC层和PHY层,其实几个网络协议都差不多,只是底层的实现不同。
比如wifi,wifi为什么能跑TCP/IP协议,wifi的物理层和以太网的物理层是完全不同的,如果没有把MAC和物理层分层的话,wifi是没有办法很容易的跑TCP/IP协议的。有了分层,我们就可以把以太网协议移植到射频里面来。
物理层频带参数
三个频段,国内用得最多是2.4Ghz-2.4835Ghz,在2.4G划分了16个信道(信道11到信道26),信道与信道的带宽是5Mhz,信道与wifi信道有交叉(如果应用中信号通讯不稳定,可以看下使用的信道是否和wifi相同,被占用比较多)
868MHZ--美国
915MHZ--欧洲
把数字信号变成一个射频信号,涉及到调制,调整方式为FSK(频移键控),通过频率的变化来表示我们的0,1信号,把数字信号变为模拟信号。
物理帧格式
if(lists.size() < 1){ lists.add(s); }else{ for (SubmitAnswer sub : lists) { if(sub.getExamPaperId() == s.getExamPaperId()){ continue; }else{ lists.add(s); } } } 原因是因为在增强的for循环中不可以改变lists的大小
一:grep文本搜索
grep:强大的文本搜索工具(是一种“贪婪“的工具)
补充说明:
grep (global search regular expression(RE) and print out the
line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。用于过滤/搜索的特定字符。可使用正则表达式能多种命令配合使用,使用上十分灵活。
选项:
-a --text # 不要忽略二进制数据。 -A <显示行数> --after-context=<显示行数> # 除了显示符合范本样式的那一行之外,并显示该行之后的内容。 -b --byte-offset # 在显示符合范本样式的那一行之外,并显示该行之前的内容。 -B<显示行数> --before-context=<显示行数> # 除了显示符合样式的那一行之外,并显示该行之前的内容。 -c --count # 计算符合范本样式的列数。 -C<显示行数> --context=<显示行数>或-<显示行数> # 除了显示符合范本样式的那一列之外,并显示该列之前后的内容。 -d<进行动作> --directories=<动作> # 当指定要查找的是目录而非文件时,必须使用这项参数,否则grep命令将回报信息并停止动作。 -e<范本样式> --regexp=<范本样式> # 指定字符串作为查找文件内容的范本样式。 -E --extended-regexp # 将范本样式为延伸的普通表示法来使用,意味着使用能使用扩展正则表达式。 -f<范本文件> --file=<规则文件> # 指定范本文件,其内容有一个或多个范本样式,让grep查找符合范本条件的文件内容,格式为每一列的范本样式。 -F --fixed-regexp # 将范本样式视为固定字符串的列表。 -G --basic-regexp # 将范本样式视为普通的表示法来使用。 -h --no-filename # 在显示符合范本样式的那一列之前,不标示该列所属的文件名称。 -H --with-filename # 在显示符合范本样式的那一列之前,标示该列的文件名称。 -i --ignore-case # 忽略字符大小写的差别。 -l --file-with-matches # 列出文件内容符合指定的范本样式的文件名称。 -L --files-without-match # 列出文件内容不符合指定的范本样式的文件名称。 -n --line-number # 在显示符合范本样式的那一列之前,标示出该列的编号。 -q --quiet或--silent # 不显示任何信息。 -R/-r --recursive # 此参数的效果和指定“-d recurse”参数相同。 -s --no-messages # 不显示错误信息。 -v --revert-match # 反转查找。 -V --version # 显示版本信息。 -w --word-regexp # 只显示全字符合的列。 -x --line-regexp # 只显示全列符合的列。 -y # 此参数效果跟“-i”相同。 -o # 只输出文件中匹配到的部分。 规则表达式:
一、HTTPS简介
1.https简介
HTTPS其实是有两部分组成:HTTP + SSL / TLS,也就是在HTTP上又加了一层处理加密信息的模块。服务端和客户端的信息传输都会通过TLS进行加密,所以传输的数据都是加密后的数据
2.https协议原理
首先,客户端与服务器建立连接,各自生成私钥和公钥,是不同的。服务器返给客户端一个公钥,然后客户端拿着这个公钥把要搜索的东西加密,称之为密文,并连并自己的公钥一起返回给服务器,服务器拿着自己的私钥解密密文,然后把响应到的数据用客户端的公钥加密,返回给客户端,客户端拿着自己的私钥解密密文,把数据呈现出来
二、证书和私钥的生成
注意:一般生成的目录,应该放在nginx/conf/ssl目录
1.创建服务器证书密钥文件 server.key:
openssl genrsa -des3 -out server.key 1024
输入密码,确认密码,自己随便定义,但是要记住,后面会用到。
2.创建服务器证书的申请文件 server.csr
openssl req -new -key server.key -out server.csr
输出内容为:
Enter pass phrase for root.key: ← 输入前面创建的密码
Country Name (2 letter code) [AU]:CN ← 国家代号,中国输入CN
State or Province Name (full name) [Some-State]:BeiJing ← 省的全名,拼音
Locality Name (eg, city) []:BeiJing ← 市的全名,拼音
Organization Name (eg, company) [Internet Widgits Pty Ltd]:MyCompany Corp.
mongodb报错:E QUERY [thread1] SyntaxError: missing ; before statement @(shell):1:4 2019年03月27日 22:55:53 zhangpeterx 阅读数 544更多
个人分类: mongodb
晚上在安装mongodb,设置密码后,如果直接连接mongodb,不用密码,虽然可以连上,但是会无法切换到指定数据库:
-> # mongo MongoDB shell version v3.6.3 connecting to: mongodb://127.0.0.1:27017 MongoDB server version: 3.6.3 > 1+1 2 > ues admin 2019-03-27T22:42:21.838+0800 E QUERY [thread1] SyntaxError: missing ; before statement @(shell):1:4 123456789 解决方法是连接时加上密码:
-> # mongo --port 27017 -u "myUserAdmin" -p "abc123" --authenticationDatabase "admin" MongoDB shell version v3.6.3 connecting to: mongodb://127.0.0.1:27017/ MongoDB server version: 3.
// 试卷id int paperId = Integer.parseInt(request.getParameter("id")); request.setAttribute("paperId", paperId); 原因分析:是因为在request域中存放时候,不可以存放数字类型的数据。
修改如下即可:
request.setAttribute("paperId", paperId+"");
Mongodb日志切割
依据客户端查询来设计集合的片键及索引,最近几天突然需要查询历史数据进行分析,我们的有些集合count达到亿条以上,每个文档几百个字段。突如其来的查询分析,数据库非常的卡,尤其这几天刚刚加入一个新的分片。前天上午来看,发现主分片竟然奔溃了,至于为什么查询量大,数据库会奔溃,需要后续进行分析。
遇到问题第一反应是看日志文件,拿到notepad之后由于文件太大无法打开,只能采用重启,然后开始查询mongodb日志管理的文档。Mongodb官网提出可以对日志进行切换。这种切换方式为:对当前的mongod或者mongos的当前日志文件进行重命名,加入当前时间,然后打开一个新的log文件,告诉所有的log写入到新的文件中。(注意千万不要自己在没有停止mongod的时候,直接mv然后再重新生成一个新的文件)。在mongodb中切换日志文件可以采用几种方式:
1.logRotate
默认情况下,Mongodb是开启--logRotaterename选项的,在rename的情况下,可以在log文件中添加UTC时间戳的后缀。在admin数据库中,执行命令db.runCommand({logRotate:1})告诉数据库进行日志切换。会生成:log_rout.log.2017-02-22T02-10-09 类似的日志文件。这里有8个小时的时区问题。
2.syslog
利用syslog选项,使用系统的logrotate,这种情况下不再需要开启logpath选项,还没有进行深入的了解。
3.SIGUSR1
在linux下,可以使用kill –SIGUSR1(pid of mongod),对mongos及mongod都适用。
如果希望定时生成日志文件,而不是人工的每天执行命令。因为我们的当前的集群方式为:mongos+mongod(配置副本集)+mongod(分片),所以如果可以ps –aux|grep mongod可以得到数组,然后直接使用kill –SiGUSR1命令就可以了。编写完sh命令之后,无法识别-SIGUSR1。
选择第一种方式进入mongodb中,编写js脚本,然后sh命令调用这个js命令,指定一个linux的任务。Linux的任务分为当前用户任务,系统用户。最好选择crontab –e直接进行编辑,00 59 * * * /bin/sh mongo_log_mgr.sh,制定了一个定时的10点30分钟执行的sh脚本,但是没有执行。
是的,任务是已经启动,有执行的。单独执行该shell命令,没有问题。测试一个hello.sh命令好了,是的,加上绝对路径就ok了:任务改为:
0 59 ** * /bin/sh /root/shell_script/mongodb/mongo_log_mgr.sh
在sh中,mongo中有一个选项可以直接运行js文件,sh中命令如下:
/usr/local/bin/mongo -u XXX -p XXX--authenticationDatabase admin ip:27017/admin --quiet /root/ shell_script/mongodb/mongo_log.js 如果希望将日志文件分为若干个文件夹,以便于查找某一天的日志,先睡眠,因为日志的移动可能需要时间,然后根据当天的日期创建文件夹.
sleep 30m
CURRENT_MONTH=$(date +%Y-%m) CURRENT_DAY=$(date +%d) LAST_DATE=$(date -d last-day +%Y-%m-%d) #如果是第一天则创建一个新的文件夹 if [ $CURRENT_DAY = 01 ] then mkdir /mongodb/log/$CURRENT_MONTH LAST_MONTH=$(date -d last-month +%Y-%m) mkdir /mongodb/log/$LAST_MONTH/$LAST_DATE mv *.
一般模糊查询语句如下:
SELECT 字段 FROM 表 WHERE 某字段 Like 条件
其中关于条件,SQL提供了四种匹配模式:
1,% :表示任意0个或多个字符。可匹配任意类型和长度的字符,有些情况下若是中文,请使用两个百分号(%%)表示。
比如 SELECT * FROM [user] WHERE u_name LIKE '%三%'
将会把u_name为“张三”,“张猫三”、“三脚猫”,“唐三藏”等等有“三”的记录全找出来。
另外,如果需要找出u_name中既有“三”又有“猫”的记录,请使用and条件
SELECT * FROM [user] WHERE u_name LIKE '%三%' AND u_name LIKE '%猫%'
若使用 SELECT * FROM [user] WHERE u_name LIKE '%三%猫%'
虽然能搜索出“三脚猫”,但不能搜索出符合条件的“张猫三”。
2,_ : 表示任意单个字符。匹配单个任意字符,它常用来限制表达式的字符长度语句:
比如 SELECT * FROM [user] WHERE u_name LIKE '三'
只找出“唐三藏”这样u_name为三个字且中间一个字是“三”的;
再比如 SELECT * FROM [user] WHERE u_name LIKE '三__';
只找出“三脚猫”这样name为三个字且第一个字是“三”的;
3,[ ] :表示括号内所列字符中的一个(类似正则表达式)。指定一个字符、字符串或范围,要求所匹配对象为它们中的任一个。