【杂项】 面试复习

1. C++

2. 计算机网络

3. 操作系统

4. 数据库

5. 数据结构

6. 杂项

1. main函数之前执行了什么?

全局对象的构造函数会在main 函数之前执行。
①设置栈指针
②初始化静态和全局变量,即data段的内容
③将未初始化部分的赋初值:数值型short,int,long等为0,bool为FALSE,指针为NULL,等等,即.bss段的内容
④运行全局构造器,估计是C++中构造函数之类的吧
⑤将main函数的参数,argc,argv等传递给main函数,然后才真正运行main函数

2. Select poll epoll

网络IO可以抽象成用户态和内核态之间的数据交换。使用select、epoll等操作系统提供的系统调用来检测IO事件的各种机制,获取到处于活跃状态的连接。
Select:
1)创建所关注的事件的描述符集合(fd_set),对于一个描述符,可以关注其上面的读(read)、写(write)、异常(exception)事件,所以通常,要创建三个fd_set,一个用来收集关注读事件的描述符,一个用来收集关注写事件的描述符,另外一个用来收集关注异常事件的描述符集合。
2)调用select()等待事件发生。这里需要注意的一点是,select的阻塞与是否设置非阻塞I/O是没有关系的。
3)轮询所有fd_set中的每一个fd,检查是否有相应的事件发生,如果有,就进行处理。
Select缺点
1)每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大!!!(复制大量句柄数据结构,产生巨大的开销 )。
2)同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大!!!(消耗大量时间去轮询各个句柄,才能发现哪些句柄发生了事件)。
3)单个进程能够监视的文件描述符的数量存在最大限制,32位机默认是1024。
4)select的触发方式是水平触发,应用程序如果没有完成对一个已经就绪的文件描述符进行IO操作,那么之后每次select调用还是会将这些文件描述符通知进程。
Poll:与select差不多,采用链表的方式替换原有fd_set数据结构,没有连接数的限制。
Epoll:将这两个操作分开,先用epoll_ctl维护等待队列,再调用epoll_wait阻塞进程(解耦)
1)通过epoll_create建立epoll句柄。
2)将描述符所感兴趣的事件通过epoll_ctl添加到等待队列中
3)调用epoll_wait返回所有可读写的描述符。

双向列表列表引用着就绪的 socket,接收内核触发的事件,所以它应能够快速的插入数据。使用双向链表来实现就绪队列redlist,可以快速删除和插入
epoll 使用了红黑树作为索引结构,保存监视的 socket,至少要方便地添加和移除,还要便于搜索,以避免重复添加。

我们在调用epoll_create时,内核除了帮我们在epoll文件系统里建了个file结点,在内核cache里建了个红黑树用于存储以后epoll_ctl传来的socket外,还会再建立一个list链表,用于存储准备就绪的事件,当epoll_wait调用时,仅仅观察这个list链表里有没有数据即可。有数据就返回,没有数据就sleep,等到timeout时间到后即使链表没数据也返回。所以,epoll_wait非常高效。
ET(边缘触发):只有当句柄状态改变时,边缘触发才会发出通知。也就是发生读写事件后,只会通知一次。Fd就会在就绪队里中删除
LT(水平触发):只要句柄满足某种状态,水平触发就会发出通知。也就是当epoll_wait检测到fd上有事件发生并将此事件通知应用程序后不会删除,而下一次调用epoll_wait的时候会继续通知
ET比LT高效的原因:因为fd通知之后没有被删除,所以就绪队列会特别长,遍历要时间;还有就是ET模式在很大程度上降低了同一个epoll事件被重复触发的次数。

3. 同步和异步:

请求发起方对消息结果的获取是主动发起的,还是等被动通知的。
(同步阻塞)如果是请求方主动发起的,一直在等待应答结果
(同步非阻塞)可以先去处理其他的事情,但要不断轮询查看发起的请求是否有应答结果
(异步阻塞)如果是由服务方通知的,也就是请求方发出请求后,要在一直等待通知
(异步非阻塞)要么就先去干自己的事了
异步通知的方式一般是通过状态改变,消息通知,或者回调函数来完成,大多数时候采用的都是回调函数。
阻塞和非阻塞:针对IO的操作,
(阻塞)阻塞调用是指调用结果返回之前,当前线程会被挂起。在得到结果之后才会返回。
(非阻塞)指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。

4. 大小端

小端模式:低的有效字节存储在低的存储器地址。小端一般为主机字节序;常用的X86结构是小端模式 很多ARM, DSP都为小端模式。
大端模式:高的有效字节存储在低的存储器地址。大端为网络字节序; KEIL C51 则为大端模式 有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。
如何判断:我们可以根据联合体来判断系统是大端还是小端。因为联合体变量总是从低地址存储

union myunion{
    int a;
    char b;
}
int is_little_endiam(void){
    uinon myunion u1;
    u1.a = 1;
    return u1.b//结合上图 
    //大端返回0  小端返回1;
}
5. 键盘输入到屏幕显示整个过程:

pic也就是可编程中断控制器的芯片组,负责监控设备,当有键入,就会产生一个中断,告诉CPU键盘设备有键入,这个时候CPU会倒IDT,也就是中断记录表中查找相应的中断程序,并且执行这个中断程序。而键入的中断程序的功能就是让CPU从对应的键盘端口取出数据,把数据放到显存的对应位置,

  1. 键盘被按下后,也就是生成 了硬件中断信号。
  2. 计算机中断控制器(PIC)8259A芯片捕捉到硬件中断信号
  3. PIC产生一个中断号,告诉CPU键盘设备有键入,并将中断号发送给中断描述符表(IDT)处理。
  4. 计算机根据IDT选择中断处理函数。
  5. 处理函数处理并通知端口驱动获取按键的信息
  6. 端口驱动将数据封装,以IRP(I/O request package)形式传递给上层处理程序。
  7. 等待输入的进程获得数据,处理并交给目标进程。
  8. 目标进程显示输入。
6. socket编程
  1. nRC = WSAStartup(0x0101, &wsaData);
    这个函数是应用程序应该第一个调用的Winsock API函数,完成对Winsock服务的初始化。
  2. srvtcpsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    函数执行成功返回一个新的SOCKET,失败则返回INVALID_SOCKET。这时可以调用WSAGetLastError函数取得具体的错误代码。所有的通信在建立之前都要创建一个SOCKET。
  3. nRC=bind(srvtcpsock, (sockaddr *)&srvbindaddr, sizeof(sockaddr));
    成功地创建了一个SOCKET后,用bind函数将SOCKET和主机地址绑定。
  4. listen(srvtcpsock, 20);
    对于服务器的程序,当申请到SOCKET,并将通信对象指定为INADDR_ANY之后,就应该等待一个客户机的程序来要求连接,listen函数就是把一个SOCKET设置为这个状态
  5. SOCKET communicatesock = accept(srvtcpsock, (sockaddr*)&thrdinfo.clientaddr, &len);
    accept函数从等待连接的队列中取第一个连接请求,并且创建一个新的SOCKET来负责与客户端会话。
  6. err = recv(communicatesock, recvbuf, MAXN, 0); InetNtop()分离出IP号
    通过已经连接的SOCKET接收数据
  7. int ret = send(communicatesock, sendbuf, len_snd + len, 0);
    用send函数通过已经连接的SOCKET发送数据。
  8. closesocket(srvtcpsock); WSACleanup();
    关闭指定的SOCKET。
    join()函数是一个等待线程函数,主线程需等待子线程运行结束后才可以结束(注意不是才可以运行,运行是并行的),如果打算等待对应线程,则需要细心挑选调用join()的位置
    detach()函数是子线程的分离函数,当调用该函数后,线程就被分离到后台运行,主线程不需要等待该线程结束才结束
7. fork创建子进程

创建一个新进程 :pid_t fork(void)
如果出错返回-1
fork 调用一次,两次返回,父进程返回新进程的pid,子进程返回0
子进程将父进程的实体复制一遍,然后从fork()下面继续运行。
父子进程执行的顺序取决于系统当前环境以及进程调度算法

8. 线程池

在程序启动的时候就创建若干线程来响应处理,它们被称为线程池,里面的线程叫工作线程
  第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
  第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
  第三:提高线程的可管理性。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值