找朋友内推的腾讯MIG一面,问了项目,也问了很多基础的东西,现总结如下:
1、函数调用的匹配顺序
函数模板、模板显式特化函数和普通函数的优先选择顺序,总结出以下4点:
1)如果有参数类型完全匹配的普通函数,则调用之;
2)否则,如果有匹配的模板显式特化函数,则调用之;
3)否则,如果模板函数能够推导出一个参数类型完全匹配的函数实例,则调用之;
4)否则,如果调用函数的实参能够进行隐式转换成与普通函数或者模板显式特化函数的类型匹配,则调用之;
5)如果以上四条都不能匹配,则函数匹配失败,发生编译错误。
2、类的构造函数调用虚函数
简直了,这在《Effective C++》里 #9 绝不在构造函数和析构函数里调用虚函数 有详细的介绍,我居然堂而皇之地忘记了。
base class 构造期间 virtual 函数绝不会下降到 derived class 阶层。非正式的说法也许比较传神:在 base class 构造期间, vritual 函数不是 virtual 函数。
借用下面的例子说明之:
#include
using namespace std;
class base
{
public:
base(){fun();}
virtual void fun(){cout << "base::fun" << endl;}
};
class derived: public base
{
public:
derived(){fun();}
virtual void fun(){cout << "derived::fun" << endl;}
};
int main()
{
derived d;
return 0;
}
base::fun //构建base部分时调用了 base::fun
derived::fun //构建derived部分时调用了 derived::fun
3、对比红黑树和AVL树
答的不好,大家自行 google。
4、shell,awk熟不熟?
(⊙v⊙)嗯,用的不多,还需学习
5、详细介绍下IPC
关于此,可以去看我的 【Linux编程】系列,持续更新中。。。
6、熟不熟悉一些开源的东西?
(⊙v⊙)嗯,不。。。
7、Linux进程调度策略
猝。。。
查看了几天资料,先看写最基本的策略:
见:http://www.personal.kent.edu/~rmuhamma/OpSystems/os.html第8章
最常见的策略有:
1)FIFO:又称FCFS(First-Come-First-Served),最基本的策略。
Processes are dispatched according to their arrival time on the ready queue. Being a nonpreemptive discipline, once a process has a CPU, it runs to completion.
2)RR:轮转调度。简单,公平,被广泛使用策略。
In the round robin scheduling, processes are dispatched in a FIFO manner but are given a limited amount of CPU time called a time-slice or a quantum.
3)SJF(Shortest-Job-First):Shortest-Job-First (SJF) is a non-preemptive discipline in which waiting job (or process) with the smallest estimated run-time-to-completion is run next.
4)SRT(Shortest-Remaining-Time):The SRT is the preemtive. The process with the smallest estimated run-time to completion is run next, including new arrivals.In SRT scheme, a running process may be preempted by a new arrival process with shortest estimated run-time.
5)Priority Scheduling:The basic idea is straightforward: each process is assigned a priority, and priority is allowed to run. Equal-Priority processes are scheduled in FCFS order. The shortest-Job-First (SJF) algorithm is a special case of general priority scheduling algorithm.Priority scheduling can be either preemptive or non preemptive.A major problem with priority scheduling is indefinite blocking or starvation. A solution to the problem of indefinite blockage of the low-priority process is aging. Aging is a technique of gradually increasing the priority of processes that wait in the system for a long period of time.
6)Multilevel Queue Scheduling
In a multilevel queue scheduling processes are permanently assigned to one queues.
The processes are permanently assigned to one another, based on some property of the process, such as
Algorithm choose the process from the occupied queue that has the highest priority, and run that process either
Each queue has its own scheduling algorithm or policy.
Possibility I (Main)If each queue has absolute priority over lower-priority queues then no process in the queue could run unless the queue for the highest-priority processes were all empty.
Possibility II
If there is a time slice between the queues then each queue gets a certain amount of CPU times, which it can then schedule among the processes in its queue. For instance:
Since processes do not move between queue so, this policy has the advantage of low scheduling overhead, but it is inflexible.
7)Multilevel Feedback Queue Scheduling
Multilevel feedback queue-scheduling algorithm allows a process to move between queues. It uses many ready queues and associate a different priority with each queue.
The Algorithm chooses to process with highest priority from the occupied queue and run that process either preemptively or unpreemptively. If the process uses too much CPU time it will moved to a lower-priority queue. Similarly, a process that wait too long in the lower-priority queue may be moved to a higher-priority queue. Note that this form of aging prevents starvation.
在此基础上我们了解下 Linux 内核主要运用到的三种调度策略:
1)SCHED_FIFO:注意与上面的 FIFO 区分。先入先出调度算法(实时调度策略,RT),相同优先级的任务先到先服务,高优先级的任务可以抢占低优先级的任务。
2)SCHED_RR:注意与上面的 RR 区分。轮转调度算法(实时调度策略,RT),采用时间片,相同优先级的任务当用完时间片会被放到队列尾部(与SCHED_FIFO的主要区别),以保证相同优先级的公平性。同样,高优先级的任务可以抢占低优先级的任务。
不同点:
当采用SHCED_RR策略的进程的时间片用完,系统将重新分配时间片,并置于就绪队列尾。放在队列尾保证了所有具有相同优先级的RR任务的调度公平。
SCHED_FIFO一旦占用cpu则一直运行,一直运行直到有更高优先级任务到达或自己放弃。
如果有相同优先级的实时进程(根据优先级计算的调度权值是一样的)已经准备好,FIFO时必须等待该进程主动放弃后才可以运行这个优先级相同的任务。而RR可以让每个任务都执行一段时间。
相同点:
RR和FIFO都只用于实时任务。
创建时优先级大于0(1-99)。
按照可抢占优先级调度算法进行。
就绪态的实时任务立即抢占非实时任务。
3)SCHED_NORMAL:也叫(SCHED_OTHER),用于普通任务,通过CFS调度器实现。
在内核中,进程优先级的取值范围是通过一个宏定义的,这个宏的名称是MAX_PRIO,它的值为140。
而这个值又是由另外两个值相加组成的,一个是代表nice值取值范围的NICE_WIDTH宏,另一个是代表实时进程(realtime)优先级范围的MAX_RT_PRIO宏。
说白了就是,Linux实际上实现了140个优先级范围,取值范围是从0-139,这个值越小,优先级越高。nice值的-20到19,映射到实际的优先级范围是100-139。
对于CFS策略,这个策略是在2008年被提出。在这个重新设计的调度器中,时间片,动态、静态优先级以及IO消耗,CPU消耗的概念都不再重要。CFS采用了一种全新的方式,对上述功能进行了比较完善的支持。其设计的基本思路是:我们想要实现一个对所有进程完全公平的调度器。
CFS策略里很重要的一个概念是:虚拟运行时(vruntime)
对于CFS来说,衡量的时间累积的绝对值都是一样纪录在vruntime中的,但是不同优先级的进程时间增长的比率是不同的,高优先级进程时间增长的慢,低优先级时间增长的快。比如,nice为19的进程,实际占用cpu为1秒,那么在vruntime中就记录1s。但是如果是-20的进程,那么它很可能实际占CPU用10s,在vruntime中才会纪录1s。CFS还包含睡眠公平概念以便确保那些目前没有运行的任务(例如,等待 I/O)在其最终需要时获得相当份额的处理器。
1)CFS如何实现pick next
所有可运行的任务通过不断地插入操作最终都存储在以时间为顺序的红黑树中,对处理器需求最多的任务(最小虚拟运行时)存储在树的左侧,处理器需求最少的任务(最大虚拟运行时)存储在树的右侧。 为了公平,CFS调度器会选择红黑树最左边的叶子节点作为下一个将获得cpu的任务。这样,树左侧的进程就被给予时间运行了。
2)tick中断
在CFS中,tick中断首先更新调度信息。然后调整当前进程在红黑树中的位置。调整完成后如果发现当前进程不再是最左边的叶子,就标记need_resched标志,中断返回时就会调用scheduler()完成进程切换。否则当前进程继续占用CPU。从这里可以看到 CFS抛弃了传统的时间片概念。Tick中断只需更新红黑树,以前的所有调度器都在tick中断中递减时间片,当时间片或者配额被用完时才触发优先级调整并重新调度。
3)红黑树键值计算
理解CFS的关键就是了解红黑树键值的计算方法。该键值由三个因子计算而得:一是进程已经占用的CPU时间;二是当前进程的nice值;三是当前的cpu负载。进程已经占用的CPU时间对键值的影响最大,其实很大程度上我们在理解CFS时可以简单地认为键值就等于进程已占用的 CPU时间。因此该值越大,键值越大,从而使得当前进程向红黑树的右侧移动。另外CFS规定,nice值为1的进程比nice值为0的进程多获得10%的 CPU时间。在计算键值时也考虑到这个因素,因此nice值越大,键值也越大。
关于进程调度,还可以参见《Linux的进程优先级NI和PR到底有什么区别》,这篇文章贴地气地讲述了Linux进程调度。
总之感觉跪了。。还需努力