• 操作系统开发系列—13.g.操作系统的系统调用 ●


    在我们的操作系统中,已经存在的3个进程是运行在ring1上的,它们已经不能任意地使用某些指令,不能访问某些权限更高的内存区域,但如果一项任务需要这些使用指令或者内存区域时,只能通过系统调用来实现,它是应用程序和操作系统之间的桥梁。

    所以,一件事情就可能是应用程序做一部分,操作系统做一部分。这样,问题就又涉及特权级变换。

    很明显,这已经难不倒我们了,因为进程的切换就是不停地在重复这么一个特权级变换的过程。在那里,触发变换的是外部中断,我们把这个诱因换一下就可以了,变成"int nnn",一切就都解决了。

    我们来实现一个叫做int get_ticks()的函数,用这个函数来得到当前总共发生了多少次时钟中断。设置一个全局变量ticks,每发生一次时钟中断,它就加1,进程可以随时通过get_ticks()这个系统调用来得到这个值。

    见syscall.asm:

    _NR_get_ticks       equ 0 ; 要跟 global.c 中 sys_call_table 的定义相对应!
    INT_VECTOR_SYS_CALL equ 0x90
    
    global	get_ticks ; 导出符号
    
    bits 32
    [section .text]
    
    get_ticks:
    	mov	eax, _NR_get_ticks
    	int	INT_VECTOR_SYS_CALL
    	ret
    

    这里将系统调用对应的中断号设为0x90,它只要不和原来的中断号重复即可。

    马上来定义INT_VECTOR_SYS_CALL对应的中断门,protect.c:

    PUBLIC void init_prot()
    {
    ...
    	init_idt_desc(INT_VECTOR_SYS_CALL,	DA_386IGate,
    		      sys_call,			PRIVILEGE_USER);
    ...
    }
    

     这样我们就将第INT_VECTOR_SYS_CALL号中断与sys_call对应起来了。这里的call [sys_call_table+eax*4](调用的是sys_call_table[eax]),与irq_table类似,sys_call_table是一个函数指针数组,每一个成员都指向一个函数,用以处理相应的系统调用。

    extern	sys_call_table
    
    global sys_call
    
    sys_call:
            call    save
    
            sti
    
            call    [sys_call_table + eax * 4]
            mov     [esi + EAXREG - P_STACKBASE], eax
    
            cli
    
            ret
    

    前面eax已被赋值为_NR_get_ticks(即0),而sys_call_table[0]已经初始化为sys_get_ticks,所以call [sys_call_table+eax*4]这一句调用的便是sys_get_ticks。

    mov [esi+EAXREG-P_STACKBASE],eax是把函数sys_call_table[eax]的返回值放在进程表中eax的位置,以便进程P被恢复执行时eax中装的是正确的返回值。

    现在可以在进程中添加调用get_ticks的代码了:

    void TestA()
    {
    	int i = 0;
    	while (1) {
    		get_ticks();
    		disp_str("A");
    		disp_int(i++);
    		disp_str(".");
    		delay(1);
    	}
    }
    

    别忘了在kernel.asm和syscall.asm中导入和导出相应符号。

    修改

    void TestA()
    {
    	int i = 0;
    	while (1) {
    		disp_str("A");
    		disp_int(get_ticks());
    		disp_str(".");
    		delay(1);
    	}
    }
    

    运行如下,第一个是A0x0,第二个是A0x27,两次之间的“#”恰好是39个,我们的get_ticks一切正常:

     

    源码

  • 相关阅读:
    AnyVal与AnyRef
    安装Zookeeper
    Kafka
    ZooKeeper总结
    Idea中JDK为1.8,还提示Diamond types are not supported at this language level
    Hive 和 Mysql
    Spark练习代码
    响应状态码
    http简介
    csrf
  • 原文地址:https://www.cnblogs.com/joey-hua/p/5487034.html
Copyright © 2020-2023  润新知