系統功能調用是操作系統提供給程序設計人員的一種服務。程序設計人員在編寫程序時,可以利用系統調用來請求操作系統的服務。
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