韓巖___第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

 

 

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