面试知识点

文章目录

c++

i++是不是原子操作

  • 1.i++分为三个阶段:
    内存到寄存器
    寄存器自增
    写回内存
    这三个阶段中间都可以被中断分离开. 不是原则操作

构造函数,析构函数,调用虚函数的问题

(1)不要在构造函数中调用虚函数的原因:因为父类对象会在子类之前进行构造,此时子类部分的数据成员还未初始化, 因此调用子类的虚函数是不安全的,故而C++不会进行动态联编。
(2)不要在析构函数中调用虚函数的原因:析构函数是用来销毁一个对象的,在销毁一个对象时,先调用子类的析构函数,然后再调用基类的析构函数。所以在调用基类的析构函数时,派生类对象的数据成员已经“销毁”,这个时再调用子类的虚函数已经没有意义了。

元编程 and type_trait

模板元编程是一种元编程技术,编译器使用模板产生暂时性的源码,然后再和剩下的源码混合并编译。这些模板的输出包括编译时期常量、数据结构以及完整的函数。如此利用模板可以被想成编译期的运行。

std::forward 的作用

“std::forward通常是用于完美转发的,它会将输入的参数原封不动地传递到下一个函数中,这个“原封不动”指的是,如果输入的参数是左值,那么传递给下一个函数的参数的也是左值;如果输入的参数是右值,那么传递给下一个函数的参数的也是右值。

C语言中可变参数的实现原理

网络协议栈的理解

enable_shared_from_this

https://blog.csdn.net/QIANGWEIYUAN/article/details/88973735

多个进程共享一个epollfd 会有什么问题

先来看看什么是“惊群”?简单说来,多线程/多进程(linux下线程进程也没多大区别)等待同一个socket事件,当这个事件发生时,这些线程/进程被同时唤醒,就是惊群。可以想见,效率很低下,许多进程被内核重新调度唤醒,同时去响应这一个事件,当然只有一个进程能处理事件成功,其他的进程在处理该事件失败后重新休眠(也有其他选择)。这种性能浪费现象就是惊群。

半/全连接攻击

https://blog.csdn.net/qq_26105397/article/details/81088188

cdn原理

https://blog.csdn.net/xiangzhihong8/article/details/83147542

eventfd,timerfd,signalfd

三种新的fd都可以进行监听,当有事件触发时,有可读事件发生。,抽象成文件描述符,都可以用,select,poll,
epoll监听

Linux相关

1.命令相关

1. netstat 显示各种网络相关的信息(网络连接状态,路由表,端口占用等)

netstat -a 列出所有端口
netstat -an | grep ssh
netstat -n | grep tcp | grep 侦听端口 | wc -l
netstat -an | grep TIME_WAIT | wc -l
netstat -p 显示正在使用Socket的程序识别码和程序名称。
-l 或–listening 显示监控中的服务器的Socket

2. tcpdump网络抓包

tcpdump -i eth1 指定监视某一个网卡的数据包
tcpdump host 210.27.48.1截获所有的210.27.48.1的主机收到和发送的包
tcpdump  tcp  port 22 /udp 43 and host ip 捕获对应ip的tcp,udp包

3. ipcs IPCS命令是Linux下显示进程间通信设施状态的工具

  ipcs -a 显示所有IPC设施
  ipcs -q 显示所有消息队列  (msgget(),msgctl(),msgsend(),msgrcv())
  ipcs -s 显示所有信号量      (sem,sem_open,sem_close,sem_init)
  ipcs -m 显示所有共享内存  (shm_open)
  ps -ef | grep test 查看进程id

4. ipcrm 删除一个或者多个消息队列,信号量,共享内存

5. vmstat 虚拟内存性能监控、CPU监控(进程上下文切换、CPU利用率)

6. top 系统负载、CPU使用率、各个进程的详细报告(CPU使用率、内存使用情况)等

7. free 相对于top使用比较简单,占用系统资源少(mem,swap)

8. 查看某个进程的文件描述符以及打开的文件。

 ps -ux  查看进程的id
 lsof -p 14300 查看某个进程的文件描述符
 ll /proc/111/fd

9. 查看cpu,内存信息

 cat /proc/cpuinfo
 cat /proc/meminfo

10. df -lh 查看硬盘的信息

11. [ ] awk sed grep

   sed 3d a.txt 删除第3行的内容

12. 网络字节序

   网络字节序转换的操作函数有这几个 ntohs() 、htons() 、 ntohl() 、htonl() 
  int check_sys()//强制类型转换为char类型,如果输出1就是小端,否则是大端

{
int a = 1;
//返回1表示小端
//返回0表示大端
return ((char)&a);
}
int check_sys()//使用联合体访问他们共同的地址部分
{
union Un
{
char c;
int i;
}u;
u.i = 1;
return u.c;
}

13. gdb调试(多进程)

   info inferiors 列出被调试的inferior
   inferiors <pid> 切换至指定的inferior
   gdb(多线程)
   info thread 查看当前线程
   thread id 切换至指定的id线程
   break file.c:100 thread all 在文件file.c 100处经过这里的所有线程设置断点
   pstree -p <pid>  查看线程结构
   bt 查看线程栈结构
   ps stack 查看栈结构
   set scheduler-locking off/on 不锁任何线程,都运行/只运行当前线程

14. 搜寻字符串

   grep ‘搜寻字符串’ filename

15. tail 查看当前用户允许打开的文件数

    tail -f a.out 实时查看日志信息
    tail -f - n 100查看后100行

16.查看文件的命令

Linux查看文件命令
linux查看日志文件内容命令有
cat 由第一行开始显示文件内容
tac 从最后一行开始显示,可以看出 tac 是 cat 的倒着写
nl 显示的时候,顺道输出行号!
more 一页一页的显示文件内容
less 与 more 类似,但是比 more 更好的是,他可以往前翻页!
head 只看头几行
tail 只看尾巴几行
你可以使用 man [命令]来查看各个命令的使用文档,如 :man cp。
https://www.cnblogs.com/yangliguo/p/8463131.html

17. linux中buffer和cache的区别

http://blog.chinaunix.net/uid-24020646-id-2939696.html

18.怎么看文件夹所有文件大小

  • 最简单的查看方法可以使用ls -ll、ls-lh命令进行查看,当使用ls -ll,会显示成字节大小,而ls- lh会以KB、MB等为单位进行显示,这样比较直观一些。
  • 通过命令du -h –max-depth=1 *,可以查看当前目录下各文件、文件夹的大小,这个比较实用。
  • 查询当前目录总大小可以使用du -sh,其中s代表统计汇总的意思,即只输出一个总和大小。

19.top里面,内存那有buffer/cache

  • 今天用top查看系统具体进程使用系统资源的情况时,对cache和buffer这两个概念不是很清楚,研究了一下:
    cache是高速缓存,用于CPU和内存之间的缓冲 buffer是I/O缓存,用于内存和硬盘的缓冲*

20.如果rm了正在读写的文件,会发生什么?

  • 当用户执行 rm 操作后,ls 或者其他文件管理命令不再能够找到这个文件,但是进程却依然在继续正常执行,依然能够从文件中正确的读取内容。这是因为,rm 操作只是将 i_nlink 置为 0 了;由于文件被进程引用的缘故,i_count 不为 0,所以系统没有真正删除这个文件。i_nlink 是文件删除的充分条件,而 i_count 才是文件删除的必要条件。

21.mv一个文件到另一个地方,是真实的把整个文件移动过去吗?

  • Linux中命令——cp、mv、rm对inode的影响

22.lsof

  • 每行显示一个打开的文件,若不指定条件默认将显示所有进程打开的所有文件。
    lsof输出各列信息的意义如下:
    COMMAND:进程的名称 PID:进程标识符
    USER:进程所有者
    FD:文件描述符,应用程序通过文件描述符识别该文件。如cwd、txt等 TYPE:文件类型,如DIR、REG等
    DEVICE:指定磁盘的名称
    SIZE:文件的大小
    NODE:索引节点(文件在磁盘上的标识)
    NAME:打开文件的确切名称

23.高并发网络编程之epoll

https://blog.csdn.net/u012206617/article/details/89260676

24.http如何使用缓存的

  • 浏览器是如何知道使用缓存的,其实这都是通过http中,浏览器将最后修改时间发送请求给web服务器,web服务器收到请求后跟服务器上的文档最后修改的时间对比(expires),如果web服务器上最新文档修改时间小于或者等于浏览器发送过来的,则发送304给浏览器,使用缓存版本。

25.怎么看网卡流量

  • sar -n dev 1

26.通过域名查ip

  • 1、dig +short blog.csdn.net
  • 2、host blog.csdn.net
  • 3、nslookup blog.csdn.net
  • 4、ping blog.csdn.net

27.怎么看打开这个文件是哪一个进程

  • 可以使bai用:ps -fe|grep filename,
    也可以使用:fuser filename查看
    然后可以看这个进程du跟哪里东西zhi有关联,使用了哪些端口
    只查看该进程:ps -ef | grep ID
    查看该进程打开的文件:lsof -p ID
    查看内存分配:lcat /proc/ID/maps
    查看堆栈:pstack 11ID
    查看发出的系统调用:strace -p ID
    查看调用库函数:ltrace -p ID

28.shell命令的返回值

  • shell 函数的返回值bai $?:

29.看某个端口被哪个程序占用

  • 查看某个端口被哪个程序占用
    netstat -anp |grep 端口号
    查看进程号对应的程序
    ps -ef | grep 17997
    查看指定端口号的进程情况
    netstat -tunlp
  • 使用lsof

30.守护进程创建

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>
#include<stdlib.h>
#include<signal.h>
#include<sys/time.h>
#include<time.h>
#define _FILE_NAME_PREFIX_ "%s/log/mydaemon.%ld"

void touchfile(int num)
{
    char * HomeDir = getenv("HOME")'
    char strFileName[256] = {0};
    sprintf(strFileName,_FILE_NAME_PREFIX_ ,HomeDir,time(NULL));
    int fd = open(strFileName,O_RDWR | O_CREAT,0666);
    if(fd < 0)
    {
      perrr("open dir");
      exit(1);
    }
    close(fd);
}


int main()
{
   //创建可子进程,父进程退出
   pid_t pid = fork();
   if(pid > 0){
      exit(1);
   }
   //当会长
   setsid();
   //设置掩码
   umask(0); //给所有权限
   // 切换目录
   chdir(getenv("HOME")); //切换到家目录;
   // 关闭文件描述符
   //close(1),close(2),close(0);
   //执行核心逻辑
   struct itimerval myit = {{60,0},{1,0}};
   setitimer(ITIMER_REAL, & myit,NULL);
   struct sigaction act;
   act.sa_flags = 0;
   sigemptyset(&act.sa_mask);
   act.sa_handler = touchfile;
   sigaction(SIGALRM,&act,NULL);
   while(1){
       //每隔一分钟在/home/itheima/log 下创建文件
       sleep(60);
   }
   //退出
   
   return 0;
}


数据结构 stl

1. vector 内部成员变量
a.数组数据的头start
b.数组数据的尾 finish
c.数组容量的尾
当size()>capacity() 扩容 ,重新申请空间并拷贝(一般是2倍)
默认初始容量是10
线程安全
底层数据结构是数组结构

2. HashSet:线程不安全,存取速度快
 底层实现是一个HashMap(保存数据),实现Set接口
默认初始容量为16(为何是16,见下方对HashMap的描述)
加载因子为0.75:即当 元素个数 超过 容量长度的0.75倍 时,进行扩容
扩容增量:原容量的 1 倍
如 HashSet的容量为16,一次扩容后是容量为32

3. HashMap:默认初始容量为16
(为何是16:16是2^4,可以提高查询效率,另外,32=16<<1 -->至于详细的原因可另行分析,或分析源代码)
加载因子为0.75:即当 元素个数 超过 容量长度的0.75倍 时,进行扩容
扩容增量:原容量的 1 倍
如 HashSet的容量为16,一次扩容后是容量为32

4. hash https://www.cnblogs.com/meihao1203/p/9277399.html

 散列技术是在记录的存储位置和它的关键字之间建立一个确定的对应关系f,使得每个关键字key对应一个存储位置f(key),adr = f(key)。查找时,根据这个确定的对应关系找到给定值key的映射f(key),若查找集合中存在这个记录,则必定在f(key)的位置上。
采用散列技术将记录存储在一块连续的存储空间中,这块连续的存储空间称为散列表或哈希表(Hash table)。关键字对应的记录存储位置称为散列地址。

直接定址法 f(key) = a * key + b(a、b为常数)
除留余数法
  此方法为最常用的构造散列函数的方法。对于散列表长为m的散列函数公式为:f(key) = key mod p(p≤m)
平方取中法
  计算关键字的平方,再取中间几位做为关键字。eg:1234,平方1522756,取中间3为227为关键字。(平方取中法比较适合不知道关键字的分布,而位数又不是很大的情况。)
解决哈希冲突办法:开放地址法(线性探测,二次探测),拉链法

操作系统

1. 伙伴算法:防止外部内存碎片,但是会造成内部碎片

2. 常见的进程调度算法

 a.先来先服务调度
       不可剥夺,适合cpu繁忙型,不适合io繁忙型
 b.时间片轮转调度
 c.短作业优先调度 (长时间进程处于饥饿状态)
 d.高响应比优先调度
     R = (W+S)/S  R为响应比,w为等待处理时间,s为预计服务时间
  e.优先级调度
     非剥夺优先级,剥夺优先级
     静态优先级,动态优先级
   f.多级反馈队列调度算法
      设置多个就绪队列,并为各个队列赋予不同的优先级,第一级队列的优先级最高,第二级其次,其余的优先级逐次降低。
      赋予各个队列中进程执行时间片的大小也不同,在优先级队列高的队列中,每个进程的运行时间就越小。  当一个新进程进入内存后,首先将他放入第1级的末尾,按FCFS原则排队等待调度。当轮到该进程执行时,如果他在一个时间片结束时尚未完成,调度程勋便将该进程转入第2级队列的末尾。

3. 页置换算法

 a.最优算法
 b .先进先出算法
 c.第二次机会算法
 d.时钟轮转法
 e.LRU算法,最近最少使用

4. 多进程与多线程的区别

 从多个方面来介绍
 a.内存,cpu调度:进程占用内存多,切换复杂,cpu利用率低,
     线程占用内存少,切换简单,cpu利用率高,上下文切换快
     (进程管理内容:cpu,寄存器,io,内存,网络资源,进程控制块。。。线程管理着线程id,寄存器,堆栈)
 b.数据共享,同步: 进程的数据共享复杂,需要进程间的通信
                                 线程共享进程数据,共享简单,但是同步复杂(需要对临界区枷锁)
  c.创建销毁,切换复杂
  d.可靠性  进程间互不影响  一个线程挂了导致整个进程挂掉

5. 协程不是被操作系统内核所管理的,而是完全由程序所控制,也就是在用户态执行。

这样带来的好处是性能大幅度的提升,因为不会像线程切换那样消耗资源。
 
协程既不是进程也不是线程,协程仅仅是一个特殊的函数,协程它进程和进程不是一个维度的。
一个进程可以包含多个线程,一个线程可以包含多个协程。
一个线程内的多个协程虽然可以切换,但是多个协程是串行执行的,只能在一个线程内运行,没法利用CPU多核能力。
进程的切换者是操作系统,切换时机是根据操作系统自己的切换策略,用户是无感知的
线程的切换者是操作系统,切换时机是根据操作系统自己的切换策略,用户无感
协程的切换者是用户(编程者或应用程序),切换时机是用户自己的程序所决定的。
协程的切换内容是硬件上下文,切换内存保存在用户自己的变量(用户栈或堆)中。协程的切换过程只有用户态,即没有陷入内核态,因此切换效率高。

5. 什么是死锁和如何解决死锁

两个进程A和B,A持有a资源,B持有b资源,A在等待b资源,B在等待a资源,两个进程都在等待其他资源的同时不释放资源,导致死锁
四个必要条件:
a.互斥条件:每个资源只能被一个进程使用。
b.请求与保持条件:一个进程请求资源而阻塞时,保持资源不释放
c.不可剥夺条件
d.循环等待条件:若干进程形成首尾相接的循环等待条件。
预防死锁:
破坏请求保持条件:1,一次性申请所有资源 2.只在初期资源向运行,运行完释放
破坏不可剥夺条件:进程获得某种不可抢占的资源,提出新的资源申请,若不能得到,释放所有资源,再重新申请
破坏循环等待条件:对资源进行排号,按照序号递增的顺序请求资源,若进程获得高资源,想要获取序号低资源,需要先释放高资源。

死锁的解除办法:
抢占资源。从一个或多个进程中抢占足够数量的资源,分配给死锁进程
终止进程:打破环路从死锁中解脱。

互斥锁与读写锁,自旋锁,条件锁

网络安全

1. sql注入

  可以执行恶意SQL语句。它通过将任意SQL代码插入数据库查询,使 攻击者能够完全控制Web应用程序后面的数据库服务器。
  如何防止SQL注入攻击?
  不要使用动态SQL : 避免将用户提供的输入直接放入SQL语句中;最好使用准备好的语句和参数化查询,这样更安全。
  不要将敏感数据保留在纯文本中 : 加密存储在数据库中的私有/机密数据;这样可以提供了另一级保护,以防攻击者成功地排出敏感数据。
  限制数据库权限和特权 : 将数据库用户的功能设置为最低要求;这将限制攻击者在设法获取访问权限时可以执行的操作。
   避免直接向用户显示数据库错误 ;攻击者可以使用这些错误消息来获取有关数据库的信息。
  对访问数据库的Web应用程序使用Web应用程序防火墙(WAF) :这为面向Web的应用程序提供了保护,它可以帮助识别SQL注入尝试;
  定期测试与数据库交互的Web应用程序 : 这样做可以帮助捕获可能允许SQL注入的新错误或回归。

2. XSS漏洞(跨站脚本攻击)

  跨站脚本攻击是指恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的。
    xss漏洞通常是通过php的输出函数将javascript代码输出到html页面中,通过用户本地浏览器执行
      第一、XSS反射型攻击,恶意代码并没有保存在目标网站,通过引诱用户点击一个链接到目标网站的恶意链接来实施攻击的。
      第二、XSS存储型攻击,恶意代码被保存到目标网站的服务器中,这种攻击具有较强的稳定性和持久性,比较常见场景是在博客,论坛等社交网站上,但OA系统,和CRM系统上也能看到它身影,比如:某CRM系统的客户投诉功能上存在XSS存储型漏洞,黑客提交了恶意攻击代码,当系统管理员查看投诉信息时恶意代码执行,窃取了客户的资料,然而管理员毫不知情,这就是典型的XSS存储型攻击。
  xss攻击能做什么:
          第一,窃取cookies,读取目标网站的cookie发送到黑客的服务器上,如下面的代码:
         第二,读取用户未公开的资料,如果:邮件列表或者内容、系统的客户资料,联系人列表等等,如代码:
  解决办法:

一种方法是在表单提交或者url参数传递前,对需要的参数进行过滤,请看如下XSS过滤工具类代码,对特殊字符进行过滤。

3.csrf攻击(跨站请求攻击)

  攻击者盗用了你的身份,以你的名义发送恶意请求,对服务器来说这个请求是完全合法的,但是却完成了攻击者所期望的一个操作,比如以你的名义发送邮件、发送
   步骤: CSRF攻击攻击原理及过程如下:
   1. 用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;
   2.在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;
   2. 用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;
   3. 网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;
     解决办法:目前防御 CSRF 攻击主要有三种策略:验证 HTTP Referer 字段;在请求地址中添加 token 并验证;在 HTTP 头中自定义属性并验证。

3. dos 攻击

a.SYN泛滥
     攻击者将其自身的源地址伪装成一个私有地址向本地系统的TCP服务发起连接请求,本地TCP服务回复一个SYN-ACK作为响应,然而该响应发往的地址并非攻击者的地址(真实地址),而是攻击者伪装的私有地址。由于该私有地址是不存在的于本地服务器所在的网络的,所有本地系统将收不到RST消息(以结束这个半打开连接)。本地TCP服务接下来要等待接收一个ACK回应,但是该回应永远不会到来,该半打开连接会保持打开状态直至连接尝试超时,因此有限的连接资源被消耗了
     Linux操作系统中的SYN cookie模块能显著的延缓SYN泛洪造成的网络资源缺失现象:在TCP服务接收到TCP SYN包并返回SYN-ACK时,不分配一个专门的数据区,而是根据这个SYN包计算一个cookie值。cookie值是一个基于SYN中的原始序列号、源地址、目的地址、端口号、密值而产生的序列号。cookie作为将要返回的SYN-ACK的初始序列号,当客户返回一个ACK包,TCP服务在根据cookie值检查该ACK包的合法性,再分配专门的数据区进行处理接下来操作。cookie的超时时间很短暂,客户端必须在很短时间内进行应答
   解决办法2:中间一个中间层,防火墙,先跟防火墙连,防火墙再跟服务器连
b.ping 泛洪
  攻击者通过ping发送的ICMP的echo请求消息也是常见的DoS攻击方式之一,其原理是强制让系统消耗大多数时间进行无用的应答,降低系统网络质量
  **c UDP泛洪**

不同于TCP,UDP是无状态的,没有任何信息被维护以指明下一个期望到来的数据包,所以UDP服务更易受这些类型攻击的影响,许多站点都禁止用所有非必要的UDP端口。
4. arp攻击
最理想的防制方法是网上内的每台计算机的ARP一律改用静态的方式,不过这在大型的网上是不可行的,因为需要经常更新每台计算机的ARP表。
另外一种方法,例如DHCP snooping,网上设备可借由DHCP保留网上上各计算机的MAC地址,在伪造的ARP数据包发出时即可侦测到。

数据库

1. 数据库攻击,怎么应对,dos攻击,sql注入

    ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200714112030950.png)

在这里插入图片描述

2. 数据库锁的类型

 Myisam与Innodb的区别
1)**.MyISAM存储引擎的特点**是:表级锁(不支持行级锁)、不支持事务和支持全文索引,适合一些CMS内容管理系统作为后台数据库使用,但是使用大并发、重负荷生产系统上,表锁结构的特性就显得力不从心;

2).InnoDB存储引擎的特点是:行级锁(也支持表级锁)、事务安全(ACID兼容)、支持外键、不支持FULLTEXT类型的索引(5.6.4以后版本开始支持FULLTEXT类型的索引)。InnoDB存储引擎提供了具有提交、回滚和崩溃恢复能力的事务安全存储引擎。InnoDB是为处理巨大量时拥有最大性能而设计的。它的CPU效率可能是任何其他基于磁盘的关系数据库引擎所不能匹敌的。
表级锁: 开销小,加锁快;不会出现死锁(因为MyISAM会一次性获得SQL所需的全部锁);锁定粒度大,发生锁冲突的概率最高,并发度最低。,MySQL的表级锁有两种模式: 表共享读锁(Table Read Lock)和表独占写锁(Table Write Lock)。
行级锁: 开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。行级锁有共享锁(S)和排他锁(X)

锁的分类

按锁的粒度分:表级锁,行级锁,页级锁
按锁级别划分:共享锁,排他锁(读锁、写锁)
共享锁(S锁):
用于不更改或不更新数据的操作(只读操作),如 SELECT 语句。
事务对数据A加上共享锁后,其他事务只能对A再加共享锁,不能加排他锁。获准共享锁的事务只能读数据,不能修改数据
排他锁(X锁):
用于数据修改操作,例如 INSERT、UPDATE 或 DELETE。确保不会同时同一资源进行多重更新。
按加锁方式划分:自动锁,显式锁
按操作划分:DML锁,DDL锁
DML锁用于确保一次只有一个人能修改一行,而且这时别人不能删除这个表
DDL操作中会自动为对象加DDL锁(DDL Lock),从而保护这些对象不会被其他会话所修改

按使用方式划分:乐观锁,悲观锁

乐观锁
每次去拿数据的时候都认为别人不会修改,故不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据
示例:版本号或时间戳控制
适用范围:适用于多读少写的场景
悲观锁
每次去拿数据的时候都认为别人会修改,故每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁
实例:DB的行锁、表锁等
适用范围:适用于数据一致性比较高的场景

3. 死锁如何防范

  1. 什么是死锁
    死锁是指多个进程因竞争资源而造成的一种僵局,若无外力作用,这些进程都将无法向前推进。

  2. 死锁产生的原因
    a.系统资源的竞争
    b.进程运行顺讯不合适
    请求和释放资源的顺序不当,会导致死锁

  3. 死锁的四个必要条件
    a.互斥条件:一个资源每次只能被一个进程使用,其他资源只能等待
    b.请求与保持条件:进程已经保持了至少一个资源,又提出新的资源请求,而这个资源又被其他进程所占有
    c.不可剥夺条件:资源在没使用完成之前,不能被其他进程强行夺走
    d.循环等待:若干进程形成首尾循环等待

  4. 死锁的避免与预防
    a. 思想:系统对进程发出的每一个系统资源申请进行动态检查,根据检查结果来确定是否分配资源,如果分配发生死锁则不分配,否则予以分配。

  5. 死锁预防
    破坏死锁的4个必要条件来预防死锁。

4. 数据库索引失效

什么时候没用
1.有or必全有索引;
2.复合索引未用左列字段;
3.like以%开头;
4.需要类型转换;
5.where中索引列有运算;
6.where中索引列使用了函数;
7.如果mysql觉得全表扫描更快时(数据少);

什么时没必要用
1.唯一性差;
2.频繁更新的字段不用(更新索引消耗);
3.where中不用的字段;
4.索引使用<>时,效果一般;

5. 数据库删除语句,drop,truncate,delete

https://www.cnblogs.com/ysy-love/p/10696825.html

6. 事务的特性

 四大特性https://www.cnblogs.com/dwxt/p/8807981.html

7.数据库索引为什么不用hash,用B+

1.hash 表只能匹配相等,不能实现范围查找
select * from xx where id > 23 就不行了
2.当需要按照索引order by 时。hash值没有办法支持排序
select * from xx order by score desc 如果score 建立索引字段,hash没法辅助排序
3.组合索引可以支持部分索引查询,(a,b,c)组合索引将几个字合并hash,没办法支持部分索引。
4.当数据量很大时,hash冲突的概率也会很大。

计算机网络

5. HTTP1.0和HTTP1.1的区别

  HTTP1.1可以使用长连接模式,头部使用connection: keep_alive
  HTTP2与HTTP1.1的区别
  a.HTTP2使用二进制代替HTTP1.0和HTTP1.1文本传输
  b.HTTP2使用多路复用机制,也就是创建一条连接可以被多个客户端并行使用,而不是阻塞式的有序等待
  **c.使用报头压缩,HTTP/2降低了开销**
  http请求和响应都是由【状态行、请求/响应头部、消息主题】三部分组成的。 一般而言,消息主体都会经过gzip压缩。
  随着web功能越来越复杂,请求数量越来越多,随之而来的就是头部的流量越来越多,并且在建立初次链接之后的链接也要发送user-agent等信息,是在是一种浪费。
  HTTP 2.0在客户端和服务端之间使用“**首部表”**来跟踪和存储之前发送的键-值对。首部表在连接过程中始终存在,新增的键-值对会更新到表尾,因此,不需要每次通信都需要再携带首部。 
  d.HTTP/2让服务器可以将响应主动“推送”到客户端缓存中
  通过在应用生成HTTP 回应的头信息中设置Link命令(推荐),服务器在收到包含Link的头信息时,就会进行推送,例如:

6. 浏览器输入url发生了什么 https://www.cnblogs.com/yuanzhiguo/p/8119470.html

1、输入网址
2、游览器查找域名的IP地址
a.从/etc/hosts里找
b.hosts里没有从本地DNS服务器找(一般由网络接入服务商提供),比如中国电信,移动
c.根服务器,顶级服务器(递归,迭代的找)
d.找到后不仅返回给电脑,并加入到缓存中,以便下次
3.建立tcp连接
在拿到域名对应的IP地址后,会以随机端口(1024~~65535)向WEB服务器程序80端口发起TCP的连接请求。
4.游览器向WEB服务器发起Http请求
建立TCP连接之后,发起HTTP请求,请求一般分为三部分
请求方法URI协议/版本
请求头(Request Header)
cookie connection host user-agent
版本 状态码
响应头
Content-length Content-Type Connection Cache-Control
请求正文
5.服务器处理结果返回
6.关闭tcp连接
7.浏览器解析资源
8.浏览器局部渲染

7. HTTPS的原理

 服务端的公钥和私钥,用来进行非对称加密
 客户端生成的随机密钥,用来进行对称加密
 8步:
 a.客户端向服务器发起HTTPS请求,连接到服务器的443端口
 b.服务器端有一个密钥对,即公钥和私钥,是用来进行非对称加密使用的,服务器端保存着私钥,不能将其泄露,公钥可以发送给任何人。
 c.服务器将自己的公钥发送给客户端。(数字签名)
 d.客户端收到服务器端的公钥之后,会对公钥进行检查,验证其合法性,检测其数字证书的合法性。如果公钥合格,那么客户端会生成一个随机值,这个随机值就是用于进行对称加密的密钥。
 e..客户端会发起HTTPS中的第二个HTTP请求,将加密之后的客户端密钥发送给服务器
 f.服务器接收到客户端发来的密文之后,会用自己的私钥对其进行非对称解密,解密之后的明文就是客户端密钥,然后用客户端密钥对数据进行对称加密,这样数据就变成了密文。
 g.然后服务器将加密后的密文发送给客户端。
 h.客户端收到服务器发送来的密文,用客户端密钥对其进行对称解密,得到服务器发送的数据。
 此时就需要引入了证书颁发机构(Certificate Authority,简称CA),CA数量并不多,Kobe客户端内置了所有受信任CA的证书。CA对James的公钥(和其他信息)数字签名后生成证书。
 https://blog.csdn.net/xiaoming100001/article/details/81109617

8. time_wait

  netstat -an | grep TIME_WAIT | wc -l
  (过多)调整内核的参数,在/etc/sysctl.conf 中net.ipv4.tcp_tw_recycle = 1(表示time_wait快速回收,默认为0)
  setsocketopt so_reuseaddr 
  保证完美断开,服务器没收到ack回复,会再发送fin包,保证第一次报文停留在网络中,影响下一次的连接
  client要维护time_wait状态,不然client断开了,服务端还没有断开,这时候服务端 如果在发送消息,可能导致返回rst,导致服务端触发sigpipe信号导致进程退出.

9. TCP连接建立,客户端出现故障

 如果建立连接,这时客户端突然出现故障,服务器不能一直等下去,服务器每收到一次客户端的请求后都会重新复位这个计时器,通常是2个小时,若两个小时没有收到客户端的任何数据

,服务器会发送一个探测报文段,以后每隔75秒发送一次,若连续发送10次人没有反应,服务器说明出现了故障,关闭连接。

10. session 和 session_id的理解

 a.什么是session
 session用来跟踪每个用户的,使用服务器生成的session_id来标识,用来区别用户
 b.session存放在哪里
 sessiom放在服务器内存里,session_id存放在服务器内存以及客户机的cookie中
 c.session和session_id的作用
 当用户发送请求时,服务器将用户cookie里面记录的session_id和服务器内存中存放的session_id对比,从而找到用户对应的session进行操作。

11.数字证书是什么,谁发放的,怎么知道是安全的,为什么?

数字证书是一种权威电子文档,验证数据发送方的合法身份,防止冒充(唯一性,可靠性)(内容:所有者公钥,所有者名字,公钥的失效期,颁发机构的名称,数字证书的序号)
由权威机构--CA证书颁发机构发行的,

1.TCP头部最少有多少字节最大能够为多少个字节?为什么?
最少为20,最大为60,协议字段里最少要有20个字节。长度字段为:4位 2^4-1=15,15*4=60

2.TCP头的紧急指针有什么作用?
用来外带数据。标志位urg被置上1时,有效。URG:紧急指针有效。它使一端可以告诉另一端有些具有某种方式的“紧急数据”已经放置在普通的数据流中。另一端被通知这个紧急数据已被放置在普通数据流中,由接收方决定如何处理。URG比特被置1,并且一个16bit的紧急指针被置为一个正的偏移量,该偏移量必须与TCP首部中的序号字段相加,以便得出紧急数据的最后一个字节的序号。注意:TCP的紧急方式不是带外数据(out-of-band data)。紧急方式有什么作用呢?两个最常见的例子是Telnet和Rlogin。当交互用户键入中断键时,另一个例子是FTP,当交互用户放弃一个文件的传输时。如果在接收方处理第一个紧急指针之前,发送方多次进入紧急方式会发生什么情况呢?在数据流中的紧急指针会向前移动,而其在接收方的前一个位置将丢失。接收方只有一个紧急指针,每当对方有新的值到达时它将被覆盖。这意味着如果发送方进入紧急方式时所写的内容对接收方非常重要,那么这些字节数据必须被发送方用某种方式特别标记。我们将看到Telnet通过在数据流中加入一个值为255的字节作为前缀来标记它所有的命令。
URG:此标志表示TCP包的紧急指针域(后面马上就要说到)有效,用来保证TCP连接不被中断,并且督促中间层设备要尽快处理这些数据;

3.TCP头的PUSH位有什么作用?
PSH:推标志该标志置位时,接收端不将该数据进行队列处理,而是尽可能快将数据转由应用处理。在处理 telnet 或 rlogin 等交互模式的连接时,该标志总是置位的。

4.tcp首部中URG和PUSH的区别?
URG标志 URG 紧急指针有效。当URG=1时,表示分段中有紧急数据应当加速传送。PSH标志 PSH 紧急位。当PSH=1时,要求发送方马上发送该分段,而接收方尽快的将报文交给应用层,不做队列处理。

5.MSS是什么?
MSS是最大数据段,相当于接收的缓冲区大小。而窗口大小则是对方剩余缓冲区的大小。当前窗口大小=MSS-未被应用程序读取的数据(已发ack包)的长度-未发ack包的数据的长度
mss是tcp能发送的分组的最大长度,在建立连接时,这个值已经被确定了,这个值并不是客观的值,而是由tcp/ip的实现确定的(root用户也可以进行修改)

6.MSS多少字节才是最合适的?太大了会导致什么情况发生?太小又会导致什么情况发生?
MSS最大传输大小的缩写,是TCP协议里面的一个概念。MSS就是TCP数据包每次能够传输的最大数据分段。为了达到最佳的传输效能TCP协议在建立连接的时候通常要协商双方的MSS值,这个值TCP协议在实现的时候往往用MTU值代替(最大MTU为1500Bytes,需要减去IP数据包包头的大小20Bytes和TCP数据段的包头20Bytes)所以往往MSS为1460。通讯双方会根据双方提供的MSS值得最小值确定为这次连接的最大MSS值。太大了会导致IP分片,从而传输性能低下。太小了导致传输次数增加,也会导致传输性能低下。

7.MTU最大为多少字节?
由于以太网EthernetII最大的数据帧是1518Bytes这样,刨去以太网帧的帧头(DMAC目的MAC地址48bit=6Bytes+SMAC源MAC地址48bit=6Bytes+Type域2bytes)14Bytes和帧尾CRC校验部分4Bytes(这个部门有时候大家也把它叫做FCS),那么剩下承载上层协议的地方也就是Data域最大就只能有1500Bytes这个值我们就把它称之为MTU。

8.TCP头主要有那些选项?
MSS,窗口扩大选项(最大为14位,则最大扩大到65535*2^14=1GB),选择确认选项,时间戳选项。

MSS:为了解决IP分片,而导致传输性能下降的问题。
窗口扩大选项(window scal):为了解决窗口太小,而使等待时间太长的问题。
选择确认选项(sack):为了解决在重传时,不用全部重传,只重传失去的部分。
时间戳选项:为了解决二个问题:一是计算往返时间RTT,二是防止序号归零。
9.在什么时候进行mss协商?协商不成功,默认为多少字节?
在三次握手时会进行协商。在发出第一个syn包的时候会带上MSS的大小,每经过一个网络设备就会取这个网络设备最小值的MSS作为新的MSS,协商不成功,默认为576字节,也有为536字节。

10.如果发送端发送报文大小大于接收端建立连接时指定的mss会怎样?在什么情况下会这发生这种情况?
会导致IP分片。MSS的作用就是为了防止IP分片而设置的。因为分片会大大降低性能。在链接已经建立了,并已经协商好了MSS,后来网络变化,走的路径不一样了。就有可能会造成发送端发送的报文大小大于接收端建立连接时的MSS的大小。
通常发送数据时,不能超过协议中的大小:TCP为1460,UDP为1472,不能超过发送缓冲区的大小。

11.MTU是什么?它的值可以通过什么相加得到?
MTU是最大传输单元。

12.为什么TCP数据中没有长度字段?而UDP中有长度字段。
因为IP协议中已经有了长度,且TCP数据段是一种流,协议中有序号来标识第一个数据包,使用确认号来标识已经收到的数据包。所以没有必要有长度。而UDP是一种数据报文。接收时,必须一次性接收完成,否则会认为是错误的数据。

13.TCP头部窗口是16bit,序号却是32bit,为什么序号不可以是更小的值呢?
序列号和确认号都是32位的,用来确认已经收到的数据。假设你的窗口是65535(16bit最大值),你采用了17bit的序列号和确认号。你只要传输2个窗口数据(17bit表示最大数=216+216-1=2*65535+1)就导致了一次序列号归零,这显然是行不通的,传输两个数据包的时间不过是毫秒级,而毫秒级就导致了序列号循环,那么假如中间有数据因不同的路径延迟到达接收端的顺序错误了,该如何判定呢,这个数据属于上一个序列号范围还是这个序列号范围?
因此,一定要让序列号长度足够大,至少应该让一次序列号的循环时间超过2倍的MSL(最大报文生存时间)时间,MSL时间随系统而不同,有30S,60S的。但随着网络的速度增长,万兆网络很快就会使4G长度的序列号循环,不过一个数据包如果在网络上传输,要么因为IP包的TTL减少为零很快被丢掉,要么和后续数据包有略微的延迟到达接收端(比如经过性能稍差的防火墙,多缓存了一会,而另一个数据包到达的路径上没有防火墙),这种属于上个序列号范围的报文,比下一个序列号范围的报文迟到的可能性基本为零。

14.UDP和TCP的区别
(起码以下几点)

基于连接和无连接(可靠,顺序,重传)
有无流量控制,拥塞避免
系统资源占用,TCP多,UDP少。
发送速度TCP慢
udp结构简单
流模式和数据报模式
15.Nagle算法是什么?用什么套接字选项关闭nagle算法?
Nagle算法:若发送应用进程把要发送的数据逐个字节地送到TCP的发送缓存,则发送方就把第一个数据字节先发送出去,把后面到达的数据字节都缓存起来。当发送方接收对第一个数据字符的确认后,再把发送缓存中的所有数据组装成一个报文段再发送出去,同时继续对随后到达的数据进行缓存。只有在收到对前一个报文段的确认后才继续发送下一个报文段。当数据到达较快而网络速率较慢时,用这样的方法可明显地减少所用的网络带宽。Nagle算法还规定:当到达的数据已达到 发送窗口大小的一半或已达到报文段的最大长度时,就立即发送一个报文段。使用这个选项TCP_NODELAY,可以关闭nagle算法。

16.TCP的流量控制原理是什么样的?
利用滑动窗口实现流量控制,如果发送方把数据发送得过快,接收方可能会来不及接收,这就会造成数据的丢失。所谓流量控制就是让发送方的发送速率不要太快,要让接收方来得及接收。
设A向B发送数据。在连接建立时,B告诉了A:“我的接收窗口是 rwnd = 400 ”(这里的 rwnd 表示 receiver window) 。因此,发送方的发送窗口不能超过接收方给出的接收窗口的数值。请注意,TCP的窗口单位是字节,不是报文段。TCP连接建立时的窗口协商过程在图中没有显示出来。再设每一个报文段为100字节长,而数据报文段序号的初始值设为1。大写ACK表示首部中的确认位ACK,小写ack表示确认字段的值ack。
糊涂窗口综合证: TCP接收方的缓存已满,而交互式的应用进程一次只从接收缓存中读取1字节(这样就使接收缓存空间仅腾出1字节),然后向发送方发送确认,并把窗口设置为1个字节(但发送的数据报为40字节的的话)。接收,发送方又发来1个字节的数据(发送方的IP数据报是41字节)。接收方发回确认,仍然将窗口设置为1个字节。这样,网络的效率很低。要解决这个问题,可让接收方等待一段时间,使得或者接收缓存已有足够空间容纳一个最长的报文段,或者等到接收方缓存已有一半空闲的空间。只要出现这两种情况,接收方就发回确认报文,并向发送方通知当前的窗口大小。此外,发送方也不要发送太小的报文段,而是把数据报积累成足够大的报文段,或达到接收方缓存的空间的一半大小。

17.几种拥塞控制方法?
慢开始( slow-start )、拥塞避免( congestion avoidance )、快重传( fast retransmit )和快恢复( fast recovery )。

慢开始( slow-start )
慢开始算法:当主机开始发送数据时,如果立即所大量数据字节注入到网络,那么就有可能引起网络拥塞,因为现在并不清楚网络的负荷情况。因此,较好的方法是先探测一下,即由小到大逐渐增大发送窗口,也就是说,由小到大逐渐增大拥塞窗口数值。通常在刚刚开始发送报文段时,先把拥塞窗口 cwnd 设置为一个最大报文段MSS的数值。而在每收到一个对新的报文段的确认后,把拥塞窗口增加至多一个MSS的数值。用这样的方法逐步增大发送方的拥塞窗口 cwnd ,可以使分组注入到网络的速率更加合理。

每经过一个传输轮次,拥塞窗口 cwnd 就加倍。一个传输轮次所经历的时间其实就是往返时间RTT。不过“传输轮次”更加强调:把拥塞窗口cwnd所允许发送的报文段都连续发送出去,并收到了对已发送的最后一个字节的确认。
拥塞避免( congestion avoidance )
拥塞避免算法:让拥塞窗口cwnd缓慢地增大,即每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1,而不是加倍。这样拥塞窗口cwnd按线性规律缓慢增长,比慢开始算法的拥塞窗口增长速率缓慢得多。
无论在慢开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞(其根据就是没有收到确认),就要把慢开始门限ssthresh设置为出现拥塞时的发送方窗口值的一半(但不能小于2)。然后把拥塞窗口cwnd重新设置为1,执行慢开始算法。这样做的目的就是要迅速减少主机发送到网络中的分组数,使得发生拥塞的路由器有足够时间把队列中积压的分组处理完毕。
快重传( fast retransmit )和快恢复( fast recovery )

18.ICMP和流量控制和TCP的流量控制、拥塞控制的区别?
ICMP中的是已经发生了,才会启用源站抑制报文来控制
而TCP中的避免发生,即还没有发生。

19.划出Tcp的状态变迁图?
图片描述

20.如何区分主动打开和被动打开?
调用了listen函数后,套接字就进入了被动打开的状态。

21.什么情况下会进入TIME_WAIT状态,为什么要有这个状态 ?这个状态持续多久?
发送方调用了close或shutdown,发送了fin包,且接收方也调用了close或shutdown函数发送了fin包。且发送方已经收到接收方的fin包。发送方就会进入TIME_WAIT状态。
确保最后一个ack成功传送,为了超时重传,2MSL,约4分钟。

22.TIME_WAIT会影响服务器程序重启,通过什么套接字选项可以解决?
SO_REUSEADDR

23.大量TIME_WAIT和CLOSE_WAIT的存在,会产生怎样的影响?
内核维护更多的状态。收到ip包,做hash运算,hlist冲突的概率更大。
很多端口无法绑定。如果服务器这时死掉,不能立刻起来。

24.为什么会有同时打开?什么情况下是同时打开?同时打开有多少次握手?
服务器程序和客户端程序同时使用connect时,如果同时收到sync包,则有可能出现同时打开。
4次握手。

25.为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?
这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可以未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。

26.为什么TIME_WAIT状态还需要等2MSL后才能返回到CLOSED状态?
这是因为虽然双方都同意关闭连接了,而且握手的4个报文也都协调和发送完毕,按理可以直接回到CLOSED状态(就好比从SYN_SEND状态到 ESTABLISH状态那样);但是因为我们必须要假想网络是不可靠的,你无法保证你最后发送的ACK报文会一定被对方收到,因此对方处于 LAST_ACK状态下的SOCKET可能会因为超时未收到ACK报文,而重发FIN报文,所以这个TIME_WAIT状态的作用就是用来重发可能丢失的ACK报文。
如果 TIME_WAIT 状态保持时间不足够长 ( 比如小于 2MSL) ,第一个连接就正常终止了。 第二个拥有相同相关五元组的连接出现,而第一个连接的重复报文到达,干扰了第二个连接。 TCP 实现必须防止某个连接的重复报文在连接终止后出现,所以让 TIME_WAIT 状态保持时间足够长 (2MSL) ,连接相应方向上的 TCP 报文要么完全响应完毕,要么被丢弃。建立第二个连接的时候,不会混淆。

27.关于TCP_NODELAY和TCP_CORK选项
TCP_CORK选项与TCP_NODELAY一样,是控制Nagle化的。

1. 打开TCP_NODELAY选项,则意味着无论数据包是多么的小,都立即发送(不考虑拥塞窗口)。
2. 如果将TCP连接比喻为一个管道,那TCP_CORK选项的作用就像一个塞子。设置TCP_CORK选项,就是用塞子塞住管道,而取消TCP_CORK选项,就是将塞子拔掉
3. 当TCP_CORK选项被设置时,TCP链接不会发送任何的小包,即只有当数据量达到MSS时,才会被发送。 一般当数据传输完成时,通常需要取消该选项,以防被塞住,这样才可以让不够MSS大小的包能及时发出去

28.为什么TCP_QUICKACK需要在每次recv后重新设置?
因为TCP_QUICKACK不是永久的,所以在每次recv数据后,应该重新设置。

29.为什么TCP延迟确认会导致延迟?
其实仅有延迟确认机制,是不会导致请求延迟的(初以为是必须等到ACK包发出去,recv系统调用才会返回)。一般来说,只有当该机制与Nagle算法或拥塞控制(慢启动或拥塞避免)混合作用时,才可能会导致时耗增长。

30.TCP超时重传机制?
超时重传是TCP协议保证数据可靠性的另一个重要机制,其原理是在发送某一个数据以后就开启一个计时器,在一定时间内如果没有得到发送的数据报的ACK报文,那么就重新发送数据,直到发送成功为止。

31.tcp的4个定时器?
2ml,保活定时器,超时定时器,坚持定时器

32.发起握手时,如果网络不通,发起端(发送第一个SYN包那端)会经历一个怎样的过程?
网络不通的:
会激活IPCMP不可达错误,被认为是软错误,客户端会保存这些信息。再重新发送syc包,不断重试。重试三次后,最后还是不成功,则返回路由不可达错误(EHOSTUNREACH)
网络通的:
握手一步发送SYN包,如果没有得到这个包的回包,会尝试三次后,每次间隔一定的时间(看TCP/IP协议),最后返回ETIMEDOUT错误。所以,connect会阻塞几分钟才返回。

c++11 特性

1. auto

  c++98就存在auto关键字,那是是用于申明变量为自动变量,自动变量意味着拥有自动的生存周期,这是多余的
  c++11 在声明变量的时候根据初始值的类型自动为此变量选择匹配的类型
  注意:auto变量必须在定义的时候初始化,类似于const关键字

2. lambda 函数

匿名函数 :通常需要一个函数,但是又不想费神命名一个函数
lambda函数比较轻便,很适合需要完成一项功能,但是此功能只在此一次使用,连名字都很随意的情况下
比如可以作为回调函数,传给某些因应用 ,sort
[=] 捕获外部变量,以传值的形式
[&]捕获外部变量,以引用的形式
【】(形参)-> 返回值{函数体};

3. 内联函数与#define

 a.内联函数在编译的时候展开,#define在预编译的时候展开
 b.在编译的时候,内联函数直接嵌入到目标代码中去,而宏只是一个简单的文本替换。
 c.内联函数可以进行类型的安全性检查,语句是否正确等编译功能,#define只是简单的文本替换,没有安全性检查。
 d.宏定义是要小心处理宏参数,一般用括号括起来,否则出现二异性。

4. 右值引用 (右值引用可以延长右值的生命周期)

  看能不能对表达式取地址,如果能,则为左值,否则为右值。
  &a 左值引用
  &&b 右值引用(int &&a = 1)可以给不具名的变量取一个别名
  不能将一个左值复制给一个右值引用
  不能将一个右值复制给一个左值引用
  getTemp()返回的右值本来在表达式语句结束后,其生命也就该终结了(因为是临时变量),而通过右值引用,该右值又重获新生,其生命期将与右值引用类型变量a的生命期一样,只要a还活着,该右值临时变量将会一直存活下去。实际上就是给那个临时变量取了个名字。

5. 移动语义

 右值引用是来支持移动语义的
 移动语义可以将资源从一个对象转移到另一个对象,这样就减少了不必要的临时对象创建,只是转移,没有内存的搬迁或者内存拷贝
 移动语义的引入是为了解决在进行大数据复制的时候,将动态申请的内存空间的所有权直接转让出去,不用进行大量的数据移动,既节省空间又提高效率。
 完全可以把临时变量a中的数据直接 “转移” 到新的变量下面即可。
 标准库在中提供了一个有用的函数std::move,std::move并不能移动任何东西,它唯一的功能是将一个左值引用强制转化为右值引用,继而可以通过右值引用使用该值,以用于移动语义。

std::move()
在C++11中,标准库在中提供了一个有用的函数std::move,std::move并不能移动任何东西,它唯一的功能是将一个左值强制转化为右值引用,继而可以通过右值引用使用该值,以用于移动语义 .

6. 完美转发

 指函数模板在向其他函数传递参数时该如何保留该参数左右值属性的问题。
 也就是说函数模板再向其他函数传递自身形参的时候,如果相应实参为左值,他就应该被转发为左值,如果他是右值,就应该被转发为右值

为了保留其他函数针对转发来的参数的左右值进行不同的处理。

7.智能指针

shared_ptr多个指针指向相同的对象。shared_ptr使用引用计数,每一个shared_ptr的拷贝都指向相同的内存。每使用他一次,内部的引用计数加1,每析构一次,内部的引用计数减1,减为0时,自动删除所指向的堆内存。shared_ptr内部的引用计数是线程安全的,但是对象的读取需要加锁。
初始化。智能指针是个模板类,可以指定类型,传入指针通过构造函数初始化。也可以使用make_shared函数初始化。不能将指针直接赋值给一个智能指针,一个是类,一个是指针。例如std::shared_ptr p4 = new int(1);的写法是错误的
拷贝和赋值。拷贝使得对象的引用计数增加1,赋值使得原对象引用计数减1,当计数为0时,自动释放内存。后来指向的对象引用计数加1,指向后来的对象。
get函数获取原始指针
注意不要用一个原始指针初始化多个shared_ptr,否则会造成二次释放同一内存
注意避免循环引用,shared_ptr的一个最大的陷阱是循环引用,循环,循环引用会导致堆内存无法正确释放,导致内存泄漏。循环引用在weak_ptr中介绍。

weak_ptr是为了配合shared_ptr而引入的一种智能指针,因为它不具有普通指针的行为,没有重载operator*和->,它的最大作用在于协助shared_ptr工作,像旁观者那样观测资源的使用情况。weak_ptr可以从一个shared_ptr或者另一个weak_ptr对象构造,获得资源的观测权。但weak_ptr没有共享资源,它的构造不会引起指针引用计数的增加。使用weak_ptr的成员函数use_count()可以观测资源的引用计数,另一个成员函数expired()的功能等价于use_count()==0,但更快,表示被观测的资源(也就是shared_ptr的管理的资源)已经不复存在。weak_ptr可以使用一个非常重要的成员函数lock()从被观测的shared_ptr获得一个可用的shared_ptr对象, 从而操作资源。但当expired()==true的时候,lock()函数将返回一个存储空指针的shared_ptr。

项目

ffmpeg命令

a . 注册所有容器格式 av_register_all()
b . 打开文件 av_open_input_file()
c .从文件中提取流的信息 av_find_stream_info()
d . 穷举所有的流,查找其中的种类
e .查找对应的解码器 avcodec_find_decoder()
f . 打开编解码器 avcodec_open()
g .为解码的帧分配内存 avcodec_alloc_frame()
h .不停的从码流中提取数据 av_read_frame();
i . 解码完成后,释放解码器avcodec_close()
k . 关闭输入文件 cv_close_input_file()
一.录制命令
1.1获取支持的设备
ffmpeg -devices
1.2 采集屏幕
ffmgeg -f avfoundation -i 1: -r 30 out.yuv
-f 指定从哪里采集数据 avfoundation
-i 1 表示从屏幕获取数据,0 表示从摄像头获取数据
-r 表示视频的帧率
1.3 播放采集数据
ffplay out.yuv //没有指定视频的分辨率和视频的格式
ffplay -s 1920x1080 -pix_fmt yuv422 out.yuv

二.分解与复用
2.1 将mp4转化为flv
ffmpeg -i test.mp4 -vcodec copy -acodec copy test.flv
2.2 将mp4文件从视频中抽取出来
ffmpeg -i test.mp4 -vcodec copy -an test.flv
-an 表示阻止文件的所有音频流
-an 表示阻止文件的所有视频流
-acodec 设置音频编解码器, copy 表示
-vcodec 设置视频编解码器
-c 表示编解码器,包括音视频编解码器

三.抽取音视频的原始数据
3.1 抽取mp4文件的原始数据 yuv数据
ffmpeg -i test.mp4 -an -codec:v rawvideo -pix_fmt yuv420p out.yuv

四.滤镜命令
ffmpeg -i test.mp3 -vf volume=1 -acodec copy volume.mp3

五.视频裁剪命令
5.1 裁剪命令
ffmpeg -i haha.mp4 -ss 00:01:10 -t 10 out.ts
-t 表示限制从输入文件读取数据的时长,单位为 s。
-ss 表示拖动到某一个时间位置,格式为:12:03:45
5.2合并视频
ffmpeg -f concat -i input.txt out.mp4

六、视频与图片转换命令
6.1、将一个视频每一帧图片提取出来,fps = 1
ffmpeg -i testfile.mp4 -r 1 -f image2 foo-%03d.jpeg
-r 1s 为一帧
-f 指定输出文件的格式为 image2
6.2、将一组图片转化为一个视频文件
ffmpeg -f image2 -i foo-%03d.jpeg out.avi

easydarwin 流媒体服务

流媒体功能:汇集采集层发布的视频,包含原始视频流和融合了分析结果、监测数据以及业务数据的视频流;为不同的终端类型的设备转发不同协议的流媒体数据,为桌面客户类型的终端转发RTSP视频流,为移动端和web浏览器播放的终端转发HLS视频流。
DSS内部原理:DSS包含两个进程,父进程负责创建和监听子进程,并等待子进程的退出,如果子进程异常退出,父进程会重新创建新的子进程[71]。子进程负责完成各种任务具体调度。
DSS通过创建四种不同的线程来完成任务:
1.父线程:记录打印相关统计信息,开启和关闭线程
2.事件线程:监听套接字相关事件
3.任务线程:获取事件线程的事件,吧套接字请求传给不同的模块处理
4.空闲任务线程:主要管理超时事件和socket任务

webservice

web service是唯一提供对数据访问功能并对外发布数据的接口,主要功能:为终端层设备提供设备信息,包括设备基本信息,视频流地址以及异常监控和分析结果。Web service开发采用gSoap工具实现其服务端。gSoap是开放的C/C++源码的SOAP/XML服务工具,提供了关于C/C++语言的SOAP实现
Web service主要为本系统提供数据服务,如:设备信息、报警信息、历史数据等查询和访问功能;同时是为经过授权的第三方系统进行数据的交换的接口,实现对其他系统的无缝对接。
WebService
就是一个应用程序,它向外界暴露出一个可以通过web进行调用的API,是分布式的服务组件。
SOAP(Simple Object AccessProtocol)简单对象访问协议
一个基于xml格式的web交互协议。
SOAP简单的理解,就是这样的一个开放协议SOAP=RPC+HTTP+XML:采用HTTP作为底层通讯协议;RPC作为一致性的调用途径,XML作为数据传送的格式,

前端的视频流是HLS格式视频流,播放器采用LongTail Video公司开发的JW Player,JW Player是一个基于Flash的开源的音视频网页播放器,该播放器在增加HLS插件后能够直接播放HLS视频流数据。

rtsp,rtmp,hls协议

1.rtsp协议

实时流协议基于文本的多媒体播放控制协议,属于应用层的协议,rtsp协议在
rtp,rtcp之上,基于TCP或udp完成视频传输
一次基本的RTSP操作过程:
首先,客户端连接到流服务器并发送一个RTSP描述命令(DESCRIBE)。
流服务器通过一个SDP描述来进行反馈,反馈信息包括流数量、媒体类型等信息。
客户端再分析该SDP描述,并为会话中的每一个流发送一个RTSP建立命令(SETUP),RTSP建立命令告诉服务器客户端用于接收媒体数据的端口。流媒体连接建立完成后,
客户端发送一个播放命令(PLAY),服务器就开始在UDP上传送媒体流(RTP包)到客户端。 在播放过程中客户端还可以向服务器发送命令来控制快进、快退和暂停等。
最后,客户端可发送一个终止命令(TERADOWN)来结束流媒体会话

rtsp_url = (“rtsp:”| “rtspu:”) “//” host [“:”port”] /[abs_path]/content_name

在这里插入图片描述
RTSP请求报文的方法包括:OPTIONS、DESCRIBE、SETUP、TEARDOWN、PLAY、PAUSE、GET_PARAMETER和SET_PARAMETER。
在这里插入图片描述

2.rtmp

https://www.cnblogs.com/zoneofmine/p/10874740.html
RTMP协议是Real Time Message Protocol(实时信息传输协议)
RTMP协议是应用层协议,是要靠底层可靠的传输层协议(通常是TCP)来保证信息传输的可靠性的。在基于传输层协议的链接建立完成后,RTMP协议也要客户端和服务器通过“握手”来建立基于传输层链接之上的RTMP Connection链接

要建立一个有效的RTMP Connection链接,首先要“握手”:客户端要向服务器发送C0,C1,C2(按序)三个chunk,服务器向客户端发送S0,S1,S2(按序)三个chunk,然后才能进行有效的信息传输。
RTMP传输的数据的基本单元为Message,但是实际上传输的最小单元是Chunk(消息块),因为RTMP协议为了提升传输速度,在传输数据的时候,会把Message拆分开来,形成更小的块,这些块就是Chunk。

RTMP协议是应用层协议,是要靠底层可靠的传输层协议(通常是TCP)来保证信息传输的可靠性的。
在基于传输层协议的链接建立完成后,一个RTMP协议的流媒体推流需要经过以下几个步骤:
握手(RTMP连接都是以握手作为开始)
建立连接 (建立客户端与服务器之间的“网络连接”)
建立流 (建立客户端与服务器之间的“网络流”)
推流 (传输视音频数据)

RTMP握手的这个过程完成了两件事:
校验客户端和服务器端RTMP协议版本号
发了一堆数据,猜想应该是测试一下网络状况,看看有没有传错或者不能传的情况

nginx

nginx使用一个多进程模型来对外提供服务,一个master进程和多个worker进程,master进程负责管理nginx本身和其他worker进程。
业务处理逻辑都在worker进程。worker进程中有一个函数,ngx_worker_process_cycle()执行无限循环,不断处理收到的来自客户端的请求,并进行处理,直到整个nginx服务被停止。
简单处理流程如下:
操作系统提供的机制(例如epoll, kqueue等)产生相关的事件。
接收和处理这些事件,如是接受到数据,则产生更高层的request对象。
处理request的header和body。
产生响应,处理响应数据并发送回客户端。
完成request的处理。
重新初始化定时器及其他事件,断开连接

1.nginx首先会根据请求信息中的Host进行匹配server_name,选择对应的server

2.如果请求中Host字段没有域名形式(即ip形式的访问网站,如:输入127.0.0.1 访问),那么nginx默认选择第一个server

3.也可以在listen加入default_server 标明默认虚拟服务 ( listen 80 default_server),那么如果找不到

测试

1.怎么理解测试

怎么理解测试这项工作的
就是利用测试工具按照测试方案和流程对产品进行功能和性能测试,甚至根据需要编写不同的测试工具,设计和维护测试系统,对测试方案可能出现的问题进行分析和评估。执行测试用例后,需要跟踪故障,以确保开发的产品适合需求。使用人工或者自动手段来运行或测试某个系统的过程,其目的在于检验它是否满足规定的需求或弄清预期结果与实际结果之间的差别

2.微信换头像测试

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值