内核基础试题
1. 简答题。(各10分)
1.1 Spin Lock 相对于信号量的特点;在UP/MP/SMP这些不同环境下,Spin Lock的不同实现方法。
1.2 简要说明e2compr压缩文件系统的压缩策略;经其处理后,上层文件系统(EXT2/3等)是否会受到影响。
1.3 比较linux操作系统内核态和用户态的抢占性,及两者之间存在差异的原因。
1.4 linux2.2支持的最大进程数是多少,演进至2.4后,这一制约是如何克服的。
1.5 列举中断屏蔽的类型,并简单比较。
1.6 列举linux所要处理的定时/计数器(实际的外围硬件设备,不是指软件定时器),
及其用途。
2. 问答题。(各20分)
2.1 穷举在用户态空间,内核消息的获取方式、差异、以及差异的原因。
2.2 解释linux进程调度中的epoch概念,该机制的目的。
2.3 描述一个硬件中断信号发生,到为其注册的中断服务例程开始执行,之间所经过的
内核处理过程。并进一步分析,制约linux中断响应时间的因素存在于哪些方面。
2.4 比较底半机制(BH)和Tasklet的特点,及运行方面的差异。
2.5 说明引导过程中initrd.img和linuxrc作用,给出制作initrd.img的伪代码形式的流程。
2.6 在VFS层中如何区分设备文件和正规文件?
2.7 内核有几种方式访问硬件设备?
2.8 内核如何访问iomem?请举例说明。
3. 分析题。
3.1 系统时间设置问题。(10分)
同样采用date命令,目的在于修改系统时间,在不同的系统上却有不同的现象:
假定初始时间(T1)为03月01日16:00 2003年,期望的修改后时间(T2)为12月31日00:00 2002年,
<1> 在EDK系统中,执行命令 #date 123100002002,系统时间立即会变为T2;但系统重新启动之后,系统时间仍恢复为T1的时间区间:03月01日16:02 2003年,修改并未保留下来。
<2> 在RedHat7.2/8.0中,重复上述设置,系统重新启动之后,时间设置得到了保留,系统运行于T2的时间区间:12月31日00:02 2002年。请分析<1> 中所表现出的现象是由于什么原因造成的;
3.2 在大家相关于串口的工作中,可能会遇到这样的问题:(20分)
串口在发送数据时,不是连续且迅速地发送,而是以一个固定的节拍(10秒),且每次只发送等长度的一段数据,请列举可能造成这一问题的所有原因;
3.3 Oops分析。(50分)
以下是一段经过符号解析过的Oops信息,我们知道造成这个Oops的直接原因在于对于内核函数__wake_up的调用过程之中出现了问题;基于上述判断,请基于已经给出的__wake_up相关源码和反汇编码,大致分析问题出现在哪个源码行,并给出分析结论;
———————————————————–
ksymoops信息:
ksymoops2.4.4on i686 2.2.19-rthal3. Options used
-v /usr/src/linux-2.2.19/vmlinux (specified)
-k /proc/ksyms (specified)
-l /proc/modules (specified)
-o /lib/modules/2.2.19-rthal3/ (default)
-m /usr/src/linux-2.2.19/System.map (specified)
current->tss.cr3 = 07d29000, %cr3 = 07d29000
*pde = 00000000
Oops: 0000
CPU: 0
EIP: 0010:[<C01110C1>]
Using defaults from ksymoops -t elf32-i386 -a i386
eax: 00000014 ebx: c0eabf74 ecx: 00000013 edx: 00000021
esi: 00000000 edi: 00000020 ebp: c0eabf6cesp: c0eabf60
ds: 0018 es: 0018 ss: 0018
Process in.identd (pid: 828, process nr: 6, stackpage=c0eab000)
Stack:00000000 c807ca0400000021 c0eabf74 c807be21 c0eabfb0 c807bf74
c807c940
00000000 0000000000000000 c803fb60 c807e000 00000e20 2b124c28
0000027c
0010a000 c807c900 000000000000f944 bffff944 c803d2ec 00000000
00000000
Call Trace: [<c807ca04>] [<c807be21>] [<c807bf74>] [<c807c940>]
[<c803fb60>] [<c807e000>]
[<c807c900>] [<c803d2ec>] [<c803c0a0>]
Code: 8b 02 85 45 fc 74 1b 85 ff 74 10 837a44 00 740a85 f6 75
>>EIP; c01110c1 <__wake_up+2d/6c> <=====
Trace; c807ca04 <[rt_das]timeout+c4/c8>
Trace; c807be21 <[rt_das]read_timeout+25/28>
Trace; c807bf74 <[rt_das]pulse_isr+150/19c>
Trace; c807c940 <[rt_das]timeout+0/c8>
Trace; c803fb60 <[rtai]global_irq_handler+0/80>
Trace; c807e000 <.bss.end+14a1/????>
Trace; c807c900 <[rt_das]board+0/28>
Trace; c803d2ec <[rtai]dispatch_global_irq+28/90>
Trace; c803c0a0 <[rtai]GLOBAL0_interrupt+18/34>
Code; c01110c1 <__wake_up+2d/6c>
00000000 <_EIP>:
Code; c01110c1 <__wake_up+2d/6c> <=====
0: 8b 02 movl (%edx),%eax <=====
Code; c01110c3 <__wake_up+2f/6c>
2: 85 45 fc testl %eax,0xfffffffc(%ebp)
Code; c01110c6 <__wake_up+32/6c>
5: 74 1b je 22 <_EIP+0×22> c01110e3
<__wake_up+4f/6c>
Code; c01110c8 <__wake_up+34/6c>
7: 85 ff testl %edi,%edi
Code; c01110ca <__wake_up+36/6c>
9: 74 10 je 1b <_EIP+0×1b> c01110dc
<__wake_up+48/6c>
Code; c01110cc <__wake_up+38/6c>
b: 837a44 00 cmpl $0×0,0×44(%edx)
Code; c01110d0 <__wake_up+3c/6c>
f: 740aje 1b <_EIP+0×1b> c01110dc
<__wake_up+48/6c>
Code; c01110d2 <__wake_up+3e/6c>
11:85 f6 testl %esi,%esi
Code; c01110d4 <__wake_up+40/6c>
13: 75 00 jne 15 <_EIP+0×15> c01110d6
<__wake_up+42/6c>
Unable to handle kernel paging request at virtual address 66fe4603
current->tss.cr3 = 00e94000, %cr3 = 00e94000
*pde = 00000000
Oops: 0000
CPU: 0
EIP: 0010:[<c01113e6>]
EFLAGS:00010a83
Warning (Oops_read): Code line not seen, dumping what data is available
>>EIP; c01113e6 <interruptible_sleep_on+5a/78> <=====
1 warning issued. Results may not be reliable.
<附录>
1. __wake_up的源码:
void __wake_up(struct wait_queue **q, unsigned int mode)
{
struct task_struct *p, *best_exclusive;
struct wait_queue *head, *next;
unsigned int do_exclusive;
if (!q)
goto out;
/*
* this is safe to be done before the check because it
* means no deference, just pointer operations.
*/
head = WAIT_QUEUE_HEAD(q);
read_lock(&waitqueue_lock);
next = *q;
if (!next)
goto out_unlock;
best_exclusive = 0;
do_exclusive = mode & TASK_EXCLUSIVE;
while (next != head) {
p = next->task;
next = next->next;
if (p->state & mode) {
if (do_exclusive && p->task_exclusive) {
if (best_exclusive == NULL)
best_exclusive = p;
}
else {
wake_up_process(p);
}
}
}
if (best_exclusive)
wake_up_process(best_exclusive);
out_unlock:
read_unlock(&waitqueue_lock);
out:
return;
}
2. __wake_up的反汇编码:
c0111094 <__wake_up>:
c0111094: 55 pushl %ebp
c0111095: 89 e5 movl %esp,%ebp
c0111097: 83 ec 08 subl $0×8,%esp
c011109a: 57 pushl %edi
c011109b: 56 pushl %esi
c011109c: 53 pushl %ebx
c011109d: 89 55 fc movl %edx,0xfffffffc(%ebp)
c01110a0:85 c0 testl %eax,%eax
c01110a2: 74 50 je c01110f4 <__wake_up+0×60>
c01110a4: 8d 48 fc leal 0xfffffffc(%eax),%ecx
c01110a7: 89 4d f8 movl %ecx,0xfffffff8(%ebp)
c01110aa: 8b 18 movl (%eax),%ebx
c01110ac: 85 db testl %ebx,%ebx
c01110ae: 74 44 je c01110f4 <__wake_up+0×60>
c01110b0:31 f6 xorl %esi,%esi
c01110b2: 89 d7 movl %edx,%edi
c01110b4: 83 e7 20 andl $0×20,%edi
c01110b7: 39 cb cmpl %ecx,%ebx
c01110b9: 74 2d je c01110e8 <__wake_up+0×54>
c01110bb: 90 nop
c01110bc: 8b 13 movl (%ebx),%edx
c01110be: 8b 5b 04 movl 0×4(%ebx),%ebx
c01110c1: 8b 02 movl (%edx),%eax
c01110c3: 85 45 fc testl %eax,0xfffffffc(%ebp)
c01110c6: 74 1b je c01110e3 <__wake_up+0×4f>
c01110c8: 85 ff testl %edi,%edi
c01110ca: 74 10 je c01110dc <__wake_up+0×48>
c01110cc: 837a44 00 cmpl $0×0,0×44(%edx)
c01110d0: 740aje c01110dc <__wake_up+0×48>
c01110d2:85 f6 testl %esi,%esi
c01110d4: 75 0d jne c01110e3 <__wake_up+0×4f>
c01110d6: 89 d6 movl %edx,%esi
c01110d8: eb 09 jmp c01110e3 <__wake_up+0×4f>
c01110da:89 f6 movl %esi,%esi
c01110dc: 89 d0 movl %edx,%eax
c01110de: e8 2d f9 ff ff call c0110a10 <wake_up_process>
c01110e3: 3b 5d f8 cmpl 0xfffffff8(%ebp),%ebx
c01110e6: 75 d4 jne c01110bc <__wake_up+0×28>
c01110e8:85 f6 testl %esi,%esi
c01110ea: 74 08 je c01110f4 <__wake_up+0×60>
c01110ec:89 f0 movl %esi,%eax
c01110ee: e8 1d f9 ff ff call c0110a10 <wake_up_process>
c01110f3: 90 nop
c01110f4: 8d 65 ec leal 0xffffffec(%ebp),%esp
c01110f7: 5b popl %ebx
c01110f8: 5e popl %esi
c01110f9:5fpopl %edi
c01110fa: 89 ec movl %ebp,%esp
c01110fc: 5d popl %ebp
c01110fd: c3 ret
c01110fe:89 f6 movl %esi,%esi
———————————————————–
内核驱动题
以下设计应该包括设计文档,实现策略说明,代码包,测试用例,使用说明.要求:按照综合编程题目的要求编写代码和文档。
参考资料: <Linux设备驱动程序>第二版.
1.设计并实现一个软件watchdog设备,以监视系统运行情况.(50分)
说明:watchdog设备用于监测系统运行状态,正常运行的系统定期写watchdog以使其不会超时,一旦超时,意味系统已挂起;watchdog应该重启系统. 现在的软件watchdog不重启系统,只用于监视应用程序的运行.
2.设计并实现一个简化的、容量可以变化的内存FIFO设备.(50分)