什么是营销型网站设计,横沥建设网站,做外贸的有哪些网站有哪些,网站返利二维码怎么做文章目录 后端太卷#xff0c;建议往嵌入式#xff0c;qt#xff0c;测试#xff0c;音视频#xff0c;C一些细分领域投简历。有任何疑问评论区聊#xff0c;我看到了回复 C面试/笔试准备#xff0c;资料汇总自我介绍项目实习尽可能有1.编程语言#xff1a;一.熟悉C语言… 文章目录 后端太卷建议往嵌入式qt测试音视频C一些细分领域投简历。有任何疑问评论区聊我看到了回复 C面试/笔试准备资料汇总自我介绍项目实习尽可能有1.编程语言一.熟悉C语言熟悉std::string的底层实现。string的底层实现写时复制技术1、 引用指针野指针2、C中的继承多态封装3、 什么是多态什么是虚函数实现原理4、C中struct与class的区别5、 new和malloc区别5、 四种强制类型转换及应用场景6、 i和i7、浅拷贝和深拷贝8、C中的内存分区 二.熟悉STL六大组件的使用了解各容器的底层实现。9、常见容器性质总结 三.掌握面向对象的编程思想理解类与类之间的关系了解面向对象的设计原则。 面向对象设计原则四.掌握C11新特性。移动语义智能指针8、C提供了哪几种智能指针其各自的特点是什么 2.数据结构和算法掌握常用的数据结构例如链表、栈、队列、二叉树、哈希表。了解红黑树、B树、B树等。掌握八大排序算法。#十大排序中的非稳定排序 3.网络编程:熟悉Linux下的Socket编程、熟悉TCP协议TCP报文头掌握网络IO复用模型select/epoll。网络socket本地socket区别 五种I/O模型1、OSI七层协议2、工业标准 4层或5层协议3、数据在网络中发送时的情况4、传输层TCP协议5、TCP建立连接时会采用三次握手为什么6、2次握手可以不8、TCP连接断开时要采用四次挥手为什么9、服务器是否可以主动断开连接呢10、 为什么需要TIME_WAIT状态11、删除TIME_WAIT状态是否可行12、Socket13、epoll 与select的对比14、水平触发 vs 边缘触发15、发送数据时若一次没有发送完成需要执行滑动窗口机制16、mmap掌握并发服务器模型Reactor。掌握Http协议。17、HTTP全称超文本传输协议。18、URI由哪些部分组成19、HTTP请求报文和响应报文由哪些部分组成20、HTTP常用方法有哪些21、HTTP常用状态码有哪些22、form-data的boundary起什么作用有什么限制23、 简要说明一下HTTPS的握手阶段流程。24、知道DNS是什么25、HTTPS和HTTP的区别26、在浏览器中输入url地址后显示主页的过程? 4.操作系统一、熟悉使用linux(ubuntu18.04)。什么是LinuxLinux和Unix有什么区别什么是Shell什么是文件系统什么是进程Linux中如何查看进程Linux中如何安装软件包Linux中如何查看系统日志Linux中如何设置文件权限Linux中如何设置环境变量Linux中如何查看网络配置Linux中如何查看硬件信息Linux中如何查看磁盘使用情况Linux中如何查看系统负载Linux中如何创建用户Linux中如何修改用户密码Linux中如何安装服务Linux中如何启动和停止服务Linux中如何查看系统版本Linux中如何查看当前用户Linux中如何设置定时任务Linux中如何远程登录Linux中如何设置防火墙Linux中如何查看当前系统使用的内存和CPU情况Linux中如何查看当前系统的IP地址Linux中如何设置系统时间Linux中如何查看系统中的进程数量Linux中如何查看系统中安装的软件包Linux中如何查看系统中的网络连接Linux中如何安装和配置Nginx Web服务器 二、熟悉进程间通信多线程编程、文件读写buffer I/O,unbuffer I/O ,mmap 。内存虚拟化1.进程通信的方式2.进程调度算法3.分段、分页、段页式4.什么是孤儿进程什么是僵尸进程他们对操作系统有什么影响5.进程的结束方式有哪些return和exit有什么区别7、进程、进程组、会话和控制终端的关系是什么样的8、守护进程和后台进程组的区别是什么9、无名管道和命名管道有哪些特点和区别10、什么是线程线程和进程有哪些区别11、线程的标识 线程的创建12、线程的清理函数什么时候会执行什么时候不会执行13、 为什么pthread_cleanup_push和pthread_cleanup_pop需要成对出现14、使用条件变量的使用为什么一定要加锁?生产者与消费者问题互斥锁条件变量线程池同一进程下的线程可以共享 三、熟悉进程池、线程池的实现。1、进程池 四、简单了解分布式系统消息队列。线程池的实现oo_threadpool 5.设计模式:方式一: 嵌套类 静态对象方式二: 自动调用destroy方法就可以回收单例对象方式三: pthead_once atexit就可以回收单例对象有环境限制只能在linux环境下,实现了多线程安全 类与类之间的关系—继承(泛化)类与类之间的关系—关联类与类之间的关系—聚合类与类之间的关系—组合类与类之间的关系—依赖设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结工厂模式代理模式Proxy Pattern【结构型模式】观察者模式Observer Pattern【行为型模式】 6.数据库:1、事务的四大基本特征是什么2、并发产生的四大基本问题是什么4、B树和B树的区别5、什么是最左前缀原则6、MyISAM与InnoDB各自有什么特点5、MyISAM索引与InnoDB索引的区别6、临时表与存储引擎是memory的表有什么区别 掌握Redis。1、 什么是Redis?有哪些有优缺点2、为什么要用 Redis /为什么要用缓存3、 Redis为什么这么快4、Redis有哪些数据类型5、什么是Redis持久化6、Redis 的持久化机制是什么各自的优缺点7、 Redis key的过期时间和永久有效分别怎么设置8、Redis事务的概念9、Redis事务的三个阶段10、Redis事务相关命令和事务的特征11、缓存穿透是什么如何解决12、缓存击穿是什么有什么解决方案13、缓存雪崩的概念如何应对 7.常用工具面试雷区一、“我没有其他问题要问了......”❌二、“期望薪资方面我没有什么想法...”❌您好我在上家公司实习/工作的时候到手的薪资是xxx结合我的工作经验和个人诉求我的期望薪资是xxx根据目前的行业前景和市场行情我觉得我的要求是合适的以上就是我个人的薪资期望您这边觉得怎样呢三、“我对该岗位没有什么经验但我会认真去学习哒...”❌ github 后端太卷建议往嵌入式qt测试音视频C一些细分领域投简历。
有任何疑问评论区聊我看到了回复
C面试/笔试准备资料汇总
自我介绍
面试官 您好我是XXX就读于XXX大学XXX专业很荣幸有机会参加此次面试我这次面试的是linux助理开发工程 师岗位我们应届生呢经验不太多但是我去年去XX实习了4个月具有一定的实践经验我之前研究了贵公司的linux助理开发工程 师岗位需求
第一我在开发环境上熟悉linuxwindows开发环境有自己配置的linux开发环境使用过阿里云的对象存储
第二熟悉CSTL
第三熟悉网络编程掌握常用算法最近在参加一期60天的算法训练营坚持14天了吧。边练边写边写写博客简历上有博客连接。github上记录了自己的学习经历以及一个面向对象和基于对象的线程池代码目前还在消化吸收。
汽车全液晶仪表盘HMI显示工具kanzi
shader就是专门用来渲染3D图形的一种技术
第四有实际项目经验是linux下的两个项目。熟悉git提交代码
我的毕设就打算写一个基于workflow的小型私有云系统。虽然还未完工但最近几天实现了内网穿透可以在网络上访问我的项目。
我的责任心很强目标导向做事情都会全力以赴。
爱好XXXXX
职业发展高级软件工程师系统分析师系统架构师。
特别期待加入您的团队。
项目实习尽可能有
必须有自己找个练练要资料的评论区聊
1.编程语言
一.熟悉C语言熟悉std::string的底层实现。
string的底层实现写时复制技术 1、 引用指针
指针是一个变量存储的是一个地址引用跟原来的变量实质上是同一个东西是原变量的别名指针可以有多级引用只有一级指针可以为空引用不能为NULL且在定义时必须初始化指针在初始化后可以改变指向而引用在初始化之后不可再改变sizeof指针得到的是本指针的大小sizeof引用得到的是引用所指向变量的大小当把指针作为参数进行传递时也是将实参的一个拷贝传递给形参两者指向的地址相同但不是同一个变量在函数中改变这个变量的指向不影响实参而引用却可以。引用本质是一个指针同样会占4字节内存指针是具体变量需要占用存储空间具体情况还要具体分析。引用在声明时必须初始化为另一变量一旦出现必须为typename refname varname形式指针声明和定义可以分开可以先只声明指针变量而不初始化等用到时再指向具体变量。引用一旦初始化之后就不可以再改变变量可以被引用为多次但引用只能作为一个变量引用指针变量可以重新指向别的变量。不存在指向空值的引用必须有具体实体但是存在指向空值的指针。
使用
经常用指针指向结构体或某个类以免重复构造消耗
野指针
产生野指针
1.指针变量未初始化或随便赋值
2.指针释放后未置空
3.指针操作超出了变量的操作域(于是指向内存都是随机的)
避免产生
1.指针初始化
2.释放后置空
2、C中的继承多态封装
大特性继承、封装和多态
1继承
让某种类型对象获得另一个类型对象的属性和方法。
它可以使用现有类的所有功能并在无需重新编写原来的类的情况下对这些功能进行扩展
常见的继承有三种方式
实现继承指使用基类的属性和方法而无需额外编码的能力接口继承指仅使用属性和方法的名称、但是子类必须提供实现的能力可视继承指子窗体类使用基窗体类的外观和实现代码的能力C里好像不怎么用
例如将人定义为一个抽象类拥有姓名、性别、年龄等公共属性吃饭、睡觉、走路等公共方法在定义一个具体的人时就可以继承这个抽象类既保留了公共属性和方法也可以在此基础上扩展跳舞、唱歌等特有方法
2封装
数据和代码捆绑在一起避免外界干扰和不确定性访问。
封装也就是把客观事物封装成抽象的类并且类可以把自己的数据和方法只让可信的类或者对象操作对不可信的进行信息隐藏例如将公共的数据或方法使用public修饰而不希望被访问的数据或方法采用private修饰。
3多态
同一事物表现出不同事物的能力即向不同对象发送同一消息不同的对象在接收时会产生不同的行为**重载实现编译时多态虚函数实现运行时多态**。
多态性是允许你将父对象设置成为和一个或更多的他的子对象相等的技术赋值之后父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单一句话允许将子类类型的指针赋值给父类类型的指针
实现多态有二种方式覆盖override重载overload。
覆盖是指子类重新定义父类的虚函数的做法。
重载是指允许存在多个同名函数而这些函数的参数表不同或许参数个数不同或许参数类型不同或许两者都不同。例如基类是一个抽象对象——人那教师、运动员也是人而使用这个抽象对象既可以表示教师、也可以表示运动员
3、 什么是多态什么是虚函数实现原理
什么叫多态
客观现实世界不同的对象面对同一个指令消息产生不同的行为。
多态的分类
静态多态编译时可以确定下来函数重载、运算符重载、函数模板
动态多态运行时可以确定下来C采用虚函数
虚函数的定义
在一个成员函数的前面加上virtual关键字该函数就成为虚函数
虚函数实现原理 当类中定义了一个虚函数时其对象的存储布局开始位置会
多一个虚函数指针该虚函数指针指向一张虚函数表
虚函数如何实现动态多态特性的 虚函数被激活的条件有 答1. 基类定义虚函数 2. 派生类覆盖重定义该虚函数 3. 创建派生类对象 4. 基类指针(引用)指向(绑定)派生类对象 5. 通过基类指针(引用)调用虚函数
重载
overload发生在同一个类中当函数名称相同时函数参数类型、顺序、个数不同
隐藏
oversee发生在父子类之间函数名称相同时就构成隐藏
覆盖(override)发生在父子类之间基类与派生类中同时定义相同的虚函数****,
**覆盖的是虚函数表中的入口地址**并不是覆盖函数本身 4、C中struct与class的区别
一、本身成员的访问级别不同
最本质的区别结构体的成员和成员函数在默认情况下的访问级别是公有的public类的成员和成员函数在默认情况下的访问级别是私有的private。 注意 二者的访问方式都是 对象名点对象成员选择运算符访问对象成员
struct的用法无需加publicstruct中成员可直接在结构体外被访用默认publicclass的用法必须加public否则默认访问权限是private使得类中成员不能直接在类外被访问
5、 new和malloc区别
相同点
都可用于内存的动态申请和释放
不同点
前者是C运算符后者是C/C语言标准库函数new自动计算要分配的空间大小malloc需要手工计算new是类型安全的malloc不是。例如
int *p new float[2]; //编译错误
int *p (int*)malloc(2 * sizeof(double));//编译无错误 new调用名为operator new的标准库函数分配足够空间并调用相关对象的构造函数delete对指针所指对象运行适当的析构函数然后通过调用名为operator delete的标准库函数释放该对象所用内存。后者均没有相关调用 后者需要库文件支持前者不用 new是封装了malloc直接free不会报错但是这只是释放内存而不会析构对象
malloc 函数的实质是它有一个将可用的内存块连接为一个长长的列表的所谓空闲链表。 调用 malloc函数时它沿着连接表寻找一个大到足以满足用户请求所需要的内存块。如果没有搜索到那么就会用sbrk()才推进brk指针来申请内存空间。 然后将该内存块一分为二一块的大小与用户申请的大小相等另一块的大小就是剩下来的字节。 接下来将分配给用户的那块内存存储区域传给用户并将剩下的那块如果有的话返回到连接表上。 调用 free 函数时它将用户释放的内存块连接到空闲链表上。 到最后空闲链会被切成很多的小内存片段如果这时用户申请一个大的内存片段 那么空闲链表上可能没有可以满足用户要求的片段了。于是malloc函数请求延时并开始在空闲链表上检查各内存片段对它们进行内存整理将相邻的小空闲块合并成较大的内存块。 搜索空闲块最常见的算法有首次适配下一次适配最佳适配。 其实就是操作系统中动态分区分配的算法 首次适配第一次找到足够大的内存块就分配这种方法会产生很多的内存碎片。 下一次适配也就是说等第二次找到足够大的内存块就分配这样会产生比较少的内存碎片。 最佳适配对堆进行彻底的搜索从头开始遍历所有块使用数据区大小大于size且差值最小的块作为此次分配的块。
free只是将内存管理块设置为可用
5、 四种强制类型转换及应用场景
static_castvoid* 向其他类型进行转换
const_cast 去除常量属性函数传参时使用
dynamic_cast基类与派生类之间使用
reinterpret_cast可以在任意类型间转换
6、 i和i
但是性能是不同的。. 在大量数据的时候i的性能要比i的性能好原因. i由于是在使用当前值之后再1所以需要一个临时的变量来转存。. 而i则是在直接1省去了对内存的操作的环节相对而言能够提高性能.
7、浅拷贝和深拷贝
浅拷贝 浅拷贝又称为值拷贝将源对象的值拷贝到目标对象中如果对象中有某个成员是指针类型数据并且是在堆区创建则使用浅拷贝仅仅拷贝的是这个指针变量的值也就是在目标对象中该指针类型数据和源对象中的该成员指向的是同一块堆空间。这样会带来一个问题就是在析构函数中释放该堆区数据会被释放多次。默认的拷贝构造函数和默认的赋值运算符重载函数都是浅拷贝。深拷贝 深拷贝在拷贝的时候先开辟出和源对象大小一样的空间然后将源对象里的内容拷贝到目标对象中去这样指针成员就指向了不同的内存位置。并且里面的内容是一样的这样不但达到了拷贝的目的还不会出现问题两个对象先后去调用析构函数分别释放自己指针成员所指向的内存。即为每次增加一个指针便申请一块新的内存并让这个指针指向新的内存深拷贝情况下不会出现重复释放同一块内存的错误。 3. 拷贝构造函数和赋值运算符重载函数就会实现深拷贝
8、C中的内存分区
分别是堆、栈、自由存储区、全局/静态存储区、常量存储区和代码区。
栈在执行函数时函数内局部变量的存储单元都可以在栈上创建函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中效率很高但是分配的内存容量有限
堆就是那些由 new分配的内存块他们的释放编译器不去管由我们的应用程序去控制一般一个new就要对应一个 delete。如果程序员没有释放掉那么在程序结束后操作系统会自动回收
自由存储区如果说堆是操作系统维护的一块内存那么自由存储区就是C中通过new和delete动态分配和释放对象的抽象概念。需要注意的是自由存储区和堆比较像但不等价。
全局/静态存储区全局变量和静态变量被分配到同一块内存中在以前的C语言中全局变量和静态变量又分为初始化的和未初始化的在C里面没有这个区分了它们共同占用同一块内存区在该区定义的变量若没有初始化则会被自动初始化例如int型变量自动初始为0
常量存储区这是一块比较特殊的存储区这里面存放的是常量不允许修改
代码区存放函数体的二进制代码
二.熟悉STL六大组件的使用了解各容器的底层实现。
9、常见容器性质总结 1.vector 底层数据结构为数组 支持快速随机访问
2.list 底层数据结构为双向链表支持快速增删
3.deque 底层数据结构为一个中央控制器和多个缓冲区详细见STL源码剖析P146支持首尾中间不能快速增删也支持随机访问
deque是一个双端队列(double-ended queue)也是在堆中保存内容的.它的保存形式如下:
[堆1] -- [堆2] --[堆3] -- …
每个堆保存好几个元素,然后堆和堆之间有指针指向,看起来像是list和vector的结合品.
4.stack 底层一般用list或deque实现封闭头部即可不用vector的原因应该是容量大小有限制扩容耗时
5.queue 底层一般用list或deque实现封闭头部即可不用vector的原因应该是容量大小有限制扩容耗时stack和queue其实是适配器,而不叫容器因为是对容器的再封装
6.priority_queue 的底层数据结构一般为vector为底层容器堆heap为处理规则来管理底层容器实现
使用重载排序时应注意重载cmp函数时是从小排序和其他相反
7.set 底层数据结构为红黑树有序不重复
8.multiset 底层数据结构为红黑树有序可重复
9.map 底层数据结构为红黑树有序不重复
10.multimap 底层数据结构为红黑树有序可重复
11.unordered_set 底层数据结构为hash表无序不重复
12.unordered_multiset 底层数据结构为hash表无序可重复
13.unordered_map 底层数据结构为hash表无序不重复
14.unordered_multimap 底层数据结构为hash表无序可重复
三.掌握面向对象的编程思想理解类与类之间的关系了解面向对象的设计原则。
面向对象设计原则
一个优良的系统设计强调要保持低耦合、高内聚的关系 SOLID的5原则 》基本原则
单一职责原则 (Single Responsibility Principle)
一个类最好只做一件事只有一个引起它变化的原因
此原则的核心就是解耦和增强内聚性
2.开闭原则 (Open Closed Principle)
对扩展开放对修改闭合
核心思想就是对抽象编程继承和多态实现 里氏替换原则 (Liscov Substitution Principle) 派生类可以扩展基类的功能但不能改变基类原有的功能 接口分离原则 (Interface Segregation Principle) 使用多个小的专门的接口而不要使用一个大的总接口。 依赖倒置原则 (Dependency Inversion Principle) 面向接口编程依赖于抽象(抽象是稳定的具体的是在变化的) 迪米特法则 Law of Demeter - Least Knowledge Principle 一个软件实体应当尽可能少地与其他实体发生相互作用 组合复用原则 (Composite/Aggregate Reuse Principle) 尽量采用组合、聚合的方式而不是继承的方式来达到软件复用的目标
四.掌握C11新特性。移动语义智能指针
移动语义就是将临时对象转移到新对象中去 8、C提供了哪几种智能指针其各自的特点是什么
使用时机
实现多态时基类指向派生类对象时可以使用智能指针。
auto_ptr 可以进行复制构造或者赋值操作但是有bug
unique_ptr
1. 独享所有权的智能指针
2. 不具备值语义不能进行拷贝构造或者赋值操作
3. 具有移动语义可以发生转移
4. 可以作为容器的元素
shared_ptr
1. 共享所有权的智能指针
2. 具备值语义可以进行复制或者赋值操作主打特点 引入了引用计数执行复制或者赋值操作时引用计数加1 当一个shared_ptr被销毁时引用计数减1直到为0时才真正释放托管的对象
3. 具有移动语义可以发生转移
4. 可以作为容器的元素
5. 又称为强引用的智能指针weak_ptr1. weak_ptr 是一个弱引用的智能指针
2. 当weak_ptr执行拷贝构造或赋值操作时不会导致引用计数加1
3. weak_ptr知道所托管的对象是否还存活 expired方法完成
4. weak_ptr不能直接访问对象没有重载-和 *运算符
5. weak_ptr如要访问资源必须提升成为shared_ptr才行 lock方法完成智能指针使用场景 实现多态创建基类指针指向派生类对象时这里可以使用智能指针。
2.数据结构和算法
掌握常用的数据结构例如链表、栈、队列、二叉树、哈希表。了解红黑树、B树、B树等。 掌握八大排序算法。 冒泡排序bubble sort — O(n2) 插入排序 insertion sort— O(n2) 归并排序 merge sort— O(n log n)
#十大排序中的非稳定排序 面试考察中一般问快排选择希尔堆这几种非稳定排序 3.网络编程:
熟悉Linux下的Socket编程、熟悉TCP协议TCP报文头掌握网络IO复用模型select/epoll。
网络socket本地socket区别
本地不需要经过网络协议栈不需要打包拆包、计算校验和、维护序号和应答等只是将应用层数据从一个进程拷贝到另一个进程。
IPC机制本质上是可靠的通讯而网络协议是为不可靠的通讯设计的
网络编程的socket地址是IP地址加端口号而UNIX Domain Socket的地址是一个socket类型的文件在文件系统中的路径
五种I/O模型 1、OSI七层协议 2、工业标准 4层或5层协议 3、数据在网络中发送时的情况 4、传输层TCP协议 5、TCP建立连接时会采用三次握手为什么
答1. 要确保双方确实已经收到了对方的确认
连接建立成功
防止大量出现被延迟的SYN报文到达服务器时
产生的问题
6、2次握手可以不
第一种情况第一次握手
SYN报文被延迟
当客户端重发SYN之后与服务器建立好了连接并且完成了数据的通信。之后被延迟的SYN报文此时到达了服务器服务器会认为客户端重新要建立连接因此会给客户端回复一个ACK报文此时服务器就开始等待客户端发送数据。很显然此时客户端根本就没有建立连接的需求会造成服务器资源的浪费
第二种情况第二个报文ACK在网络中消失没有被client接收到服务器因为已经发生了ACK报文它认为连接已经建立好了傻傻地等待客户端发数据过来造成服务器资源的浪费此时客户端根本就没有收到因此认为该连接没有建立成功的
8、TCP连接断开时要采用四次挥手为什么
答TCP是一个全双工的协议。全双工的含义可以同时进行数据的读写操作互不干扰。全双工当连接断开时要做到两个方向上的数据传输全部断开。
1第一次client发送FIN报文时表示client已经发送完了所有的数据再没有数据要发送给server了但还可以
接收数据
2当server收到FIN报文并进行确认发送ACK时表示它已经知道了client没有数据发送了。
3当server也没有数据要发送给client时发送FIN报文给client
4当client收到FIN时最后一次给server发送ACK报文当ACK报文到达服务器时就断开连接
9、服务器是否可以主动断开连接呢
答 可以。如果服务器主动断开连接 会进入到TIME_WAIT状态该状态持续2MSL的时间
此时服务器不能做其他的事情是对服务器资源的一种浪费因此一般情况下服务器不会主动断开连接。
但服务器是可以主动断开连接的同时为了防止出现服务器资源浪费的情况会设置套接字属性可以重用
10、 为什么需要TIME_WAIT状态
答1防止出现连接无法正常断开的情况
2 防止出现数据蹿链的情况
11、删除TIME_WAIT状态是否可行 一种情况:
假设server端没有收到第4次挥手ACK服务器认为连接没有断开因此它会重发FIN报文等待客户端给其回复ACK
客户端由于已经发送了ACK报文它认为该连接已经断开了因此不会再接收FIN报文了
总结这样会导致该连接无法正常断开
第二种情况数据蹿链
一个tcp连接由协议类型、源IP/源port、目的IP/目的port五元组信息构成
第一次起了一个连接也完成了通信过程连接关闭了当再起一个新连接时其五元组与第一次是相同的
此时如果第一次连接进行过程中在网络中被延迟的数据到达了第二个连接是一定会被第二个连接接收的。因此就会造成数据蹿链的问题
在网络中被延迟的数据指的是确认重传的数据
12、Socket
13、epoll 与select的对比 14、水平触发 vs 边缘触发 15、发送数据时若一次没有发送完成需要执行滑动窗口机制
16、mmap 掌握并发服务器模型Reactor。 掌握Http协议。
17、HTTP全称超文本传输协议。
超文本①HTTP是文本协议这意味着HTTP报文的头部数据是文本类型的用户可以直接阅读报文内容。 ②最初载荷类型是超文本数据现在可以载荷其他类型数据。 传输①HTTP采用客户端-服务端的传输模型。 ②HTTP是一种无状态的协议。 协议HTTP是一种应用层协议在TCP/IP协议族处于第四层在ISO/OSI体系中处于第七层其依赖的传输层是 可靠的协议比如TCP协议、QUIC协议。
18、URI由哪些部分组成
scheme方案名默认HTTP常见的还有HTTPSFTP
://
userinfo用户名密码host:port域名IP4/IP6端口号http的80、https的443可以省略
/路径资源在服务器中的路径默认/后边可以省略
?查询字符串键值对用连接
#分页符19、HTTP请求报文和响应报文由哪些部分组成
###请求报文
1、报文头起始行方法URI版本首部字段空行。
2、报文体。###响应报文
1、报文头起始行版本状态码原因字符串首部字段空行。
2、报文体。20、HTTP常用方法有哪些
GET“读”用来获取资源
POST“写”用来提交表单给对应的资源这个请求通常来说会修改资源的状态称为有副作用的。
PUT用请求的内容替换掉目标资源的内容。
DELETE删除目标资源
HEAD用来获取资源的首部字段不获取响应体。21、HTTP常用状态码有哪些
200 ok 请求成功301 Moved Permanently 永久重定向302 Found 临时重定向400 Bad Request 语法无效403 Forbidden 无权限404 Not Found 无资源405 Method Not Allowed 不允许的方法500 Internal Server Error 服务端错误501 Not Implemented 服务器不支持请求方法502 Bad Gateway 错误的响应504 Gateway Timeout 响应超时22、form-data的boundary起什么作用有什么限制
作用作为请求报文报文体中key-value的分隔符限制长度不能超过70个字符传输的内容不能与boundary相同最后一个boundary后面会添加--作为整个请求体的结尾。23、 简要说明一下HTTPS的握手阶段流程。
Client hello客户端向服务端发送连接请求并发送支持的TLS版本支持的加密算法
Server helo服务端向客户端发送连接请求回复加密算法
Certificate服务端验证证书
Server key exchange服务端向客户端发送通过算法生成的公钥
Server finished服务端发送密钥完成
Client key exchange客户端向服务端发送算法生成的公钥
Client hello客户端向服务端发送连接确认
Finished完成连接
Finished完成连接24、知道DNS是什么
官方解释DNSDomain Name System域名系统因特网上作为域名和IP地址相互映射的一个分布式数据库能够使用户更方便的访问互联网而不用去记住能够被机器直接读取的IP数串。
通过主机名最终得到该主机名对应的IP地址的过程叫做域名解析或主机名解析。
通俗的讲我们更习惯于记住一个网站的名字比如www.baidu.com,而不是记住它的ip地址比如167.23.10.2
25、HTTPS和HTTP的区别
1、HTTP协议传输的数据都是未加密的也就是明文的因此使用HTTP协议传输隐私信息非常不安全 HTTPS协议是由SSLHTTP协议构建的可进行加密传输、身份认证的网络协议要比http协议安全。
2、https协议需要到ca申请证书一般免费证书较少因而需要一定费用。 3、http和https使用的是完全不同的连接方式用的端口也不一样前者是80后者是443
26、在浏览器中输入url地址后显示主页的过程? 根据域名进行DNS域名解析拿到解析的IP地址建立TCP连接向IP地址发送HTTP请求服务器处理请求返回响应结果关闭TCP连接浏览器解析HTML浏览器布局渲染 4.操作系统
一、熟悉使用linux(ubuntu18.04)。
什么是Linux
Linux是一种自由和开放源代码的类Unix操作系统它是由Linus Torvalds和其他开发人员共同创建的。
Linux和Unix有什么区别
Linux是基于Unix的但它是一个独立的操作系统。Unix是商业化的操作系统而Linux是开源的。
什么是Shell
Shell是Linux中的命令行解释器它是用户与内核之间的接口。用户可以使用Shell来执行命令、编辑文件、管理文件系统等操作。
什么是文件系统
文件系统是计算机中用来管理文件和目录的一种方式。Linux中的文件系统包括Ext2、Ext3、Ext4等。
什么是进程
进程是正在运行的程序的实例。每个进程都有自己的内存空间、文件句柄等资源。
Linux中如何查看进程
可以使用ps命令来查看当前运行的进程也可以使用top命令来查看进程的资源使用情况。
Linux中如何安装软件包
可以使用包管理器来安装软件包如yum、apt-get等。也可以手动下载软件包并使用源代码编译安装。
Linux中如何查看系统日志
可以使用日志文件来查看系统日志如/var/log/messages、/var/log/syslog等。
Linux中如何设置文件权限
可以使用chmod命令来设置文件权限如chmod x filename可以将文件设置为可执行权限。
Linux中如何设置环境变量
可以使用export命令来设置环境变量如export PATH$PATH:/usr/local/bin可以将/usr/local/bin路径添加到PATH环境变量中。
Linux中如何查看网络配置
可以使用ifconfig命令来查看网络配置如ifconfig eth0可以查看eth0网卡的配置信息。
Linux中如何查看硬件信息
可以使用lshw命令来查看硬件信息如lshw -short可以查看系统中的所有硬件设备。
Linux中如何查看磁盘使用情况
可以使用df命令来查看磁盘使用情况如df -h可以查看磁盘的使用情况和可用空间。
Linux中如何查看系统负载
可以使用uptime命令来查看系统负载情况如uptime可以查看系统的负载平均值。
Linux中如何创建用户
可以使用useradd命令来创建用户如useradd username可以创建一个名为username的用户。
Linux中如何修改用户密码
可以使用passwd命令来修改用户密码如passwd username可以修改名为username的用户的密码。
Linux中如何安装服务
可以使用系统自带的包管理器来安装服务如yum install httpd可以安装Apache Web服务器。
Linux中如何启动和停止服务
可以使用systemctl命令来启动和停止服务如systemctl start httpd可以启动Apache Web服务器。
Linux中如何查看系统版本
可以使用uname命令来查看系统版本如uname -a可以查看详细的系统信息。
Linux中如何查看当前用户
可以使用whoami命令来查看当前用户如whoami可以查看当前登录用户的用户名。
Linux中如何设置定时任务
可以使用crontab命令来设置定时任务如crontab -e可以编辑当前用户的定时任务。
Linux中如何远程登录
可以使用ssh命令来远程登录如ssh usernamehost可以远程登录到名为host的主机并使用username账号进行登录。
Linux中如何设置防火墙
可以使用iptables命令来设置防火墙如iptables -A INPUT -p tcp --dport 80 -j ACCEPT可以允许80端口的TCP流量通过防火墙。
Linux中如何查看当前系统使用的内存和CPU情况
可以使用top命令来查看当前系统使用的内存和CPU情况如top -n 1可以查看当前的系统状态并在一秒钟后退出。
Linux中如何查看当前系统的IP地址
可以使用ifconfig命令来查看当前系统的IP地址如ifconfig eth0可以查看eth0网卡的IP地址。
Linux中如何设置系统时间
可以使用date命令来设置系统时间如date -s 2022-01-01 00:00:00可以将系统时间设置为2022年1月1日0时0分0秒。
Linux中如何查看系统中的进程数量
可以使用ps命令来查看系统中的进程数量如ps -ef | wc -l可以查看当前系统中的进程数量。
Linux中如何查看系统中安装的软件包
可以使用包管理器来查看系统中安装的软件包如yum list installed可以查看当前系统中已安装的软件包。
Linux中如何查看系统中的网络连接
可以使用netstat命令来查看系统中的网络连接如netstat -an | grep ESTABLISHED可以查看当前系统中的已经建立的网络连接。
Linux中如何安装和配置Nginx Web服务器
可以使用包管理器来安装Nginx Web服务器如yum install nginx可以安装Nginx。配置文件位于/etc/nginx/nginx.conf。
二、熟悉进程间通信多线程编程、文件读写buffer I/O,unbuffer I/O ,mmap 。 open, read, write, lseek及close unbuffer I/O
fopen, fread, fwrite, fclose buffer I/O 例如 迅雷下载文件 ftruncate 截断文件提前确定文件大小。
内存虚拟化 1.进程通信的方式
管道、命名管道、信号、消息队列、共享内存、内存映射、信号量、Socket 管道 管道也叫无名匿名管道它是是 UNIX 系统 IPC进程间通信的最古老形式所有的 UNIX 系统都支持这种通信机制。管道本质其实是内核中维护的一块内存缓冲区Linux 系统中通过 pipe() 函数创建管道会生成两个文件描述符分别对应管道的读端和写端。无名管道只能用于具有亲缘关系的进程间的通信。 命名管道 匿名管道由于没有名字只能用于亲缘关系的进程间通信。为了克服这个缺点提出了有名管道FIFO也叫命名管道、FIFO文件。有名管道FIFO不同于匿名管道之处在于它提供了一个路径名与之关联以 FIFO 的文件形式存在于文件系统中并且其打开方式与打开一个普通文件是一样的这样即使与 FIFO 的创建进程不存在亲缘关系的进程只要可以访问该路径就能够彼此通过 FIFO 相互通信因此通过 FIFO 不相关的进程也能交换数据。 信号 信号是 Linux 进程间通信的最古老的方式之一是事件发生时对进程的通知机制有时也称之为软件中断它是在软件层次上对中断机制的一种模拟是一种异步通信的方式。信号可以导致一个正在运行的进程被另一个正在运行的异步进程中断转而处理某一个突发事件。 消息队列 消息队列就是一个消息的链表可以把消息看作一个记录具有特定的格式以及特定的优先级对消息队列有写权限的进程可以向消息队列中按照一定的规则添加新消息对消息队列有读权限的进程则可以从消息队列中读走消息消息队列是随内核持续的。 共享内存 共享内存允许两个或者多个进程共享物理内存的同一块区域通常被称为段。由于一个共享内存段会称为一个进程用户空间的一部分因此这种 IPC 机制无需内核介入。所有需要做的就是让一个进程将数据复制进共享内存中并且这部分数据会对其他所有共享同一个段的进程可用。与管道等要求发送进程将数据从用户空间的缓冲区复制进内核内存和接收进程将数据从内核内存复制进用户空间的缓冲区的做法相比这种 IPC 技术的速度更快。 内存映射 内存映射Memory-mapped I/O是将磁盘文件的数据映射到内存用户通过修改内存就能修改磁盘文件。 信号量 信号量主要用来解决进程和线程间并发执行时的同步问题进程同步是并发进程为了完成共同任务采用某个条件来协调它们的活动。对信号量的操作分为 P 操作和 V 操作P 操作是将信号量的值减 1V 操作是将信号量的值加 1。当信号量的值小于等于 0 之后再进行 P 操作时当前进程或线程会被阻塞直到另一个进程或线程执行了 V 操作将信号量的值增加到大于 0 之时。 Socket 套接字Socket就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端提供了应用层进程利用网络协议交换数据的机制。Socket 一般用于网络中不同主机上的进程之间的通信。
2.进程调度算法 先来先服务FCFS调度算法 先来先去服务调度算法是一种最简单的调度算法也称为先进先出或严格排队方案。每次调度都是从后备作业进程队列中选择一个或多个最先进入该队列的作业进程将它们调入内存为它们分配资源、创建进程当每个进程就绪后它加入就绪队列。当前正运行的进程停止执行选择在就绪队列中存在时间最长的进程运行。 短作业优先SJF调度算法 短作业优先SJF的调度算法是从后备队列中选择一个或若干个估计运行时间最短的作业进程将它们调入内存运行短进程优先SPF调度算法从就绪队列中选择一个估计运行时间最短的进程将处理机分配给它使之立即执行直到完成或者发生某件事而阻塞时才释放处理机。 优先级调度算法 优先级调度算法又称优先权调度算法该算法既可以用于作业调度也可以用于进程调度该算法中的优先级用于描述作业运行的紧迫程度。在作业调度中优先级调度算法每次从后备作业队列中选择优先级最髙的一个或几个作业将它们调入内存分配必要的资源创建进程并放入就绪队列在进程调度中优先级调度算法每次从就绪队列中选择优先级最高的进程将处理机分配给它使之投入运行。 高响应比优先调度算法 高响应比优先调度算法主要用于作业调度该算法是对 FCFS 调度算法和 SJF 调度算法的一种综合平衡同时考虑每个作业的等待时间和估计的运行时间。在每次进行作业调度时先计算后备作业队列中每个作业的响应比从中选出响应比最高的作业投入运行。 时间片轮转调度算法 时间片轮转调度算法主要适用于分时系统。每次调度时把 CPU 分配给队首进程并令其执行一个时间片。时间片的大小从几 ms 到几百 ms。当执行的时间片用完时由一个计时器发出时钟中断请求调度程序便据此信号来停止该进程的执行并将它送往就绪队列的末尾然后再把处理机分配给就绪队列中新的队首进程同时也让它执行一个时间片。 多级反馈队列调度算法 多级反馈队列调度算法是时间片轮转调度算法和优先级调度算法的综合和发展通过动态调整进程优先级和时间片大小多级反馈队列调度算法可以兼顾多方面的系统目标。
3.分段、分页、段页式
标准回答
分段 **将用户程序地址空间分成若干个大小不等的段**每段可以定义一组相对完整的逻辑信息。存储分配时以段为单位段与段在内存中可以不相邻接实现了离散分配。分段主要是为了使程序和数据可以被划分为逻辑上独立的地址空间并且有助于共享和保护。分页 用户程序的地址空间被划分成若干固定大小的区域称为“页”**相应地内存空间分成若干个物理块页和块的大小相等。可将用户程序的任一页放在内存的任一块中实现了离散分配。**分页主要用于实现虚拟内存从而获得更大的地址空间。段页式 页式存储管理能有效地提高内存利用率解决内存碎片而分段存储管理能反映程序的逻辑结构并有利于段的共享。将这两种存储管理方法结合起来就形成了段页式存储管理方式。 段页式存储管理方式即先将用户程序分成若干个段再把每个段分成若干个页并为每一个段赋予一个段名。在段页式系统中为了实现从逻辑地址到物理地址的转换系统中需要同时配置段表和页表利用段表和页表进行从用户地址空间到物理内存空间的映射。
系统为每一个进程建立一张段表每个分段有一张页表。段表表项中至少包括段号、页表长度和页表始址页表表项中至少包括页号和块号。在进行地址转换时首先通过段表查到页表始址然后通过页表找到页帧号最终形成物理地址。 ps -ef | grep 进程号
top
4.什么是孤儿进程什么是僵尸进程他们对操作系统有什么影响
孤儿进程子进程还在运行父进程已经终止孤儿进程会被1号进程收养
僵尸进程子进程已经终止但父进程没有为子进程收尸此时的子进程是僵尸进程
当进程终止时Linux内核里面会为终止的进程保留一些信息(pid终止状态CPU总时间)
父进程可以调用wait或者waitpid获取这些信息
当子进程终止时内核会给父进程发送SIGCHLD信号父进程默认处理忽略
5.进程的结束方式有哪些return和exit有什么区别
1、return返回函数值是关键字 exit 是一个函数。
2、return是语言级别的它表示了调用堆栈的返回而exit是系统调用级别的它表示了一个进程的结束。
3、return是函数的退出(返回)exit是进程的退出。
4、return是C语言提供的exit是操作系统提供的或者函数库中给出的。
5、return用于结束一个函数的执行将函数的执行信息传出个其他调用函数使用exit函数是退出应用程序删除进程使用的内存空间并将应用程序的一个状态返回给OS这个状态标识了应用程序的一些运行信息这个信息和机器和操作系统有关一般是 0 为正常退出 非0 为非正常退出。
6、非主函数中调用return和exit效果很明显但是在main函数中调用return和exit的现象就很模糊多数情况下现象都是一致的。
7、进程、进程组、会话和控制终端的关系是什么样的
每个进程都属于一个进程组。
进程组一个或多个进程的集合。(一个进程只能隶属于一个进程组)
会话一个或多个进程组的集合
控制终端
(1)一个会话可以有0个或者1个控制终端
(2)如果会话有控制终端会话的首进程也被称为控制进程
(3)与终端相连的会话有一个前台控制组有0个或多个后台控制组
(4)前台进程组的成员可以响应键盘中断信号可以读取终端输入后台进程组则不会
(5)会话与终端断开连接会话首进程会收到SIGHUP信号
8、守护进程和后台进程组的区别是什么
(1)守护进程已经完全脱离终端控制台了而后台程序并未完全脱离终端(在终端未关闭前还是会往终端输出结果);
(2)守护进程在关闭终端控制台时不会受影响而后台程序会随用户退出而停止需要在以nohup command 格式运行才能避免影响;
(3)守护进程的会话组和当前目录文件描述符都是独立的。后台运行只是终端进行了一次fork让程序在后台执行这些都没改变;
9、无名管道和命名管道有哪些特点和区别
命名管道有名管道是文件系统中一种专门用来读写的文件但是通过有名管道进
行通信的时候实际上并没有经过磁盘而是经过内核的管道缓冲区进行数据传递。
特点FIFO可以在无关的进程之间交换数据与无名管道不同FIFO有路径名与之相关联它以一种特殊设备文件形式存在于文件系统中。
无名管道它不需要在文件系统创建单独的文件相反它是进程在执行过程中动态创建和销毁的。
特点它是半双工的即数据只能在一个方向上流动具有固定的读端和写端它只能用于具有亲缘关系的进程之间的通信也是父子进程或者兄弟进程之间它可以看成是一种特殊的文件对于它的读写也可以使用普通的read、write 等函数。但是它不是普通的文件并不属于其他任何文件系统并且只存在于内存中。
10、什么是线程线程和进程有哪些区别
线程一条执行流程
进程CPU分配资源的最小单位
线程CPU调度是最小单位
11、线程的标识
pthread_self获取线程的id
pthread_t pthread_self(void);pthread_t表示线程的id
pthread_equal比较两个线程是否相等
int pthread_equal(pthread_t t1, pthread_t t2);//相等返回非0值pthread_create创建一个新的线程
线程的创建
pthread_create创建一个新的线程
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);thread线程的id(传入传出参数因为用户不能指定线程的id必须由内核分配)
attr(attribute)线程的属性一般直接填NULL表示默认属性
start_routine(本质函数指针返回值(void *) ( * ) (void *))线程的入口函数类似于进程的main函数
void *是通用指针可以转化为其他任意类型的指针
void *在32位系统上占4个字节在64位系统上占8个字节因此void *可以和整型数值与浮点数值进行转换
arg线程入口函数的参数
返回值成功返回0失败非0
pthread_create是新线程先执行还是旧线程先执行是不确定的(类比fork是竞态条件的滋生地) 线程的终止
(1)线程的入口函数返回返回值为线程的退出码
(2)线程可以被同进程中的其他线程取消pthread_cancel
int pthread_cancel(pthread_t thread);(3)线程自己调用pthread_exit(只会导致线程退出)(其中参数retval为线程的退出码)
void pthread_exit(void *retval);互斥锁mutex
(保护共享资源避免出现数据不一致的现象)
mutual exclusive
类型pthread_mutex_t(互斥锁)
一、pthread_mutex_init与pthread_mutex_destory销毁与初始化
pthread_mutex_init初始化锁
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);//动态初始化pthread_mutex_t mutex PTHREAD_MUTEX_INITIALIZER;//静态初始化pthread_mutex_destory销毁锁得到未初始化的锁
int pthread_mutex_destroy(pthread_mutex_t *mutex);(1)如果锁是静态变量可以采用静态方式进行初始化
(2)如果锁变量位于堆空间是动态申请的采用动态的方式初始化
(d)
pthread_join线程会一直阻塞等待目标线程终止(thread)目标线程终止时会将退出码放入retval所指的位置
int pthread_join(pthread_t thread, void **retval);//线程退出的值会保留在retval所指的位置12、线程的清理函数什么时候会执行什么时候不会执行
pthread_cleanup_push 负责将清理函数压入一个栈中这个栈会在下列情况下弹出 线程因为取消而终止时所有清理函数按照后进先出的顺序从栈中弹出并执行。 线程调用 pthread_exit 而主动终止时所有清理函数按照后进先出的顺序从栈中弹出并执行。 线程调用 pthread_clean_pop 并且 execute 参数非0时弹出栈顶的清理函数并执行。 线程调用 pthread_clean_pop 并且 execute 参数为0时弹出栈顶的清理函数不执行。
13、 为什么pthread_cleanup_push和pthread_cleanup_pop需要成对出现
POSIX要求 pthread_cleanup_push 和 pthread_cleanup_pop 必须成对出现在同一个作用域当中主 要是为了约束程序员在清理函数当中行为。下面是在 /urs/include/pthread.h 文件当中线程清理函 数的定义 可以发现push和pop的宏定义不是语义完全的它们必须在同一作用域中成对出现才能使花括号成功匹 配。
14、使用条件变量的使用为什么一定要加锁?
阻止其他线程改变条件变量 生产者与消费者问题
其实也就是多个线程的问题但是会涉及到线程之间对共享资源的互斥访问所以需要有互斥锁与条件变量的准备知识接下来我们先看看互斥锁与条件变量。 互斥锁
在多线程编程中用来控制共享资源的最简单有效也是最广泛使用的机制就是 mutex(MUTual
EXclusion) 即互斥锁
条件变量
理论上来说利用互斥锁可以解决所有的同步问题但是生产实践之中往往会出现这样的问题一个线
程能够执行取决于一个共享资源的具体数值而该共享资源的数值会随着程序的运行不断地变化线程
也经常在可运行和不可运行之间动态切换假如纯粹使用互斥锁来解决问题的话就会出现大量的重复
的“加锁-检查条件不满足-解锁”的行为这样的话不满足条件的线程会经常试图占用CPU资源上下文
切换也会非常频繁。
对于这样依赖于共享资源这种条件来控制线程之间的同步的问题我们希望采用一种无竞争的方式让多
个线程在共享资源处会和——这就是条件变量。条件变量一定要配合锁来使用当A线程持有锁的时
候A可以检查条件是否成立假如条件不成立A可以让自己阻塞并且解锁条件变量保证了陷入阻塞
和解锁是原子的此时锁被释放其他的线程比如B线程可以持有锁有些情况下可以不持有锁去
修改条件的内容一旦B认为现在是一个合适的时机唤醒A时B可以通知到A线程。A线程收到通知之
后会首先恢复运行并加锁再继续执行后续的指令。使用条件变量可以明确A、B线程某些行为之间的
先后顺序以实现同步的效果。
线程池 同一进程下的线程可以共享
线程共享的内容包括
进程代码段进程的公有数据(利用这些共享的数据线程很容易的实现相互之间的通讯)、进程打开的文件描述符、信号的处理器、进程的当前目录和进程用户ID与进程组ID
线程独有的内容包括
线程ID寄存器组的值线程的堆栈错误返回码线程的信号屏蔽码
三、熟悉进程池、线程池的实现。
1、进程池 四、简单了解分布式系统消息队列。 线程池的实现
为什么要有线程池假设没有使用线程池时一个请求用一个子线程来处理。每来一个请求都得创建
子线程子线程执行请求关闭子线程。当请求量并发比较大的时候频繁地创建和关闭子线程
也是有开销的。因此提出线程池提前开辟好N个子线程当有任务过来的时候先放到任务队列中
之后N个子线程从任务队列中获取任务并执行这样能大大提高程序的执行效率。其实当任务数大于
线程池中子线程的数目的时候就需要将任务放到缓冲区队列里面所以本质上还是一个生产者消
费者模型。
oo_threadpool bo_threadpool 交互图 github源代码链接1750252467/ThreadPool (github.com)
5.设计模式: 熟悉单例模式。 源码及详细介绍博客单例模式C_泷fyk的博客-CSDN博客 方式一: 嵌套类 静态对象 方式二: 自动调用destroy方法就可以回收单例对象 方式三: pthead_once atexit就可以回收单例对象有环境限制只能在linux环境下,实现了多线程安全 了解常用的设计模式如工厂模式、观察者模式。 类与类之间的关系—继承(泛化) 基类部分成为派生类的一部分 在语义上A is B 在代码上继承 继承与泛化的区别继承是基类向派生类方向泛化是从派生类向基类方向 类与类之间的关系—关联 关联关系有两种形式 双向的关联关系 单向的关联关系 彼此并不负责对方的生命周期 在语义上A has B关系是固定的 在代码上一般使用指针或者引用 类与类之间的关系—聚合 比较强的一种关联关系 对象之间的关系表现为整体和局部 整体部分并不负责局部对象的销毁 在语义上A has B 在代码上数据成员以指针或者引用形式存在 类与类之间的关系—组合 更强的一种关联关系 对象之间的关系表现为整体和局部 整体部分负责局部对象的销毁 在语义上A has B 在代码上数据成员以子对象成员形式存在 类与类之间的关系—依赖 从语义上来说是 A use B是偶然的临时的并非固定的 在代码上 B作为A的成员函数参数 B作为A的成员函数的局部变量B作为A的成员函数返回值 A的成员函数调用B的静态方法 依赖 关联 聚合 组合 继承 设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结 工厂模式 作用 用于创建复制对象明确地计划不同条件下创建不同的实例。优点 使代码结构清晰能够更加有效的进行封装。对调用者屏蔽具体的产品实现。降低耦合度。缺点 对于简单对象使用工厂模式会增加其系统的复杂度。 代理模式Proxy Pattern【结构型模式】 作用 为其他对象提供一种代理来控制对某个对象的访问在一些已有的方法在使用的时候需要对已有的方法进行拓展可用此模式来完成。优点 职责清晰有更高的拓展性更加的智能。缺点 实现代理模式增加了工作量且通过代理模式访问会使性能降低。 观察者模式Observer Pattern【行为型模式】 作用 用于在易用和低耦合下实现一个对象改变给其他对象通知的功能。 优点 观察者和被观察抽象耦合的。 缺点 当观察者较多时完成通知耗时较长观察者和被观察是循环依赖时会导致循环调用可能会使导致系统崩溃
6.数据库:
掌握Linux下使用MySQL。
1、事务的四大基本特征是什么
原子性事务要么全部不发生要么全部都发生
一致性事务的执行的前后数据的完整性保持一致。且事务执行前后数据的总和不变。
隔离性一个事物内部的操作及使用的数据对并发的其他事务是隔离的并发执行的各个事物之间不能
互相干扰。事务之间是串行执行的。
隔离级别有关系隔离性不能达到100%
持久性指一个事物一旦提交它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障
不应该对其有任何影响2、并发产生的四大基本问题是什么
1、脏写
脏写是指当多个事务并发写同一数据时先执行的事务所写的数据会被后写的数据覆盖
2、脏读
如果一个事务A向数据库写数据但该事务还没提交或终止另一个事务B就看到了事务A写入数据库的
数据这个现象我们称为脏读。
3、不可重复读
一个事务有对同一个数据项的多次读取但是在某前后两次读取之间另一个事务更新该数据项并且
提交了。在后一次读取时感知到了提交的更新
4、幻读
一个事务前后两次读数据的时候凭空多产生了一条此时就像产生幻觉一样称为幻读。T2事务前后
两次进行读操作的过程中T1事务新增了一条数据并且提交了所以对于T2事务而言产生幻读。4、B树和B树的区别
B树结点中既存key值也存value还要存指向孩子结点的指针所以一个B树结点存储key值的数量
是有限的。
B树非叶子结点中存key值不存value还要存指向孩子结点的指针所以一个B树结点存储key值
的数量相对B树而言数据量要大这样树的高度就会降低树的高度就是进行磁盘IO次数。5、什么是最左前缀原则
在组合索引中如果要进行查询的时候一定要出现组合索引中最左边的一列在最左边一列相同情况
下第二列才可能排好序然后在第一列第二列排好序的情况下第三列才能局部有序依次类推。
所以在进行查询的时候如果不出现第一列后面的列是不能保证有序的就用不到索引。所以在查询
的时候一定要出现第一列6、MyISAM与InnoDB各自有什么特点
MyISAM存储引擎
特点a. 查询速度很快b. 支持表锁c. 支持全文索引(正排索引、倒排索引)d. 不支持事务
InnoDB存储引擎
特点a. 支持事务b. 支持行锁和表锁默认支持行锁c. 支持MVCC(多版本并发控制)版本号事务的编号d. 支持崩溃恢复e. 支持外键一致性约束5、MyISAM索引与InnoDB索引的区别
MyISAM存储引擎
MySQL 5.5 之前默认的存储引擎。
特点a. 查询速度很快b. 支持表锁c. 支持全文索引(正排索引、倒排索引)d. 不支持事务
使用 MyISAM 存储表会生成三个文件.
.frm # 存储表结构是任何存储引擎都有的
.myd # 存放数据
.myi # 存放索引
InnoDB存储引擎
MySQL 5.5 以及以后版本默认的存储引擎。没有特殊应用推荐使用InnoDB引擎。
特点a. 支持事务b. 支持行锁和表锁默认支持行锁c. 支持MVCC(多版本并发控制)版本号事务的编号d. 支持崩溃恢复e. 支持外键一致性约束
粒度
使用 InnoDB 存储表会生成两个文件.
.frm # 存储表结构是任何存储引擎都有的
.ibd # 存放数据和索引6、临时表与存储引擎是memory的表有什么区别
临时表创建完成之后默认的存储引擎还是innodb但是show tables看不到表的名字如果将存在临时表的会话关闭那么临时表就会消失不会在存在了。
存储引擎是memory的表创建之后存储引擎明显就不是innodb而是memoryshow tables的时候 是可以看到表的名字的即使将会话关闭存储引擎是memory的表表是不会消失的。断电重启之后表的结构还在但是表中的内容消失了。掌握Navicat操作MySQL。
掌握Redis。 1、 什么是Redis?有哪些有优缺点
Redis(Remote Dictionary Server) 是一个使用 C 语言编写的开源的BSD许可高性能非关系型NoSQL的键值对数据库。
与传统数据库不同的是 Redis 的数据是存在内存中的所以读写速度非常快因此 redis 被广泛应用于缓存方向每秒可以处理超过 10万次读写操作是已知性能最快的Key-Value DB。
数据库容量受到物理内存的限制不能用作海量数据的高性能读写因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上
2、为什么要用 Redis /为什么要用缓存
主要从“高性能”和“高并发”这两点来看待这个问题。
高性能
假如用户第一次访问数据库中的某些数据。这个过程会比较慢因为是从硬盘上读取的。将该用户访问的数据存在数缓存中这样下一次再访问这些数据的时候就可以直接从缓存中获取了。操作缓存就是直接操作内存所以速度相当快。如果数据库中的对应数据改变的之后同步改变缓存中相应的数据即可
高并发
直接操作缓存能够承受的请求是远远大于直接访问数据库的所以我们可以考虑把数据库中的部分数据转移到缓存中去这样用户的一部分请求会直接到缓存这里而不用经过数据库。
3、 Redis为什么这么快
1完全基于内存绝大部分请求是纯粹的内存操作非常快速。数据存在内存中类似于 HashMapHashMap 的优势就是查找和操作的时间复杂度都是O(1)
2数据结构简单对数据操作也简单Redis 中的数据结构是专门进行设计的
3采用单线程避免了不必要的上下文切换和竞争条件也不存在多进程或者多线程导致的切换而消耗 CPU不用去考虑各种锁的问题不存在加锁释放锁操作没有因为可能出现死锁而导致的性能消耗
4使用多路 I/O 复用模型非阻塞 IO
4、Redis有哪些数据类型
Redis相比其他缓存有一个非常大的优势就是支持多种数据类型。Redis主要有5种数据类型包括StringListSetZsetHash虽然Redis不像关系数据库那么复杂的数据结构但是也能适合很多场景比一般的缓存数据结构要多。
5、什么是Redis持久化
持久化就是把内存的数据写到磁盘中去防止服务宕机了内存数据丢失。
6、Redis 的持久化机制是什么各自的优缺点
Redis 提供两种持久化机制 RDB默认 和 AOF 机制:
RDB是Redis DataBase缩写快照
RDB是Redis默认的持久化方式。按照一定的时间将内存的数据以快照的形式保存到硬盘中对应产生的数据文件为dump.rdb。通过配置文件中的save参数来定义快照的周期。
优点
1、只有一个文件 dump.rdb方便持久化。2、容灾性好一个文件可以保存到安全的磁盘。3、性能最大化fork 子进程来完成写操作让主进程继续处理命令所以是 IO 最大化。使用单独子进程来进行持久化主进程不会进行任何 IO 操作保证了 redis 的高性能4.相对于数据集大时比 AOF 的启动效率更高。
缺点
1、数据安全性低。RDB 是间隔一段时间进行持久化如果持久化之间 redis 发生故障会发生数据丢失。所以这种方式更适合数据要求不严谨的时候)2、AOFAppend-only file)持久化方式 是指所有的命令行记录以 redis 命令请 求协议的格式完全持久化存储)保存为 aof 文件。
AOF持久化
AOF持久化(即Append Only File持久化)则是将Redis执行的每次写命令记录到单独的日志文件中当重启Redis会重新将持久化的日志中文件恢复数据。
当两种方式同时开启时数据恢复Redis会优先选择AOF恢复。
优点
1、数据安全aof 持久化可以配置 appendfsync 属性有 always每进行一次 命令操作就记录到 aof 文件中一次。2、通过 append 模式写文件即使中途服务器宕机可以通过 redis-check-aof 工具解决数据一致性问题。3、AOF 机制的 rewrite 模式。AOF 文件没被 rewrite 之前文件过大时会对命令 进行合并重写可以删除其中的某些命令比如误操作的 flushall)
缺点
1、AOF 文件比 RDB 文件大且恢复速度慢。2、数据集大的时候比 rdb 启动效率低。
两者对比
AOF文件比RDB更新频率高优先使用AOF还原数据。AOF比RDB更安全也更大RDB性能比AOF好如果两个都配了优先加载AOF
7、 Redis key的过期时间和永久有效分别怎么设置
EXPIRE和PERSIST命令。
我们知道通过expire来设置key 的过期时间那么对过期的数据怎么处理呢?
除了缓存服务器自带的缓存失效策略之外Redis默认的有6中策略可供选择我们还可以根据具体的业务需求进行自定义的缓存淘汰常见的策略有两种
定时去清理过期的缓存当有用户请求过来时再判断这个请求所用到的缓存是否过期过期的话就去底层系统得到新数据并更新缓存。
两者各有优劣第一种的缺点是维护大量缓存的key是比较麻烦的第二种的缺点就是每次用户请求过来都要判断缓存失效逻辑相对比较复杂具体用哪种方案大家可以根据自己的应用场景来权衡。
8、Redis事务的概念
Redis 事务的本质是通过MULTI、EXEC、WATCH等一组命令的集合。事务支持一次执行多个命令一个事务中所有命令都会被序列化。在事务执行过程会按照顺序串行化执行队列中的命令其他客户端提交的命令请求不会插入到事务执行命令序列中。
总结说redis事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令。
9、Redis事务的三个阶段
事务开始 MULTI命令入队事务执行 EXEC
10、Redis事务相关命令和事务的特征
Redis事务功能是通过MULTI、EXEC、DISCARD和WATCH 四个原语实现的
Redis会将一个事务中的所有命令序列化然后按顺序执行。
redis 不支持回滚“Redis 在事务失败时不进行回滚而是继续执行余下的命令” 所以 Redis 的内部可以保持简单且快速。如果在一个事务中的命令编译出现错误那么所有的命令都不会执行如果在一个事务中出现运行错误那么正确的命令会被执行。
WATCH 命令是一个乐观锁可以为 Redis 事务提供 check-and-set CAS行为。 可以监控一个或多个键一旦其中有一个键被修改或删除之后的事务就不会执行监控一直持续到EXEC命令。MULTI命令用于开启一个事务它总是返回OK。 MULTI执行之后客户端可以继续向服务器发送任意多条命令这些命令不会立即被执行而是被放到一个队列中当EXEC命令被调用时所有队列中的命令才会被执行。EXEC执行所有事务块内的命令。返回事务块内所有命令的返回值按命令执行的先后顺序排列。 当操作被打断时返回空值 nil 。通过调用DISCARD客户端可以清空事务队列并放弃执行事务 并且客户端会从事务状态中退出。UNWATCH命令可以取消watch对所有key的监控。
11、缓存穿透是什么如何解决
缓存穿透是指缓存和数据库中都没有的数据导致所有的请求都落到数据库上造成数据库短时间内承受大量请求而崩掉。
解决方案
接口层增加校验如用户鉴权校验id做基础校验id0的直接拦截从缓存取不到的数据在数据库中也没有取到这时也可以将key-value对写为key-null缓存有效时间可以设置短点如30秒设置太长会导致正常情况也没法使用。这样可以防止攻击用户反复用同一个id暴力攻击采用布隆过滤器将所有可能存在的数据哈希到一个足够大的 bitmap 中一个一定不存在的数据会被这个 bitmap 拦截掉从而避免了对底层存储系统的查询压力
12、缓存击穿是什么有什么解决方案
缓存击穿是指缓存中没有但数据库中有的数据一般是缓存时间到期这时由于并发用户特别多同时读缓存没读到数据又同时去数据库去取数据引起数据库压力瞬间增大造成过大压力。和缓存雪崩不同的是缓存击穿指并发查同一条数据缓存雪崩是不同数据都过期了很多数据都查不到从而查数据库。
解决方案
设置热点数据永远不过期。利用互斥锁保证同一时刻只有一个客户端可以查询底层数据库的这个数据一旦查到数据就缓存至Redis内避免其他大量请求同时穿过Redis访问底层数据库。
13、缓存雪崩的概念如何应对
缓存雪崩是指缓存同一时间大面积的失效所以后面的请求都会落到数据库上造成数据库短时间内承受大量请求而崩掉。
解决方案 缓存数据的过期时间设置随机防止同一时间大量数据过期现象发生。 一般并发量不是特别多的时候使用最多的解决方案是加锁排队。
7.常用工具 熟悉Windows下的Visual Studio/VS Code。 F5 开始使用调试器运行程序F9 在当前行设置断点F10 运行到下一个断点处F5 从被调试的已停止程序恢复执行F11 步进到函数内如果当前程序指针指向一个函数F10 步过函数如果当前程序指针指向一个函数ShiftF11 步出执行的函数 掌握源码阅读工具SlickEdit;熟悉Linux下Vim编辑器GNU GCC工具链gcc/g/gdb/cgdb。 掌握makefile文件的编写Git等版本控制系统。 makefile: 目标依赖 命令 内置函数 git: 进入到工作目录 git status 查看状态。 git pull 写文件 git add 文件名 git commit -m “代码提交信息” 到HEAD中 git push 创建一个叫做feature_x的分支并切换过去 git checkout -b feature_x 切换回主分支 git checkout master 再把新建的分支删掉 git branch -d feature_x 除非你将分支推送到远端仓库不然该分支就是 不为他人所见的 git push origin branch git commit --amend 好用减少提交无用信息可常用。 git reset --soft HEAD 回退差异存在暂存区也好用不轻易删除代码。 git reset --hard HEAD 回退删除 慎用一不小心删除代码还不可逆。 git reset HEAD || git reset --mixed HEAD 回退改变的差异在工作区。
cgdb
调试命令 (缩写)作用(gdb) break (b)在源代码指定的某一行设置断点其中xxx用于指定具体打断点位置(gdb) run (r执行被调试的程序其会自动在第一个断点处暂停执行。(gdb) continue (c当程序在某一断点处停止后用该指令可以继续执行直至遇到断点或者程序结束。(gdb) next (n)令程序一行代码一行代码的执行。(gdb) steps如果有调用函数进入调用的函数内部否则和 next 命令的功能一样。(gdb) until (u) (gdb) until (u) location当你厌倦了在一个循环体内单步跟踪时单纯使用 until 命令可以运行程序直到退出循环体。 until n 命令中n 为某一行代码的行号该命令会使程序运行至第 n 行代码处停止。(gdb) print (p打印指定变量的值其中 xxx 指的就是某一变量名。(gdb) list (l)显示源程序代码的内容包括各行代码所在的行号。(gdb) finishfi结束当前正在执行的函数并在跳出函数后暂停程序的执行。(gdb) returnreturn结束当前调用函数并返回指定值到上一层函数调用处停止程序执行。(gdb) jumpj)使程序从当前要执行的代码处直接跳转到指定位置处继续执行后续的代码。(gdb) quit (q)终止调试。
使用过阿里云的OSS对象存储备份文件并使用阿里云作为markdown的图床发布博客文章。
面试雷区
一、“我没有其他问题要问了…”❌
每当求职者面试即将结束时面试官一般都会问道你还有什么问题要问我们的吗
漂亮的回答会给予面试官一种你认真准备面试的感觉另外还可以考察你对本工作岗位的意向程度如果屏幕前的你是有心人的话是肯定的不会没问题的~~~
建议话术✔
提前围绕该岗位的未来发展、主要职责或工作内容、公司氛围、具体项目等准备问题…
仅供参考****
1、请问如果我能顺利入职的话主要负责的业务是哪块呢主要的工作内容是怎样的呢
2、请问贵部门的员工配置是怎样的呢有多少员工呢
3、我的个人职业规划大概是这样的…请问您觉得当下我该如何做可以更好的适应入职的节奏或工作内容呢
二、“期望薪资方面我没有什么想法…”❌
一个对薪资没有要求与想法的员工是很可怕的上班就是为了赚钱为了提高生活水平你连薪资都没有要求难道让领导靠感情来管理维系你吗
这种回答会给HR一种不上进没追求的感觉或者就是心浮气躁并没有对本次面试上心只是一个匆匆体验客…
建议话术✔
提前调查该城市该行业该岗位的平均薪资水平进而结合个人实习经历或自身能力进一步谈。中心思想自身价值个人追求
仅供参考
您好我在上家公司实习/工作的时候到手的薪资是xxx结合我的工作经验和个人诉求我的期望薪资是xxx根据目前的行业前景和市场行情我觉得我的要求是合适的以上就是我个人的薪资期望您这边觉得怎样呢
三、“我对该岗位没有什么经验但我会认真去学习哒…”❌
不要带着所谓的“学生思维”去表达自己的想法公司不是学校公司招人是需要你来创造价值的你需要尽可能表现出自己的外在价值或潜在价值。
建议话术✔
作为一名应届毕业生虽然我没有相关的经验但是之前有接触过这方面的内容此处可以举个栗子对xxx也有过比较深入的了解和熟悉本岗位的主要工作内容我也在本领域的师兄/师姐/朋友那了解过还是比较熟悉的。
另外公司在xxx方面的发展和成绩我也很感兴趣十分期待自己能够顺利加入这个团队贡献自己的一份力量
github
1750252467/ThreadPool (github.com)