面试题2: 文字描述题

1. 什么是进程?什么是线程?

进程是资源分配的最小单位。程序的一次执行过程,就是进程的运行。
线程是cpu调度的最小单位,线程属于进程,如果进程结束,那么这个进程的所有线程也都会被结束。同一个进程的多个线程之间共享进程的公共资源。

2. 进程和线程的区别

a.地址空间和其它资源:进程间相互独立,同一进程的各线程间共享。
b.通信:进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。
c.调度和切换:线程上下文切换比进程上下文切换要快得多。

3. 进程之间的通信方式以及优缺点?

管道、信号、信号量、消息队列、共享内存、套接字

(1) 管道
管道分为无名管道和有名管道。
无名管道是一种半双工的通信方式,数据只能单向流动,而且只能在有亲缘关系的进程间使用。当一个进程创建了无名管道并调用fork创建子进程后,父进程关闭读/写管道,子进程关闭写/读管道,实现两个进程之间的通信。
有名管道也是一种半双工的通信方式,但是允许在无亲缘关系的进程间使用。
无名管道:
优点:简单、方便
缺点:局限于单向通信,只能在有亲缘关系的进程间使用,缓冲区有限
有名管道:
优点:可以在任意进程间使用
缺点:使用不当容易出错;缓冲区有限

(2) 信号量
信号量是一个计数器,用来控制多个进程/线程对共享资源的访问,作为多进程/线程之间的同步手段。
优点:可以用在多进程、多线程
缺点:信号量有限

(3) 信号
信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生.

(4) 消息队列
消息队列是消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信号少,管道只能承载无格式字节流服务等缺点,允许不同进程间传递格式化的数据流,支持为消息安排优先级顺序。

优点:可以实现任意进程间的通信,并通过系统调用函数来实现消息发送和接收之间的同步,无需考虑同步问题,方便;
缺点:信息的复制需要额外消耗CPU的时间,不适宜于信息量大或操作频繁的场合

(5) 共享内存
共享内存就是映射一段能被其他进程访问的内存,通过这块内存进程数据传递。共享内存是最快的进程间通信方式。

优点:无须复制,快捷,信息量大;
缺点:需要考虑进程间读写的同步问题

(6) 套接字:可用于不同及其间的进程通信
优点:1)传输数据为字节级,传输数据可自定义,数据量小效率高;2)传输数据时间短,性能高;3) 适合于客户端和服务器端之间信息实时交互;4) 可以加密,数据安全性强
缺点:1) 需对传输的数据进行解析,转化成应用级的数据。

4. 线程之间的通信方式?

互斥锁、条件变量、信号量等。

5. 什么时候用多线程?什么时候用多进程?

(1) 需要频繁创建、销毁的优先使用线程
进程的开销较线程更大
(2) 需要进行大量运算的优先使用线程
(3) 强相关的处理优先使用线程,弱相关的处理使用进程
(4) 可能要扩展到多机分布的用进程,多核分布的用线程

6. 死锁

概念:进程间进行通信或相互竞争系统资源而产生的永久阻塞,若无外力作用将永远处在死锁状态。
产生原因:(1)系统资源不足;(2)进程运行推进顺序与速度不同也可能导致死锁;(3)资源分配不当;

产生死锁四个必要条件:
(1) 互斥条件:就是一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程在请求其它资源而阻塞时,但是它对自己已获得的资源又保持不放。
(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

预防死锁和避免死锁的方法:在系统设计、进程调度方面注意不让产生死锁的四个必要条件成立,确定资源的合理分配算法,避免进程永远占用系统资源,对资源分配要进行合理的规划。

7. 多线程中栈与堆是公有的还是私有的

因为线程是共享进程的资源的,所以栈是私有的,堆是公有的。

8. 线程池的概念

线程池就是一堆已经创建好的线程,最大数目一定,然后初始后都处于空闲状态,当有新任务进来时就从线程池中取出空闲线程处理任务,任务完成之后又重新放回去,当线程池中的所有线程都在任务时,只能等待有线程结束任务才能继续执行。

1. 关键字volatile有什么含义,举3个例子

一个被定义为volatile类型的变量意味着这个变量的值可能会被意想不到地改变,编译器在用到这个变量的时候,最好重新去读取这个变量的值。
并行设备的硬件寄存器(比如状态寄存器);
中断服务子程序的非自动变量;
多线程中被多个任务共享的变量。

2. select函数的优缺点

优点: 几乎能在所有的平台上使用
缺点:
(1) 每次调用select,都会把fd的集合从用户态拷贝到内核态,当fd很多时,这个开销会很大。
(2) 每次调用select,都会在内核遍历传递进来的所有fd,当fd很多时,这个开销也很大。
(3) 单个进程能够监视的fd数量存在限制
(4) 每次调用select,都必须对参数进行重新设定,比较麻烦,而且会降低性能。

while (1)
{
	FD_ZERO(&rset);
	FD_SET(fd1, &rset);
	FD_SET(fd2, &rset);
	maxfd = fd1 > fd2 ? fd1 : fd2;
	sttime.tv_sec = 5;
	sttime.tv_usec = 0;
	ret = select(maxfd + 1, &rset, NULL, NULL, &sttime);
	if (ret < 0) {
		if (errno == EINTR)
			continue;
		else 
			break;
	}
	if (ret == 0)
		cout << "time out" << endl;
		continue;
	if (FD_ISSET(fd1, &rset))
	{
		read(fd1, buf, sizeof(buf));
		...
	}
	if (FD_ISSET(fd2, &rset))
	{
		read(fd2, buf, sizeof(buf));
		...
	}		
}

3. poll函数的优缺点

优点:调用poll函数,只需要进行一次参数设定就好。当fd数目很多时,效率比select高。
确定:
当fd数目很多时,fd集合在应用态与内核态之间复制,也存在很大开销。
与select一样,poll函数返回后,也需要采用轮训的方式来处理,影响效率。

struct pollfd stpolls[2];
stpolls[0].fd = fd1;
stpolls[0].events = POLLIN;
stpolls[1].fd = fd2;
stpolls[1].events = POLLIN;
while (1)
{
	ret = poll(stpolls, 2, 200);
	if (ret < 0) {
		if (errno == EINTR)
			continue;
		else
			break;
	}
	if (ret == 0) {
		cout << "timeout" << endl;
		break;
	}
	if (stpolls[0].events = stpolls[0].revents) {
		read(stpolls[0].fd, buf, sizeof(buf));
		...
	}
	if (stpolls[1].events = stpolls[1].revents) {
		read(stpolls[1].fd, buf, sizeof(buf));
		...
	}	
}

4. ARP协议的工作原理

每台主机都会建立一个ARP列表,用来表示IP地址和MAC的对应关系。当源主机向目的主机发送数据包时,首先到自己的ARP列表里查找,是否有目的IP对应的MAC,如果有,封装数据包,发送到目的MAC对应的主机。如果没有,向该网段广播ARP请求包。同网段内所有收到该ARP请求的主机,都会对比ARP请求包里查询的IP地址是否是自己的IP,如果不是,忽略该请求包,如果是,将向源主机回应一个ARP响应包,告知其MAC地址,并在自己的ARP列表里更新源主机的IP和MAC地址。收到ARP响应的源主机,利用获取的目的MAC地址重新封装报文,进行发送,并在自己的ARP列表里更新目的IP和MAC。

5. tcp与udp的区别

tcp提供面向连接的可靠的数据流服务
udp提供面向非连接的不可靠的数据报服务

6. tcp的可靠如果保证

tcp通过序号和ack的方式,实现传输的可靠性

7. tcp的三次握手和四次挥手

三次握手:
一、客户端发出连接请求
(1) 生成一个随机数作为初始序号seq=x
(2) 发出syn包,seq=x
(3) 客户端进入SYN_SEND状态,等待服务器回应
二、服务器回应客户端连接请求
(1) 生成一个随机数作为初始序号seq=y
(2) 回应客户端syn+ack包,ack=x+1, seq=y
(3) 服务器进入SYN_RECV状态
三、客户端确认收到,连接建立成功
(1) 客户端收到服务器的syn+ack后,回应ack包,ack=y+1, seq=x+1
(2) 客户端、服务器进入ESTABLISHED状态,连接建立成功
在这里插入图片描述
四次挥手

一、客户端请求断开连接
(1) 客户端发出FIN包,seq=x
(2) 客户端进入FIN-WAIT-1状态
二、服务器响应ack
(1) 服务器响应客户端FIN包,回应ack=x+1, seq = y,服务器进入CLOSE-WAIT状态。
(2) 这时客户端到服务器的连接已经断开,但服务器仍然可以往客户端发消息
(3) 客户端收到服务器的ack响应,进入TIME-WAIT-2状态
三、服务器发送FIN包
(1) 服务器待消息发送完毕,发出FIN包。由于在CLOSE-WAIT状态可能还发送了数据,所以seq=z
(2) 服务器进入LAST-ACK状态,等待客户端确认
四、客户端响应服务器的FIN包
(1) 客户端收到服务器的FIN包后,发出ack确认,ack=z+1, seq = x+1
(2) 服务器收到客户端的ack后,立即进入CLOSED状态
(3) 客户端发出ack后进入TIME-WAIT状态。经过2MSL时间后,客户端进入CLOSED状态
在这里插入图片描述

9. 为什么连接的时候是三次握手,关闭的时候却是四次握手?

建立连接时,客户端发送SYN包,服务器后回应SYN+ACK包,然后等待客户端发送确认消息,这是可靠连接的最低限度。
关闭连接时,当服务器收到FIN包后,可能还有数据要发送,所以不会立刻关闭,先回复一个ACK。当数据发送完成时,再向客户端发送FIN包,释放连接,然后等待客户端确认,所以需要四步。

10. 为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?

客户端最后发出的ACK包可能会丢失,TIME-WAIT状态就用来重发丢失的ACK报文。如果客户端发出的ACK丢失,服务器没有收到ACK,服务器将不断重发FIN报文,
所以客户端不能立刻关闭。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。所谓的2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。

11. 如果已经建立了连接,但是客户端突然出现故障了怎么办?

TCP设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

12. tcp/ip协议中每层对应的协议

网络层:ARP ICMP IP
传输层:TCP UDP
应用层:FTP TFTP HTTP CAPWAP DNS TELNET DHCP

13. tcp/udp对应的应用层协议

tcp: http telnet ftp
udp: tftp dns dhcp

14. 特殊的ip地址
(1) 网络地址
   IP地址由网络号(包括子网号)和主机号组成,网络地址的主机号为全0,网络地址代表着整个网络。
(2) 广播地址
    广播地址通常称为直接广播地址,是为了区分受限广播地址。
    广播地址与网络地址的主机号正好相反,广播地址中,主机号为全1。当向某个网络的广播地址发送消息时,该网络内的所有主机都能收到该广播消息。
(3) 组播地址
    D类地址就是组播地址。
    先回忆下A,B,C,D类地址吧
    A类地址以00开头,第一个字节作为网络号,地址范围为:0.0.0.0~127.255.255.255;
    B类地址以10开头,前两个字节作为网络号,地址范围是:128.0.0.0~191.255.255.255;
    C类地址以110开头,前三个字节作为网络号,地址范围是:192.0.0.0~223.255.255.255。
    D类地址以1110开头,地址范围是224.0.0.0~239.255.255.255,D类地址作为组播地址(一对多的通信);
    E类地址以1111开头,地址范围是240.0.0.0~255.255.255.255,E类地址为保留地址,供以后使用。
    Notice:只有A,B,C有网络号和主机号之分,D类地址和E类地址没有划分网络号和主机号。
(4) 255.255.255.255   该IP地址指的是受限的广播地址。受限广播地址与一般广播地址(直接广播地址)的区别在于,受限广播地址之只能用于本地网络,路由器不会转发以受限广播地址为目的地址的分组;一般广播地址既可在本地广播,也可跨网段广播。例如:主机192.168.1.1/30上的直接广播数据包后,另外一个网段192.168.1.5/30也能收到该数据报;若发送受限广播数据报,则不能收到。
    Notice:一般的广播地址(直接广播地址)能够通过某些路由器(当然不是所有的路由器),而受限的广播地址不能通过路由器。

(5) 0.0.0.0
     常用于寻找自己的IP地址,例如在我们的RARP,BOOTP和DHCP协议中,若某个未知IP地址的无盘机想要知道自己的IP地址,它就以255.255.255.255为目的地址,向本地范围(具体而言是被各个路由器屏蔽的范围内)的服务器发送IP请求分组。

(6) 回环地址
   127.0.0.0/8被用作回环地址,回环地址表示本机的地址,常用于对本机的测试,用的最多的是127.0.0.1。

(7) A、B、C类私有地址
   私有地址(private address)也叫专用地址,它们不会在全球使用,只具有本地意义。
   A类私有地址:10.0.0.0/8,范围是:10.0.0.0~10.255.255.255
   B类私有地址:172.16.0.0/12,范围是:172.16.0.0~172.31.255.255
   C类私有地址:192.168.0.0/16,范围是:192.168.0.0~192.168.255.255
15. NAT协议 DHCP协议 DNS协议的作用
NAT协议:
	网络地址转换协议。
	将私有IP地址转为公网IP地址,或者将公网IP地址转为私有IP地址。
DHCP协议:
	动态主机配置协议。给局域网主机自动分配IP地址。
DNS协议:
	域名系统。向DNS服务器发送请求,解析域名对应的IP。
16. c++容器

(1) vector

单向开口的序列式(数组)容器,随机访问迭代器
头 front()
尾 back()
插入 insert(pos, element)
	v.push_back()
移除
	v.pop_back()

(2) deque容器

双向开头的序列式容器,随机访问迭代器
头 front() back()
插入移除  push_back() push_front()
	pop_back() pop_front()
	insert(pos, element)

(3) stack容器

先进后出,无迭代器
栈顶 top()
插入 push()
出栈 pop()

(4) queue 队列容器

先进先出
头 front() back()
插入移除 push() pop()

(5) list容器 双向链表

头 front() back()
插入移除 push_front() push_back()
pop_front() pop_back()

(6) set容器 平衡二叉树,自动排序

插入:insert(element)
移除  erase(element)

(7) 对组pair

pair<int, string>  p1(23, "xiao");
pair<int, string>  p2 = make_pair(23, "xiao");

(8) map容器 红黑树

所有元素都是对组pair
map<int, string>m1;
插入 insert(element)
m1.insert(pair<int, string>(23, "xiao"));
m1.insert(make_pair(12, "xiao"));
m1[23] = "xiao";
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值