arduino与openmv的智能物流小车 一、购买模块组件准备阶段 1、ArduinoMAGE2560+扩展板 使用这个当做主控板,加上扩展板已经满足了所有需求,主要是也很便宜,唯一不足的是就是扩展板装上的时候,扩展板的电源接口的引脚有时候会与MAGE2560 的数据接口碰上,导致板子短路,当初因为这个换了好几块板子。
2、openmv openmv主要是用来扫码和识别物料颜色,我用的型号是openmv4 H7,识别很灵敏,但是换不同场景识别物料的时候一定要记得调节物料颜色阈值,不然有时候会识别不到。
3、机械臂+手爪 控制机械臂舵机用的是*“16路pwm Servo舵机驱动板”*。这个很好用,可以最多同时控制16个舵机。
制作机械臂和手爪的时候,用了三个双轴舵机和三个单轴舵机,制作之前一定要想好机械臂的运动过程 和小车的模块组件有没有冲突,我们当初因为没有考虑周到,打坏了好几个数码管。
4、电机驱动 电机使用的是L298N逻辑驱动模块,可能是我们买的那个驱动模块的问题,电机启动时有时间差,四个电机不是同时启动。但是控制信号的逻辑都是相通的。
5、麦克纳姆轮 麦克纳姆轮很好的解决因为转圈的问题,产生了小车的方向偏差。所以使小车处于一个方向就可以跑完全程。注意:买轮子时一定要注意和电机是否有匹配的联轴器,否则不合适的话轮子走路时会形成内八字建议买的时候买成套的,当时我们的电机找了好多家就是没有配套的联轴器,然后自己3d打印的联轴器小车走路就是内八字。气急败坏下,直接重新买了一套。
6、循迹模块 循迹模块一般使用的就是红外循迹和灰度循迹
如果比赛对于环境要求很高的话,使用红外循迹的话因为灯光等场地因素会非常的不稳定,所以选择的时候要选择带光电的灰度循迹模块。非常好使。
7、电池 电池刚开始选择的是普通的锂电池,发现东西一多了之后根本带不动,在同学的建议下买了航模电池,不得不说航模电池的是真的给力。
8、其他 TM1637的六位数码管
可调节变压器模块
先写到这,之后想到会有补充
过几天还会说一些相关模块代码
稳定和不稳定排序详解 参考:https://www.jianshu.com/p/7c03e5eb143c
稳定排序有:插入排序、冒泡排序、归并排序、基数排序
不稳定排序有:选择排序、快速排序、希尔排序、堆排序
稳定排序 插入排序:
在一个有序的序列中插入一个数,使插入后的序列保持有序。
因为插入的过程中都是从后向前进行查找,遇到小于等于(或大于等于)的数停止寻找,进行插入操作。
不改变排序前后相等数值的相对顺序,故使稳定的排序算法。
冒泡排序:
冒泡故名思义,数值小的向上飘,数值大的向下沉,向上飘的数遇到的小于等于当前数的值停止,向下沉的数遇到大于等于当前数的数停止,
类似于对于向上飘的数有个排序之前在其前面数值相等限制了其向上飘的脚步,原先在俺之下,排序后也在俺之下,向下沉也是同理。故也是稳定的排序算法。
归并排序:
将一段序列分为若干个小序列进行排序,排序后的小序列进行合并得到最后的排序结果。
主要运用了分治的思想。
分成的前后若干个小序列在最后进行合并时本身就包含了前后位置信息,在合并时不改变相同值在排序前后的相对顺序,故归并排序也是稳定排序。 基数排序:
按从低到高的相应位的值进行排序,也是稳定排序算法。 不稳定排序算法 非稳定排序算法包括:选择排序、快速排序、希尔排序、堆排序*
选择排序:
主要思想是分别找出当前遍历元素中的最小值与相应位置的数进行交换,
第一遍寻找元素的从第一个元素起的最小值(或最大值)和第一个元素进行交换,第二趟寻找从第二个元素起最小的(或最大的)元素与第二个元素进行交换,以此类推。
例子如下:[4,4’,2] 排序后 [2,4’,4]
快速排序
快速排序是指通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序。整个排序过程可以递归进行,以此达到整个数据变成有序序列。 这里可以使用例子进行记忆:以5作为基准,从最右元素找到小于5的元素3`
然后将5和3`进行互换, 就会发现3·在前面的情况,即出现了不稳定的情况。
[5,3,3,4,3’,8,7] 排序后[3’,3,3,4,5,8,7]
希尔排序
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止 一次插入排序是稳定的,多次插入排序不是稳定的。
[3,3`,2,4]
最终的结果为:
[2,3`,3,4]
其中3和3`的顺序发生变化。
堆排序
堆排序(英语:Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
比如:3 27 36 27,
如果堆顶3先输出,则,第三层的27(最后一个27)跑到堆顶,然后堆稳定,继续输出堆顶,是刚才那个27,这样说明后面的27先于第二个位置的27输出,不稳定。
Linux odoo开发环境配置
安装postgresql9.6
第1步:添加RPM源(通过官网获取下载地址)
yum install https://download.postgresql.org/pub/repos/yum/9.6/redhat/rhel-7-x86_64/pgdg-centos96-9.6-3.noarch.rpm
PS:如果安装过程出现错误,或提示已加载,但是无法提示没有相关依赖包,则可以先清除yum缓存
清理yum缓存:
yum clean 的参数有headers, packages, metadata, dbcache, plugins, expire-cache, rpmdb, all 第2步:安装PostgreSQL 9.6服务端及相关第三方扩展
yum install postgresql96-server postgresql96-contrib postgresql96-devel
第3步:检查是否安装成功
rpm -aq| grep postgres
第4步:创建数据库存放路径位置
mkdir -p /data/pg/data #存放数据库的文件夹
chown -R postgres:postgres /data/pg #为新创建的pg文件夹分配数据库服务的操作权限
chown -R postgres:postgres /data/pg/data #为存放数据库的文件夹分配权限
chmod 750 /data/pg/data
第5步:设置环境变量
编辑/etc/profile文件
nano /etc/profile
在末尾添加如下的信息配置:
PGDATA=/data/pg/data
PGHOST=127.0.0.1
PGDATABASE=postgres
PGUSER=postgres
PGPORT=5432
PATH=/usr/pgsql-9.6/bin:$PATH
export PATH
export PGDATA PGHOST PGDATABASE PGUSER PGPORT
export TMOUT=1000
很多用户在使用电脑过程中,习惯让桌面上的图标能随意按照自己的喜好摆放。
但如果电脑桌面布局被锁定了,就会无法在桌面上随意放置我们的图标。
这时该怎么去设置解除桌面布局的锁定状态呢?今天我们就来给大家分享些解决方法。
首先,右击桌面空白处,将“查看”中的“自动排列图标”取消勾选。
通常这时候桌面的锁定状态就解除了。
但如果还没成功解除,那么进入“我的电脑”,选择“系统属性”。
再选择进入“高级系统设置”。
在高级页中选择性能中的“设置”。
在弹出的性能选项页中下拉找到并勾选上“在桌面上为图标标签使用阴影”即可。
我们的电脑桌面锁定状态就顺利被解决啦。
如果此时发现桌面图标的大小变了,还可以使用电脑医生进行快速修复。
首先,我们的电脑需装有金山毒霸软件。
若还未安装可前往官网下载,或直接点击下方图片即可快速下载安装。
↓ 点击图片 立即下载 ↓
打开金山毒霸,点击打开右下方的百宝箱。
选择常用工具中的“电脑医生”,点击打开。
在搜索框中输入“电脑图标大小”,点击搜索方案。
在电脑医生提供的解决方案中选择最符合我们情况的一个。
点击立即修复,若出现弹窗提示点击确认即可。
最后电脑医生自动修复结束,点击完成。
以上就是解决电脑桌面布局被锁定不能移动图标的方法了。
最后,如果这篇文章对你有所帮助,或者今后想要学习更多有用有趣的电脑知识或操作技巧,欢迎持续关注我们的官网资讯。
若使用金山毒霸过程中遇到其他问题,欢迎联系我们。
文章目录 写在前面系统前置知识ByteTalk架构设计图ByteTalk架构 —— nginx反向代理负载均衡nginx 反向代理的配置 ByteTalk架构 —— 服务器群(服务单元)ByteTalk 服务单元 —— 抽象服务节点:ProxyServiceByteTalk 抽象服务节点 —— 聊天处理服务器:ChatServerByteTalk 业务服务单元 —— 以登录、注册节点:UserService为例 ByteTalk 架构缺陷参考文献 作者:shenmingik
邮箱:2107810343@qq.com
时间:2021/5/5 12:04
开发环境:Ubuntu VS Code
编译器:g++
编译工具:CMake
数据库:MySQL Redis
注册中心:ZooKeeper
序列化格式:Protobuf
编程语言:C++
源码链接:GitHub
写在前面 针对春招各个大厂的面试官对我春招项目:基于muduo网络库的集群聊天系统 提出的问题以及建议,对原来的集群项目进行了以下改进:
由简单nginx集群改为分布式集群序列化格式由 json 改为protobuf引入自己写的RPC框架引入配置注册中心 zookeeper引入数据库连接池增加新业务 整个项目从构思到架构设计再到服务端研发总共花费了一个月左右的事件,期间遇到过大大小小的问题,也都总结了下来:杂记——在开发ByteTalk中遇到的困难以及解决
系统前置知识 有些还没整理完,先放上整理过的知识:
zookeeper 系列:
zookeeper入门——基础知识 protobuf 系列:
protobuf入门 RPC 系列:
一个基于 protobuf 和 zookeeper 的RPC框架 数据库系列:
mysql使用手册——基础篇自己实现一个数据库连接池redis 的机制 Nginx系列:
Ubuntu 安装Nginx及简单配置 ByteTalk架构设计图 图可能有点模糊,接下来我会把每个图放大讲解。
ByteTalk架构 —— nginx反向代理负载均衡 整个系统在客户端和实际服务的服务器中添加了一个反向代理服务器 —— nginx,同时利用nginx的负载均衡来达到降低网络和服务器的负载的目的。但是,这个也有缺陷,在本文的末尾会讲到。
文章目录 情况简述解决方式1. wget随便获取一个网页 得到认证界面的IP地址2. 通过ssh进行端口映射 从本地打开对应网页3. 通过curl命令进行登录3.1 浏览器打开3.2 在终端输入命令 情况简述 连接了学校的Linux服务器,服务器接入了校园网,但由于校园网需要WEB认证,因此无法链接网络。
解决方式 1. wget随便获取一个网页 得到认证界面的IP地址 [root@localhost sht]# wget www.baidu.com --2021-05-05 13:36:46-- http://www.baidu.com/ 正在解析主机 www.baidu.com (www.baidu.com)... 36.152.44.96, 36.152.44.95 正在连接 www.baidu.com (www.baidu.com)|36.152.44.96|:80... 已连接。 实际看起来不是这样,解析主机后会得到一个IP地址,如果你获取的不是所需要的网址的话,那这个网址大概率就是登录界面。
2. 通过ssh进行端口映射 从本地打开对应网页 ssh -L 映射到的端口号(我用的18097):上一步获取到的IP地址:上一步获取到的端口号(一般80) 服务器用户名@服务器地址 3. 通过curl命令进行登录 3.1 浏览器打开 浏览器打开
127.0.0.1:映射到的端口号 按F12 ,在开发者选项中,找到network部分,输入好账号密码,登录。
登录后应该是不成功的(有的方式可能成功,但是我们学校的验证方式包括了本机的IP地址,因此不可以),network中第一个请求(也就是最大的),在上面,右键,选如图所示的。
3.2 在终端输入命令 把刚刚复制的话复制在终端里,可以看到,上面是有IP地址的,这个地址记得改成服务器的地址(就是你连他的时候用的地址),能不能用就看对应的web认证的认证方式了,一般改这段参数就可以
1.版本要求 版本: >PCL1.3
2.简介 欧式聚类是点云聚类的一种重要方法,利用点云中点与点之间的欧式距离进行聚类,当点与点之间的欧式距离小于设定的阈值则视为一类。欧式聚类是车辆前方障碍物检测的重要方法。
3.数据 本例中使用的点云数据(test.pcd)请见百度网盘分享。
链接:https://pan.baidu.com/s/1io3q_ESUbhdGT2vr6-NuVA
提取码:ias2
4.代码 #include <pcl/point_types.h> #include <pcl/io/pcd_io.h> #include <pcl/kdtree/kdtree.h> #include <pcl/segmentation/extract_clusters.h> #include <pcl/visualization/cloud_viewer.h> int main(int argc, char** argv) { // 读取测试点云 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); pcl::PCDReader reader; reader.read("test.pcd", *cloud); // 创建KdTreea对象用于点云搜索 pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>); tree->setInputCloud(cloud); std::vector<pcl::PointIndices> cluster_indices; //创建索引对象向量,用于存储不同聚类结果的点云索引 pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec; //创建欧式聚类对象 ec.setClusterTolerance(0.13); // 设置距离阈值为13cm。点与点之间小于这个距离阈值视为一类 ec.setMinClusterSize(200); //设置聚类最少点数 ec.setMaxClusterSize(5000); //设置聚类最大点数 ec.setSearchMethod(tree); //输入点云搜索方法 ec.setInputCloud(cloud); ec.extract(cluster_indices); //开始聚类 //将聚类结果合成一幅点云,方便后面对比显示 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster(new pcl::PointCloud<pcl::PointXYZ>); for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin(); it !
centos 6.3上新建了vsftp ,用于文件下载使用 。/var/ftp/pub可以匿名登陆下载 。如果想要上传则需要使用密码验证 。
登陆使用的账号是ftpclient ,路径在/home/ftpclient 。在/var/ftp/pub下新建一个软链接:
cd /var/ftp/pub
ln -s /home/ftpclient client
但用ftp客户端匿名连上去后,进入client目录报550错误,无权限访问。
ftp> cd pub
250 Directory successfully changed.
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
lrwxrwxrwx 1 0 0 15 Sep 08 03:30 client -> /home/ftpclient
226 Directory send OK.
ftp> cd client
550 Failed to change directory.
无论怎么修改/home/ftpclient的权限都是一样。后面在网上找到,可以用mount –bind的方式规避权限问题。操作步骤如下:cd /var/ftp/pub
mkdir client
mount --bind /home/ftpclient client
题目描述:
老师给了小乐乐一个正整数序列,要求小乐乐把这个序列去重后按从小到大排序。但是老师给出的序列太长了,小乐乐没办法耐心的去重并排序,请你帮助他。
输入描述:
第一行包含一个正整数n,表示老师给出的序列有n个数。接下来有n行,每行一个正整数k,为序列中每一个元素的值。(1 ≤ n ≤ 105,1 ≤ k ≤ n)
输出描述:
输出一行,为去重排序后的序列,每个数后面有一个空格。
示例1
输入
4
2
2
1
1
输出
1 2
示例2
输入
5
5
4
3
2
1
输出
1 2 3 4 5
import java.util.Scanner; import java.util.Arrays; public class Main{ public static void main(String [] args){ Scanner in =new Scanner(System.in); int n=in.nextInt(); int [] arr=new int [n]; for(int i=0;i<n;i++){ arr[i]=in.nextInt(); } //数组元素去重 boolean isrepeat;//是否有重复元素 int [] temparr=new int [n]; int t=0;//用来统计无重复的元素 for(int i=0;i<n;i++){ isrepeat=false; for(int j=i+1;j<n;j++){ if(arr[i]==arr[j]){ isrepeat=true;//表示有重复元素 break; } } if(isrepeat==false){//没有重复元素 temparr[t]=arr[i]; t++; } } //数组拷贝 int [] newarr=new int [t]; System.
前言 这篇blog是关于在《一个64位操作系统的设计与实现》中,第4.8节创建init进程产生的异常。会出现什么异常?如何解决?是这篇blog的重点。
涉及异常种类 助记符描述触发源#GP(general protection)通用保护异常任何内存引用和保护检测#PF(page fault)页错误任何内存引用#UD(undefined opcode)无效/未定义的机器码UD2指令或保留机器码 正文 一、首先出现的是,#GP异常。 先说结论:这个问题是示例代码的问题。
#GP异常通常会打印出出现异常的RIP地址,通过objdump -D system反汇编源代码,根据RIP地址定位到__switch_to函数的retq指令,当__switch_to函数执行完毕后,会跳转到kernel_thread_func模块,通过打印该模块的函数地址,发现地址异常,示例代码是这样写的:
extern void kernel_thread_func(void); __asm__ ( "kernel_thread_func: \n\t" " popq %r15 \n\t" " popq %r14 \n\t" " popq %r13 \n\t" // ... ); 猜想,这样定义函数时,函数地址的位置并不是我们想要的'正确地址',所以我通过另外一种方式定义该函数:
extern void kernel_thread_func(void); void kernel_thread_func() { __asm__ ( " popq %r15 \n\t" " popq %r14 \n\t" " popq %r13 \n\t" // ... ); } 成功解决该问题,但随之出现另外一个问题 #PF异常 。
二、#PF异常 先说结论:作者在书籍中遗漏了一些注释代码,即有一小段代码需要注释,但是在书籍中未提到,源码中该段代码被注释,这段代码是:
// ~ kernel/memory.
TCP的定义
TCP全称为Transmission Control Protocol(传输控制协议),是一种面向连接的、可靠的、基于字节流的传输层通信协议。TCP是为了在不可靠的互联网络上提供可靠的端到端字节流而专门设计的一个传输协议。
TCP的三次握手和四次挥手,可以说是老生常谈的经典问题了,通常也作为各大公司常见的面试考题,具有一定的水平区分度。看似简单的面试问题。如果你的回答不符合面试官期待的水准,有可能就直接凉凉了。
本文会围绕,从三次握手和四次挥手相关的一系列核心问题,分享如何更准确回答和应对常见的面试问题,以后面对再刁钻的面试官,你都可以随意地跟他扯皮了
优雅回答三次握手 三次握手:服务端新建套接字,绑定地址信息后开始监听,进入LISTEN状态。客户端新建套接字绑定地址信息后调用connect,发送连接请求SYN,并进入SYN_SENT状态,等待服务器的确认。服务端一旦监听到连接请求,就会将连接放入内核等待队列中,并向客户端发送SYN和确认报文段ACK,进入SYN_RECD状态。客户端收到SYN+ACK报文后向服务端发送确认报文段ACK,并进入ESTABLISHED状态,开始读写数据。服务端一旦收到客户端的确认报文,就进入ESTABLISHED状态,就可以进行读写数据了
为什么握手是三次,而不是两次或者四次? 答:两次不安全,四次没必要。tcp通信需要确保双方都具有数据收发的能力,得到ACK响应则认为对方具有数据收发的能力,因此双方都要发送SYN确保对方具有通信的能力。第一次握手是客户端发送SYN,服务端接收,服务端得出客户端的发送能力和服务端的接收能力都正常;第二次握手是服务端发送SYN+ACK,客户端接收,客户端得出客户端发送接收能力正常,服务端发送接收能力也都正常,但是此时服务器并不能确认客户端的接收能力是否正常;第三次握手客户端发送ACK,服务器接收,服务端才能得出客户端发送接收能力正常,服务端自己发送接收能力也都正常。
三次握手可以携带数据吗? 答:第一次、第二次握手不可以携带数据,而第三次握手是可以携带数据的。假设第一次可以携带数据,如果有人恶意攻击服务器,每次都在第一次握手中的SYN报文放入大量数据,重复发送大量SYN报文,此时服务器会花费大量内存空间来缓冲这些报文,服务器就更容易被攻击了
tcp三次握手失败,服务端会如何处理? 答:握手失败的原因有两种,第一种是服务端没有收到SYN,则什么都不做;第二种是服务端回复了SYN+ACK后,长时间没有收到ACK响应,则超时后就会发送RST重置连接报文,释放资源
ISN代表什么?意义何在?ISN是固定不变的吗?ISN为何要动态随机 答:ISN全称是Initial Sequence Number,是TCP发送方的字节数据编号的原点,告诉对方我要开始发送数据的初始化序列号。ISN如果是固定的,攻击者很容易猜出后序的确认号,为了安全起见,避免被第三方猜到从而发送伪造的RST报文,因此ISN是动态生成的
什么是半连接队列 答:服务器第一次收到客户端的SYN之后,就会处于SYN_RECD状态,此时双方还没有完全建立连接。服务器会把这种状态下的请求连接放在一个队列里,我们把这种队列称之为半连接队列。当然还有一个全连接队列,就是已经完成三次握手,建立起来连接的就会放在全连接队列中,如果队列满了就有可能出现丢包现象
优雅回答四次挥手 四次挥手:客户端主动调用close时,向服务端发送结束报文段FIN报,同时进入FIN_WAIT1状态;服务器会收到结束报文段FIN报,服务器返回确认报文段ACK并进入CLOSE_WAIT状态,此时如果服务端有数据要发送的话,客户端依然需要接收。客户端收到服务器对结束报文段的确认,就会进入到FIN_WAIT2状态,开始等待服务器的结束报文段;服务器端数据发送完毕后,当服务器真正调用close关闭连接时,会向客户端发送结束报文段FIN包,此时服务器进入LAST_ACK状态,等待最后一个ACK的带来;客户端收到服务器发来的结束报文段, 进入TIME_WAIT, 并发出送确认报文段ACK;服务器收到了对结束报文段确认的ACK,进入CLOSED状态,断开连接。而客户端要等待2MSL的时间,才会进入到CLOSED状态
为什么握手是三次,而挥手时需要四次呢? 答:其实在TCP握手的时候,接收端将SYN包和ACK确认包合并到一个包中发送的,所以减少了一次包的发送。对于四次挥手,由于TCP是全双工通信,主动关闭方发送FIN请求不代表完全断开连接,只能表示主动关闭方不再发送数据了。而接收方可能还要发送数据,就不能立即关闭服务器端到客户端的数据通道,所以就不能将服务端的FIN包和对客户端的ACK包合并发送,只能先确认ACK,等服务器无需发送数据时在发送FIN包,所以四次挥手时需要四次数据包的交互
TIME_WAIT状态有什么作用,为什么主动关闭方没有直接进入CLOSED状态释放资源? 答:如果主动关闭方进入CLOSED状态后,被动关闭方发送FIN包后没有得到ACK确认,超时后就会重传一个FIN包。如果客户端没有TIME_WAIT状态而直接进入CLOSED状态释放资源,下次启动新的客户端就可能使用了与之前客户端相同的地址信息,有两个危害,第一种是这个刚启动的新的客户端绑定地址成功时,就会收到了一个重传的FIN包,对新连接就会造成影响。第二种是如果该新客户端向相同的服务端发送SYN连接请求,但是此时服务端处于LAST_ACK状态,要求收到的是ACK而不是SYN,因此就会发送RST重新建立请求。
为什么TIME_WAIT状态需要经过2MSL才能进入CLOASE状态? 答:MSL指的是报文在网络中最大生存时间。在客户端发送对服务端的FIN确认包ACK后,这个ACK包有可能到达不了,服务器端如果接收不到ACK包就会重新发送FIN包。所以客户端发送ACK后需要留出2MSL时间(ACK到达服务器器+服务器发送FIN重传包,一来一回)等待确认服务器端缺失收到了ACK包。也就是说客户端如果等待2MSL时间也没收到服务器端重传的FIN包,则就可以确认服务器已经收到客户端发送的ACK包
一台主机上出现大量的TIME_WAIT是什么原因?应该如何处理? 答:TIME_WAIT是主动关闭方出现的,一台主机出现大量的TIME_WAIT证明这台主机上发起大量的主动关闭连接。常见于一些爬虫服务器。这时候我们应该调整TIME_WAIT的等待时间,或者开启套接字地址重用选项
一台主机上出现大量的CLOSE_WAIT是什么原因?应该如何处理? 答:CLOSE_WAIT是被动关闭方收到FIN请求进行回复之后的状态,等待上层程序进一步处理,若出现大量CLOSE_WAIT,有可能是被动关闭方主机程序中忘了最后一步断开连接后调用close释放资源。这是一个 BUG.,只需要加上对应的 close 即可解决问题
tcp连接管理中的保活机制 答:tcp通信中,若两端长时间没有数据往来,则这时候每隔一段时间,服务端会向客户端发送一个保活探测数据报,要求客户端进行回复。若连续多次没有收到响应,就认为连接已经断开。长时间默认为7200s,每隔一段时间默认为75s,连续多次无响应默认为9次。这些数据都可以在套接字中修改,接口:Setsockopt
磁盘:机械硬盘(HHD)、固态硬盘(SSD)、混合硬盘(HDD,机械硬盘发展而来)。
机械硬盘的基本参数:
容量:有2T,1T,500G等;
转速:5400转/分,7200,10000,15000
平均访问时间:寻道时间+等待时间
传输速率:分为内部传输速率和外部传输速率,内部传输速率:未使用缓冲区时的速率,主要依赖转盘的速度。外部传输速率:突发数据传输率;
缓存:每块硬盘有一个缓存,将内存常用的数据放置缓存中,以供内存快速读取数据;
机械硬盘接口种类:
IDE:目前来说已不常用
SATA/SATAⅡ/SATAⅢ:常用于线上并发少的、尽量少用于数据库等操作上;
SCSI:用于中高端服务器;
SAS:可用于线上高并发及重要业务上的服务器上;
机械硬盘物理结构:
磁头:最昂贵的部件,读写数据;
盘片:存储数据;
主轴马达:转动磁盘;
磁头臂
永磁铁
盘片上的概念介绍:
磁头数head:每个盘片有上下两面,对应2个磁头;
磁道数track:磁道是从盘片外圈0磁道,1磁道...靠近主轴的同心圆是停靠磁头的位置;
柱面cylinder:相同半径的磁道组成了柱面,同磁道数量
扇区sector数:每个磁道被切割成扇形区域,每条磁道上的扇区数量相等(靠近0磁道的扇区面积大,密度小,靠近主轴的扇区面积小,密度大),每个扇区容量为512B
圆盘数:盘片数量
那么每块硬盘容量可用 磁头数*柱面数(磁道数)*扇区数*512B 来计算
文章目录 问题描述回溯算法的回顾使用知识回顾去解决问题定义问题的解空间确定易于搜索的解空间结构从根节点出发以深度优先的方式搜索空间树 实现代码 问题描述 题目描述:
有4个物品,其重量分别是{2, 3, 4, 5},价值分别为{3, 4, 5, 6},背包的容量为8。如何装才能价值最大,最大价值为多少?
输入格式:
第一行:是测试数据。
接下来对于每组测试数据,第一行是物品数量和背包最大承重,第二行是每个物品的价值,第三行是每个物品的重量。
输出格式:
一个整数,为最大价值总和是多少。
输入样例:
4 8 3 4 5 6 2 3 4 5 输出样例:
10 回溯算法的回顾 概述:回溯算法是一种通用的解题法,有较广的适用性基本步骤: 定义问题的解空间,解空间必须包括问题的最优解,一般情况下要列出所有的解确定易于搜索的解空间结构:常用的有两种,子集树(零一背包问题)和排列树(货郎问题)
* 子集树:从n个元素的集合S中找出满足某种性质的子集时
* 排列树:从n个元素的集合S中找出满足某种性质的排列时从根节点出发,以深度优先的方式去搜索解空间树确定剪枝函数,两种策略:约束函数和限界函数 使用知识回顾去解决问题 定义问题的解空间 解空间必须包含的问题的最优解的一般情况下,都是列出所有的解
确定易于搜索的解空间结构 定义问题的解空间,每一个物品有两种状态,放或者不放,形成对应的树形结构如图。 单个物体
多个物体
因为每一个物体只有放或者不放两种状态,就是一个二叉树,这里只列了三层,实际上有四层,每一个结点的值是当前物体的价值。其实,我知道表示成了二叉树,但是并不知道如何使用代码去实现。使用二叉树的数据结构吗?链表还是数组。 从根节点出发以深度优先的方式搜索空间树 从根节点出发以深度优先的方式搜索解空间树。算法搜索至空间树的任意一点时,先判断该点是否包含问题的解。判断依据:
* 肯定不包含解,即重量超过背包的容量,则跳过对该节点为根的子树的搜索,逐层向祖先结点回溯
* 肯定包含解,即重量没有超过背包的容量,则继续按照深度优先搜索的策略进行搜索。
实现代码 #include<iostream> #include<math.h> using namespace std; //用于记录是否存放当前地物体 int inOut[4]; //保存最多的价值 int value; //定义背包的总共的重量的 int bagVolume = 9; /* 描述:背包问题的约束条件,当传入对应的序号,就去判定是否要放对应的物品 参数:放入包中物体的序号 返回:当前物体总重量和背包容量的关系 true:表示没有超重 false:表示超重 原理:判定当前的物品的总重量,是不是小于物体的实际重量 */ bool bagConstraint(int m, int weight[]) { //一直遍历m层之前的所有物体,求出其对应的重量 int allweight = 0; for (int i = 0; i <= m; ++i) { //计算出总共的重量的 allweight += inOut[i] * weight[i]; } //比较当前的物体总重量和背包的总重量关系 return allweight <= bagVolume; } /* 描述:深度优先搜索的函数,递归函数 参数:m:是要装入背包的物品的数量 weight:是背包中各个物品的重量 value:是背包中各个物品的价值 返回:最终返回的是最大的价值 问题: */ void bagProblem(int m, int weight[], int valueAll[]) { //首先确定终止条件,那就比较最大值 if (m == 4) { int sum = 0; for (int i = 0; i < m; ++i) { sum += valueAll[i] * inOut[i]; } //比较最大值 if (sum > value) { value = sum; } } else { //没有到达终止条件,继续向下进行递归 for (int i = 0; i < 2; ++i) { inOut[m] = i; //判定是否满足对应约束条件 if (bagConstraint(m, weight)) { //满足约束条件,继续向下进行递归的 bagProblem(m + 1, weight, valueAll); } } } } int main(int argc, char const* argv[]) { cout << "
1 输入输出:
1.1 概述
输入函数input x=input([‘输入信息’]) 返回值为str
输出语句print(对象1,…对象n,seq=’ ‘,end=’\n’)
1.2 举例
如何输入获得两个字符串?(若输入abc def或者abc,def)
x,y = input('Input:').split() #换行符读不到 x,y = input('Input:').split(' ') #逗号分隔 x,y = input('Input:').split(',') 如何输入获得两个整数?
x,y = eval(input("Input: ")) 输入获得一个元素均为数值型的列表?
lst = list(eval(input('Input: '))) Input:12,3.4,789 输入:lst 输出:[12,3.4,789] lst = eval(input('Input: ')) Input:[12,3.4,789] 输入:lst 输出:[12,3.4,789] 如何将循环输出的所有数据放在同一行输出?
for i in range(1,5): print(i,end=' ') 如何通过列表解析的方法把字符串转成数值类型?
lst = input('Input: ').split(',') Input:12,3.4,789 输入:lst 输出:['12','3.4','789'] 输入:[eval(item) for item in lst] 输出:[12,3.4,789] 2 函数式编程:
2.1 概述
直接查看文件内容
1. cat
cat 是concatenate的缩写,主要功能是将文件内容连续显示在输出设备上,搭配有效的参数,可以使输出内容达到自己想要的结果。它的缺点是当文件内容行数很多时,往往根本来不及看,所以使用时有局限性。
$ cat rainbow
This
is
my
rainbow.
'[-n]参数,用来显示行号'
$ cat -n rainbow
1 This
2 is
3 my
4 rainbow.
'[-A]参数,用来将文件内容完整显示(包含特殊字符)'
$ cat -A rainbow
This $
is $
my $
^Irainbow.$
正常情况下,即使文本内容中有Tab或换行符等特殊字符,输出结果中也不会展示出来。使用cat -A时,输出结果中会将Tab以^I显示,换行符会显示为$。在Windows系统中,是以^M$为换行符,如果你在Windows平台下调试通过的脚本放在Linux系统中却报错,vim中查看代码也没有发现任何问题,那就需要考虑是不是换行符引发的问题。
2. tac
从单词来看,tac是上一个命令cat的反写,实际它的功能也和cat有类似关系。cat是将第一行到最后一行内容连续显示在输出设备上,而tac则是将最后一行到第一行内容连续显示在输出设备上。
$ tac rainbow
rainbow.
m y
is
This
3. nl
nl命令和cat -n命令类似,也是会在显示内容时自动添加行号。但是nl命令会自动跳过空白行,而cat -n则不会忽略空白行。
$ nl rainbow
1 This
2 is
3 m y
4 rainbow.
$ cat -n rainbow
NEO4J安装指南Linux篇,neo4j安装指南
NEO4J安装指南Linux篇
NEO4J安装指南Linux篇
1.JAVA环境——neo4j要求JDK8
查看Java版本
[root@tac software]# java -version
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)
You have new mail in /var/spool/mail/root
[root@tac software]#
2.创建一个用户neo4j,用来管理Neo4j 。当然这不是必须的。也可以是其它账号或root账号。
[root@tac neo4j-community-3.3.6]# groupadd nosql
[root@tac neo4j-community-3.3.6]# useradd -G nosql neo4j
3.解压
[root@tac ~]# tar -zxvf neo4j-community-3.3.6-unix.tar.gz -C /usr/local
4.修改环境变量
[root@tac neo4j-community-3.3.6]# vi /etc/profile
export NEO4J_HOME=/usr/local/neo4j/neo4j-community-3.3.6
export PATH=$PATH:$NEO4J_HOME/bin
保存退出后执行更改
[root@tac neo4j-community-3.3.6]# source /etc/profile
Linux中用的是时间片轮转算法,进程轮训要消耗时间,转换到一个进程来执行要消耗时间。结果在进程睡眠和运行过程中,许多时间已经过去了。
sleep()是以秒为单位的,要想延迟一个较小的时间,就需要用到usleep()。
另外还有个nanosleep(),用法好像很复杂。
usleep可能很难保证时间精度。我写了一段测试代码
#include #include #include intmain(void)
{
inti;
structtimeval tvTotal;
structtimeval tvBegin, tvEnd, tvSub;
tvTotal.tv_sec = 0;
tvTotal.tv_usec = 0;
for(i = 0; i {
gettimeofday(&tvBegin, NULL);
usleep(1000);// 1000 us(microsecond/微秒) = 1 ms(毫秒)
gettimeofday(&tvEnd, NULL);
timersub(&tvEnd, &tvBegin, &tvSub);
tvTotal.tv_sec += tvSub.tv_sec;
tvTotal.tv_usec += tvSub.tv_usec;
printf("%d\n", tvSub.tv_usec);
}
printf("try to usleep 1000 us 100 times, average of result is: %ld\n", tvTotal.tv_sec*1000*10+tvTotal.tv_usec/100);
return0;
}
在虚拟机上运行的结果,证实偏差很大:
[root@localhost ~]# ./test
1118
linux查看硬件信息
(1)查看硬盘大小:df -h
(2)查看内存大小free -m ll-h/proc/kcore
(3)查看CPUcat /proc/cpuinfo
(4)如何查看Linux系统中逻辑和物理cpu的个数
linux下/proc/cpuinfo文件会显示cpu的信息
逻辑CPU个数是指cat /proc/cpuinfo所显示的processor的个数#cat /proc/cpuinfo | grep "processor" | wc -l
物理CPU个数,是指physical id(的值)的数量#cat /proc/cpuinfo | grep "physical id" | sort | uniq | wc -l
每个物理CPU中Core的个数:每个相同的physical id都有其对应的core id。如core id分别为1、2、3、4,则表示是Quad-Core CPU,若core id分别是1、2,则表示是Dual-Core。#cat /proc/cpuinfo | grep "cpucores" | wc -l
逻辑CPU:每个物理CPU中逻辑CPU(可能是core,threads或both)的个数:#cat /proc/cpuinfo | grep "siblings"
它既可能是cores的个数,也可能是core的倍数。当它和core的个数相等时,表示每一个core就是一个逻辑CPU,若它时core的2倍时,表示每个core又enable了超线程(Hyper-Thread)。
比如:一个双核的启用了超线程的物理cpu,其core id分别为1、2,但是sibling是4,也就是如果有两个逻辑CPU具有相同的”core id”,那么超线程是打开的。
查看linux内核版本[root@xiaohuai~]#uname -a
Linux xiaohuai 2.6.32-358.14.1.el6.x86_64 #1 SMP Tue Jul 16 23:51:20 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
题目描述:
小乐乐在课上学习了二进制八进制与十六进制后,对进制转换产生了浓厚的兴趣。因为他的幸运数字是6,所以他想知道一个数表示为六进制后的结果。请你帮助他解决这个问题。
输入描述:
输入一个正整数n (1 ≤ n ≤ 109)
输出描述:
输出一行,为正整数n表示为六进制的结果
示例1:
输入
6
输出
10
示例2:
输入
120
输出
320
解题思路:
十进制转化为其他进制的数,用短除法倒取余数。
import java.util.Scanner; public class Main{ public static void main(String [] args){ Scanner in=new Scanner(System.in); int n=in.nextInt(); int a=0; int i=0; int [] s=new int [100]; while(n!=0){ a=n%6; n=n/6; i++; s[i]=a; } for(int j=i;j>0;j--){ System.out.print(s[j]); } //Integer.toString(int par1,int par2) //par1表示要转成字符串的数字,par2表示要转成的进制表示 } }
什么是CPU上下文切换?
现在linux是大多基于抢占式,CPU给每个任务一定的服务时间,当时间片轮转的时候,需要把当前状态保存下来,同时加载下一个任务,这个过程叫做上下文切换。时间片轮转的方式,使得多个任务利用一个CPU执行成为可能,但是保存现场和加载现场,也带来了性能消耗。 那线程上下文切换的次数和时间以及性能消耗如何看呢?
如何获得上下文切换的次数?
vmstat直接运行即可,在最后几列,有CPU的context switch次数。 这个是系统层面的,加入想看特定进程的情况,可以使用pidstat。
$ vmstat 1 100
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 88 233484 288756 1784744 0 0 0 23 0 0 4 1 94 0 0
4 0 88 233236 288756 1784752 0 0 0 0 6202 7880 4 1 96 0 0