随笔:操作系统:系统调用的实现

1.用户态与内核态:

*将内核程序与用户程序隔离!

内核态能访问任何数据,用户态不能访问内核数据。

当前程序执行在什么态?因CS:IP是当前指令,故用CS的最低两位来表示:0是内核态(00),3是用户态(11)


2.中断指令:int

Intel x86中,中断指令:int

将使CS中的CPL改为0,进入内核。这是用户程序(CPL=3,DPL=0)发起的调用内核代码的唯一方式

*系统调用:

(1)用户程序中包含一段包含int指令的代码

(2)操作系统写中断处理,获取想调程序的编号

(3)操作系统根据编号执行相应代码

过程:

应用程序:
	调用printf(xxx)
c函数库:
	库函数printf(xxx)
	库函数write(xxx)
os内核:
	系统调用write(xxx)
	

linux/lib/write.c

#include <unistd.h>
_syscall3(int, write, int, fd, const char *buf, off_t, count)
linux/include/unistd.h

define _syscall3(type, name, atype, a ,btype, b, ctype, c)
type name(atype a ,btype b, ctype c) {
	long_res;
	__asm__ volatile("int 0x80":"=a(__res)":""(__NR__##name),"b"((long)(a)),"c"((long)(b)),"d"((long)(c)));
	if(__res>=0)
		return (type)__res;
	errno =-__res;
	return -1;
}
#define __NR_write 4 /* __NR_write 是系统调用号,放在eax中;同时eax也存放返回值。ebx,ecx,edx存放3个参数*/
void sched_init(void) {
	set_system_gate(0x80,&system_call);
}
用于设置0x80的中断处理
linux/include/asm/system.h

#define set_system_gate(n, addr)
_set_gate(&ide[n],15,3,addr); idt是中断向量表基址
#difine _set_gate(gate_addr, type, dp1, addr)
__asm__("movw %%ax\n\t" "movw %0,%%dx\n\t" "mov1 %%eax,%1\n\t" "mov1 %%edx,%2"::"i"((short)(0x8000+(dpl<<13)+type<<8))),
"o"(*((char *)(gate_addr))), "o"(*(4+(char *)(gate_addr))),"d"((char *)(addr),"a"(0x00080000))
linux/kernel/system_call.s

nr_system_calls=72
.globl _system_call /* 中断处理程序 */
_system_call: cmpl $nr_system_calls-1,%eax /* %eax存放系统调用号 */
	ja bad_sys_call
	push %ds	push %es	push %fs
	push1 %edx	push1 %ecx	push1 %ebx	/* 调用的参数 */
	mov1 $0x10,%edx		mov %dx,%ds		mov %ds,%es /* 内核数据 */
	mov1 $0x17,%edx		mov %dx,%fs		/* fs找到用户数据 */
	call _system_call_table(,%eax,4) 	/* ex:a(,%eax,4)=a+4*eax */
	push1 %eax	/* 返回值压栈,被ret_from_sys_call使用 */
	...
	
ret_from_sys_call: popl %eax,(其他的pop),iret
_sys_call_table+4*%eax 即为相应系统调用处理函数的入口
include/linux/sys.h

fn_ptr _sys_call_table[]= /* _system_call_table是一个全局函数数组 */
{
	sys_setup, sys_exit, sys_fork, sys_read, sys_write,...
};
include/linux/sched.h

typedef int (fn_ptr *)();
call sys_table(,%eax,4)即为 call sys_write

用户态 内核态
printf
用户调用
->printf 展成int 0x80->system_call 中断处理->sys_call_table 查表->__NR_write=4->调用 sys_write







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实验报告撰写要求 实验报告要求具有以下内容: 一、实验目的 二、实验内容 三、实验要求 四、算法流程图 五、给出测试数据及运行结果 六、实验体会或对改进实验的建议 实验1 进程调度 一、实验目的 通过实验加强对进程调度算法的理解和掌握。 二、实验内容 编写程序实现基于优先级的时间片轮转调度算法。 三、实验要求 1、假定系统有5个进程,每个进程用一个进程控制块PCB来代表,进程控制块的结构如下图1.1所示: 进程名 优先级 要求运行时间 已运行时间 进程状态 指针 图1.1 其中: 进程名:作为进程的标识,假设五个进程的进程名分别为p1,p2,p3,p4,p5。 指针:进程按顺序排成循环链表,用指针指出下一个进程的进程控制块首地址,最后一个进程中的指针指出第一个进程的进程控制块首地址。 要求运行时间:假设进程需要运行的单位时间数。 已运行时间:假设进程已经运行的单位时间数,初值为0。 状态:可假设有两种状态,就绪状态和结束状态。进程的初始状态都为就绪状态。 2、每次运行所设计的处理器调度程序调度进程之前,为每个进程随机确定它的要求运行时间。 3、此程序是模拟处理器调度,因此,被选中的进程并不实际启动运行,而是执行 已运行时间+1 来模拟进程的一次运行,表示进程已经运行过一个单位时间。 4、在所设计的程序中应有显示语句,能显示每次被选中的进程名以及运行一次后进程队列的变化。 5、优先级可自己给出初始值,但要求采用动态优先级,可自己设计优先数如何变化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值