</pre><p></p><p><span style="color:rgb(51,51,51); font-family:'Microsoft YaHei'; font-size:14px; line-height:26px">张磊 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程</span><a target=_blank target="_blank" href="http://mooc.study.163.com/course/USTC-1000029000" style="color:rgb(51,102,153); text-decoration:none; font-family:'Microsoft YaHei'; font-size:14px; line-height:26px">http://mooc.study.163.com/course/USTC-1000029000</a></p><p><span style="font-family:Microsoft YaHei; color:#333333"><span style="font-size:14px; line-height:26px">课程调用测试代码如下:</span></span></p><p><span style="font-family:Microsoft YaHei; color:#333333"><span style="font-size:14px; line-height:26px"></span></span></p><pre name="code" class="cpp">#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "menu.h"
#define FONTSIZE 10
int PrintMenuOS()
{
int i, j;
char data_M[FONTSIZE][FONTSIZE] =
{
" ",
" * * ",
" *** *** ",
" * * * * ",
" * * * * ",
" * ** * ",
" * * ",
" * * ",
" * * ",
" "
};
char data_e[FONTSIZE][FONTSIZE] =
{
" ",
" ",
" ** ",
" * * ",
" * * ",
" ****** ",
" * ",
" * ",
" *** ",
" "
};
char data_n[FONTSIZE][FONTSIZE] =
{
" ",
" ",
" ** ",
" * * ",
" * * ",
" * * ",
" * * ",
" * * ",
" * * ",
" "
};
char data_u[FONTSIZE][FONTSIZE] =
{
" ",
" ",
" * * ",
" * * ",
" * * ",
" * * ",
" * * ",
" * ** ",
" ** * ",
" "
};
char data_O[FONTSIZE][FONTSIZE] =
{
" ",
" **** ",
" * * ",
" * * ",
" * * ",
" * * ",
" * * ",
" * * ",
" **** ",
" "
};
char data_S[FONTSIZE][FONTSIZE] =
{
" ",
" **** ",
" ** ",
" ** ",
" *** ",
" ** ",
" ** ",
" ** ",
" **** ",
" "
};
for(i=0; i<FONTSIZE; i++)
{
for(j=0; j<FONTSIZE; j++)
{
printf("%c", data_M[i][j]);
}
for(j=0; j<FONTSIZE; j++)
{
printf("%c", data_e[i][j]);
}
for(j=0; j<FONTSIZE; j++)
{
printf("%c", data_n[i][j]);
}
for(j=0; j<FONTSIZE; j++)
{
printf("%c", data_u[i][j]);
}
for(j=0; j<FONTSIZE; j++)
{
printf("%c", data_O[i][j]);
}
for(j=0; j<FONTSIZE; j++)
{
printf("%c", data_S[i][j]);
}
printf("\n");
}
return 0;
}
int Quit(int argc, char *argv[])
{
/* add XXX clean ops */
}
int Time(int argc, char *argv[])
{
time_t tt;
struct tm *t;
tt = time(NULL);
t = localtime(&tt);
printf("time:%d:%d:%d:%d:%d:%d\n",t->tm_year+1900, t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
return 0;
}
int TimeAsm(int argc, char *argv[])
{
time_t tt;
struct tm *t;
asm volatile(
"mov $0,%%ebx\n\t"
"mov $0xd,%%eax\n\t"
"int $0x80\n\t"
"mov %%eax,%0\n\t"
: "=m" (tt)
);
t = localtime(&tt);
printf("time:%d:%d:%d:%d:%d:%d\n",t->tm_year+1900, t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
return 0;
}
int main()
{
PrintMenuOS();
SetPrompt("MenuOS>>");
MenuConfig("version","MenuOS V1.0(Based on Linux 3.18.6)",NULL);
MenuConfig("quit","Quit from MenuOS",Quit);
MenuConfig("time","Show System Time",Time);
MenuConfig("time-asm","Show System Time(asm)",TimeAsm);
ExecuteMenu();
}
实验楼编译运行 gdb 调试程序:
1.rm menu -rf
2.git clone https://github.com/mengning/menu.git
3.cd menu
4.make rootfs
库函数触发中断后,会进入一个ENTRY(system_call)函数中
ENTRY(system_call)
RING0_INT_FRAME # can't unwind into user space anyway
ASM_CLAC
pushl_cfi %eax # save orig_eax
SAVE_ALL
GET_THREAD_INFO(%ebp)
# system call tracing in operation / emulation
testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%ebp)
jnz syscall_trace_entry
cmpl $(NR_syscalls), %eax
jae syscall_badsys
syscall_call:
call *sys_call_table(,%eax,4)
syscall_after_call:
movl %eax,PT_EAX(%esp) # store the return value
syscall_exit:
LOCKDEP_SYS_EXIT
DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don't miss an interrupt
# setting need_resched or sigpending
# between sampling and the iret
TRACE_IRQS_OFF
movl TI_flags(%ebp), %ecx
testl $_TIF_ALLWORK_MASK, %ecx # current->work
jne syscall_exit_work
restore_all:
TRACE_IRQS_IRET
restore_all_notrace:
#ifdef CONFIG_X86_ESPFIX32
movl PT_EFLAGS(%esp), %eax # mix EFLAGS, SS and CS
# Warning: PT_OLDSS(%esp) contains the wrong/random values if we
# are returning to the kernel.
# See comments in process.c:copy_thread() for details.
movb PT_OLDSS(%esp), %ah
movb PT_CS(%esp), %al
andl $(X86_EFLAGS_VM | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax
cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax
CFI_REMEMBER_STATE
je ldt_ss # returning to user-space with LDT SS
#endif
restore_nocheck:
RESTORE_REGS 4 # skip orig_eax/error_code
irq_return:
INTERRUPT_RETURN
.section .fixup,"ax"
挑几个重要的分析下:
<pre name="code" class="cpp" style="color: rgb(51, 51, 51); font-size: 14px; line-height: 26px;">SAVE_ALL //保存中断现场
movl %eax,PT_EAX(%esp) # store the return value //调用系统函数
syscall_exit_work //退出前返回状态
irq_return //结束整个系统调用函数 返回。