操作系统接口&系统调用的实现

本文深入解析了操作系统接口的概念及其重要性,介绍了系统调用作为连接用户程序与内核的桥梁的作用,并详细阐述了其在Linux系统中的具体实现过程。

接口

连接两个东西,信号转换,屏蔽细节…

操作系统接口

连接上层用户和操作系统软件,方便了使用,屏蔽了细节。

操作系统接口的形式

为应用层提供一些重要的函数,如printf,write,read等。接口表现为函数调用,又由系统提供,所以称为系统调用(system call)。

操作系统接口的一个标准 POSIX

实现POSIX标准中要求的接口的操作系统,应用程序可以在它们之上无差别运行。
在这里插入图片描述

系统调用的实现思路

走系统调用这条路更加安全,如果对访问所有内存都不做区分,那么用户可以随意调用数据。随机jmp。甚至可以看到root密码并修改它。
操作系统将内核程序和用户程序隔离,设计出内核态和用户态。用户态必须通过系统调用才能进入内核态执行。用户态执行在用户段下
内核态执行在内核段下。
为了区分内核态和用户态,需要有一种处理器硬件设计,也就是处理器保护环:
在这里插入图片描述
硬件提供了主动进入内核的方法:
对于Intel x86,那就是中断指令:

  • int int指令将使CS中的CPL改成0, “进入内核
  • 这是用户程序发起的调用内核代码的唯一方式 (此时,CPL=3而 DPL=0)

系统调用的核心就是:

  • 用户程序中包含一段有int指令的代码
  • 操作系统中事先有中断处理函数,int指令后面就是这个处理函数所在的编号
  • 操作系统根据编号执行相应的中断处理函数

实际上 这个编号是固定的,系统调用的中断号为0x80

系统调用具体实现

以printf为例,应用程序调用printf,库函数printf内部有调用库函数write(),改函数内部会做系统调用write,在linux/lib/write.c中

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

#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) __resl
										errno=-__res;
										return -1;
								}

这段内嵌汇编,主要是将__NR_write放入eax中,a,b,c三个参数分别放到ebx,ecx,edx中。
__NR_write是以宏定义的形式放在unistd.h中的,值为4,这个号码指示了系统调用应该去执行write对应的处理函数。
函数处理完成后,返回值在eax中,通过__res变量拿到,最后return出去。
只要是三个参数的系统调用都可以使用_syscall3宏
现在来揭晓这段代码可以运作的前提

void sched_init(void)
{
	set_system_gate(0x80, &system_call;
}

sched_init中将0x80号中断处理函数设为system_call了。做这件事情的函数叫做set_system_gate,它的本质是设置中断向量表中的0x80所代表的表项,设置该表项中的各个字段,尤其是处理函数的入口点偏移为system_call的地址值
linux/include/asm/system.h

#define set_system_gate(n, addr)	\
		_set_gate(&idt[n], 15, 3,addr);		//idt是中断向量表的基址

#define _set_gate(gate_addr, type, dpl, addr)\
		__asm__(
			"movw %%dx, %%ax \n\t"
			"movw %0, %%dx\n\t"
			"movl %%eax, %1\n\t"
			"movl %%edx, %2"
			: 
			: "i"( (short)(0x8000+(dpl<<13)+type<<8)), "o"(*((char*)(gate_addr))), "o"(*(4+(char*)(gate_addr))),\
				 "d"((char*)(addr))), "a"(0x00080000))
		    );

在这里插入图片描述

整个过程的流程图

在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值