韩岩___第5课___《linux内核分析》MOOC课

system_call中断处理过程分析

         系统功能调用是操作系统提供给程序设计人员的一种服务。程序设计人员在编写程序时,可以利用系统调用来请求操作系统的服务。

         time系统调用过程

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 Linux3.18.6)",NULL);

   MenuConfig("quit","Quit from MenuOS",Quit);

   MenuConfig("time","Show System Time",Time);

   MenuConfig("time-asm","Show SystemTime(asm)",TimeAsm);   // 将实现的函数加入到命令列表中

   ExecuteMenu();                                                   // 最终执行体,等待用户交互

}

 

 

以下是注册及执行流程

/* add cmd to menu */

int MenuConfig(char * cmd, char * desc, int(*handler)())

{

   tDataNode* pNode = NULL;

   if ( head == NULL)

    {

       head = CreateLinkTable();

       pNode = (tDataNode*)malloc(sizeof(tDataNode));

       pNode->cmd = "help";

       pNode->desc = "Menu List";

       pNode->handler = Help;

       AddLinkTableNode(head,(tLinkTableNode *)pNode);

    }

   pNode = (tDataNode*)malloc(sizeof(tDataNode));

   pNode->cmd = cmd;

   pNode->desc = desc;

   pNode->handler = handler;

   AddLinkTableNode(head,(tLinkTableNode *)pNode);  // 关键在这里,添加到命令链表中

   return 0;

}

 

 

/* Menu Engine Execute */

int ExecuteMenu()  // 命令执行程序

{

   /*cmd line begins */

   while(1)

    {

                   intargc = 0;

                   char*argv[CMD_MAX_ARGV_NUM];

       char cmd[CMD_MAX_LEN];

                   char*pcmd = NULL;

       printf("%s",prompt);

       /* scanf("%s", cmd); */

                   pcmd= fgets(cmd, CMD_MAX_LEN, stdin);

                   if(pcmd== NULL)

                   {

                            continue;

                   }

       /* convert cmd to argc/argv */

                   pcmd= strtok(pcmd," ");

                   while(pcmd!= NULL && argc < CMD_MAX_ARGV_NUM)

                   {

                            argv[argc]= pcmd;

                            argc++;

                            pcmd= strtok(NULL," ");

                   }

       if(argc == 1)

       {

           int len = strlen(argv[0]);

           *(argv[0] + len - 1) = '\0';

       }

       tDataNode *p =(tDataNode*)SearchLinkTableNode(head,SearchConditon,(void*)argv[0]);

       if( p == NULL)

       {

           continue;

       }

       printf("%s - %s\n", p->cmd, p->desc);

       if(p->handler != NULL)

       {

           p->handler(argc, argv);   // 这里最终执行我们添加进命令链表的函数

       }

    }

}

 接着,步入正轨,具体了解调用流程:

       1.库函数触发中断,并给出系统调用号;2.操作系统通过中断描述符表找到对应的中断处理函数:

       于是我们看到了ENTRY(system_call)

        进一步找到对应的宏定义:/linux-3.18.6/include/linux/linkage.h

        #define ENTRY(name) \
                                               .
globl name ASM_NL \
                                                
ALIGN ASM_NL \

                                               name:

        这里有些不太理解,按照宏中显示此处便定义了标号system_call,但在后面却又看到system_call,希望理解的小伙伴可以告知,觉得这段主要起链接用途,还有个ENDPROC(system_call)与之对应

ENTRY(system_call)

         RING0_INT_FRAME                            # can't unwind intouser 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)

         jnzsyscall_trace_entry

         cmpl$(NR_syscalls), %eax

         jaesyscall_badsys

syscall_call:                                 

         call*sys_call_table(,%eax,4)  # 这里将真正调用对应的系统调用,调用号的意义在这里也表现出来了sys_call_table + 4 * %eax即为系统调用的地址

syscall_after_call:

         movl%eax,PT_EAX(%esp)                 # storethe 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

         movlTI_flags(%ebp), %ecx

         testl$_TIF_ALLWORK_MASK, %ecx         #current->work

         jnesyscall_exit_work

 

restore_all:

         TRACE_IRQS_IRET

restore_all_notrace:

#ifdef CONFIG_X86_ESPFIX32

         movlPT_EFLAGS(%esp), %eax         # mixEFLAGS, 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.

         movbPT_OLDSS(%esp), %ah

         movbPT_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

         jeldt_ss                      # returning touser-space with LDT SS

#endif

restore_nocheck:

         RESTORE_REGS4                       # skiporig_eax/error_code

irq_return:

         INTERRUPT_RETURN

  一下在附上系统调用表/linux-3.18.6/arch/frv/kernel/entry.S ,摘录了部分

###################################################################################################

         .balign               L1_CACHE_BYTES

         .globl                  system_call

system_call:

         LEDS                   0x6101

         movsg                psr,gr4                        ; enable exceptions

         ori              gr4,#PSR_ET,gr4

         movgs                gr4,psr

 

         sti              gr7,@(gr28,#REG_SYSCALLNO)

         sti.p          gr8,@(gr28,#REG_ORIG_GR8)

 

         subicc                gr7,#nr_syscalls,gr0,icc0

         bnc            icc0,#0,__syscall_badsys

 

         ldi              @(gr15,#TI_FLAGS),gr4

         andicc                gr4,#_TIF_SYSCALL_TRACE,gr0,icc0

         bne            icc0,#0,__syscall_trace_entry

 

__syscall_call:

         slli.p          gr7,#2,gr7

         sethi                   %hi(sys_call_table),gr5

         setlo                   %lo(sys_call_table),gr5

         ld               @(gr5,gr7),gr4

         calll           @(gr4,gr0)

 

 

###############################################################################

#

# return to interrupted process

#

###############################################################################

__syscall_exit:

         LEDS                   0x6300

 

         #keep current PSR in GR23

         movsg                psr,gr23

 

         ldi              @(gr28,#REG_PSR),gr22

 

         sti.p          gr8,@(gr28,#REG_GR(8))        ; save return value

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章