您的位置:首页 > 运维架构 > Linux

Linux内核分析-系统中断在内核中的实现

2016-03-27 15:59 691 查看

分析system_call中断处理过程

在MenuOS中添加上周所运用到的系统调用

即在Linuxkernel/menu/test.c文件中,添加代码如下:

int Mkdir()
{
const  char *ch = "test"; //创建的文件夹名称
mode_t mode = 0700;        //创建的文件夹的权限
int flag = 0;        //是否创建成功新的文件夹的标识符
flag = mkdir(ch,mode);    //调用mkdir
if(flag==0)                //flag=0则创建成功,否则失败
{
printf("succeed");
}
else
printf("error");
return 0;
}
int MkdirAsm()
{
char *ch="test-asm"; //创建文件夹的名称
mode_t mode=S_IRWXU;  //创建新的文件夹的权限
int flag=0;            //标识符
asm volatile(
"mov $0x27,%%eax\n\t"    //系统调用号赋给eax寄存器
"mov %1,%%ebx\n\t"        //将文件夹的名称赋给ebx寄存器
"mov %2,%%ecx\n\t"        //将文件夹的权限赋给ecx寄存器
"int $0x80\n\t"            //开启中断,执行mkdir系统调用
"mov %%eax,%0\n\t"        //将返回值赋给flag
:"=m"(flag)                //输出变量flag
:"d"(ch),"D"(mode)        //输入变量ch与mode
);
if(flag==0)            //flag=0则创建成功,否则失败
printf("succeed");
else
printf("error");
return 0;
}

int main()
{
PrintMenuOS();
SetPrompt("MenuOS>>");
MenuConfig("version","XXX V1.0(Menu program v1.0 inside)",NULL);
MenuConfig("quit","Quit from XXX",Quit);
MenuConfig("mkdir","Make up a new director",Mkdir);
MenuConfig("Mkdirasm","Make up a new director by asm",MkdirAsm);
ExecuteMenu();
}


make rootfs即可完成功能的添加

gdb单步调试系统调用mkdir

设置断点:



在MenuOS界面输入mkdir,则发现停在了system_mkdir该函数处:



进行单步调试,发现其步骤大约为读取pathname(所需要创建文件夹的名称),配置权限,完成创建:



同理输入命令mkdirasm,完成单步调试,与mkdir一样的结果(因为都是调用系统调用mkdir)

输入c,将程序进行完,则出现最终结果:



system_call到iret的步骤

代码如下:

.macro INTERRUPT_RETURN ; 中断返回

iret

.endm

.macro SAVE_ALL ; 保护现场

...

.macro RESTORE_INT_REGS

...

.endm

ENTRY(system_call)
SAVE_ALL
syscall_call:
call *sys_call_table(,%eax,4)
movl %eax, PT_EAX(%esp)  ; store the return value
syscall exit:
testl $_TIF_ALLWORK_MASK, %ecx # current->work
jne syscall_exit_work
restore_all:
RESTORE_INT_REGS
irq_return:
INTERRUPT_RETURN      ; 到这里就算执行完了
ENDPROC(system_call)

syscall_exit_work:
testl  $_TIF_WORK_SYSCALL_EXIT, %ecx
jz work_pending
END(syscall_exit_work)

work_pending:
testb $_TIF_NEED_RESCHED, %cl
jz work_notifysig
work_resched:
call schedule
jz restore_all
work_notifysig:
...                  ; deal with pending signals
END(work_pending)


流程图如下:



SAVE_ALL宏可以在栈中保存中断处理程序可能会使用的所有CPU寄存器,以此起到保护现场的作用

根据sys_call_table查找所需要的中断程序的中断号,从而执行system_call

系统调用完成后,则执行iret结束该操作。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: