5系统调用system_call的处理过程

安大大 + 原创作品转载请注明出处 + 《Linux操作系统分析》MOOC课程

给MenuOS增加time和time-asm命令

按照老师的方式在实验楼里git clone不能成功,就直接copy进去了test.c这个文件里的内容。test.c中新增加了Time和TimeAsm两个函数,以及main函数中新增加了两条语句。

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();
}

然后make rootfs 直接自动编译自动生成根文件系统,而且启动起来MenuOS。



**help列表里新增加了time和time-asm命令**

给MenuOS增加新的命令的方式(如增加time和time-asm):

  1. 在main函数中增加MenuConfig
  2. 增加对应的Time函数和TimeAsm函数
  3. make rootfs

使用gdb跟踪系统调用内核函数sys_time

**启动qemu**
**打开gdb**
**把带有符号表的debug版本3.18内核加载进来,然后连接到需要调试的MenuOS里**
**b设置断点,c会执行到断点处停下来,list可以查看断点处附近的代码**
**在这个文件夹下通过syscall_32.tbl文件查看13号系统调用time对应的内核处理函数**
**13号系统调用time对应的内核处理函数是sys_time**
**设置sys_time断点,执行time命令,程序执行到断点处**
**list查看sys_time对应的代码**

在gdb调试过程中,n表示next,s表示step,区别在于n会跳过函数,s会进入到函数里。如果这里一直按n单步执行会进入 schedule函数

**单步执行会进入到get_seconds()函数里**
**finish执行完当前的函数**
**return i 获得的time的数值**
不知道为什么和老师的不一样,这里执行到了schedule函数

sys_time返回后进入汇编代码处理gdb无法继续跟踪

执行int 0x80之后执行system_call对应的代码

system_call也可以设置断点,time返回
gdb进不去system_call,只能停在sys_time

system_call 不是普通的函数,它是一段汇编代码,gdb还不能对其进行跟踪调试
思考题:怎么让系统停在system_call的位置进行调试

**在这个目录下entry_32.S**
**system_call是这段汇编代码的起点,gdb还不能跟踪**

系统调用在内核代码中的工作机制和初始化

**xyz和sys_xyz是通过系统调用号联系起来的,int 0x80和system_call是通过中断向量匹配起来的**

系统调用机制的初始化:

\init\main.c start_kernel

trap_init();

\arch\x86\kernel\traps.c

#ifdef CONFIG_X86_32
//系统调用的中断向量和system_call汇编代码的入口
//一旦执行int 0x80,CPU就跳转到system_call这个位置来执行
    set_system_trap_gate(SYSCALL_VECTOR, &system_call);
    set_bit(SYSCALL_VECTOR, used_vectors); 
#endif

系统调用的工作机制,一旦start_kernel初始化好之后,在代码中一旦出现int 0x80的指令,就会立即跳转到system_call这个位置。

entry_32.S部分代码:
//这段代码就是系统调用处理的过程,其它的中断过程也是与此类似
//系统调用就是一个特殊的中断,也存在保护现场和回复现场
ENTRY(system_call)//这是0x80之后的下一条指令
    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)//定义的系统调用的表,eax传递过来的就是系统调用号,在例子中就是调用的systime
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//退出之前,syscall_exit_work 
    //进入到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//iret(宏),系统调用过程到这里结束

当一个系统调用发生的时候,进入内核处理这个系统调用,由内核提供服务,当这个服务结束返回到用户态之前,即在系统调用返回之前,有可能发生进程调度(call schedule),进程调度的里边就会发生进程上下文的切换。
把内核可以抽象成很多种不同的中断处理过程的集合。

system_call到iret之间的处理过程流程图

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,290评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,107评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,872评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,415评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,453评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,784评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,927评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,691评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,137评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,472评论 2 326
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,622评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,289评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,887评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,741评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,316评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,490评论 2 348

推荐阅读更多精彩内容