操作系统4---接口以及实现
一,接口
1.接口的定义
用户使用计算机的三种方式:
1.命令行:即通过命令程序,linux系统中常用此种方式
2.图形按钮:通过鼠标点击等操作实现对计算机的操控。windows系统在这方面做的就非常优秀。这种方式通过消息框架程序和消息处理程序实现
3.应用程序
不管采用何种方式,我们都需要让操作系统和应用程序之间建立联系。如何建立连接 ? 操作系统接口
接口其实是一种抽象,比如插排,它将内部的电路全部封装起来,只提供两个插口,用电设备插上就能用;不用管插座内部是如何实现的。
操作系统接口也具有连接两个东西、屏蔽细节、方便用户使用的特点。它连接上层应用软件和底层硬件,屏蔽细节,用户直接通过程序(应用软件)使用计算机,方便用户使用。操作系统的接口其实就是一个个函数,知道它的功能然后直接调用就行,而不用管它内核里面是怎么实现的,因为这个函数是系统调用的,所以也称为系统调用。比如:write()、read()等等
2.接口的分类
操作系统接口的功能就是提供一个用户使用系统的界面。根据服务对象的不同,操作系统的接口可以划分为两类:一是供用户使用的用户级接口,二是供程序使用的程序级接口。
(1)用户接口
用户接口就是操作系统向用户提供的使用界面。分为脱机接口与交互式接口两种
(2) 程序接口
程序级接口是为程序访问系统资源而提供的,它由一组系统调用组成。系统调用(System Call)可以看作是由操作系统内核提供的一组广义指令。程序员在设计程序时,凡涉及到系统资源访问的操作,如文件读/写、数据输入/输出、网络传输等,都必须通过系统调用来实现。所以说,系统调用是操作系统提供给应用程序的唯一接口。
从层次上来看,用户接口属于高层接口,是用户与操作系统之间的接口。而程序接口则是低级接口,是任何核外程序(包括应用程序和系统程序)与操作系统内核之间的接口。用户接口的功能最终是通过程序接口来实现的。
二,系统调用的实现
思考下面这个问题:
========================
= main{} =
= {whoami();} =
=========================
=whoami() =
={printf(100,8)} =
="xxxxx" =
=========================
如图,上面一层是用户程序调用whoami,一个字符串“xxxxx”放在下一层操作系统内核中(系统引导时载入),取出来打印。
那用户为什么不可以直接从操作系统内核中那这个数据,直接显示 出来呢?他们不是都在内存中吗?
答案当然是否定的,因为操作系统不允许我们随意调用数据,不能随意jmp,否则我们机器不小心被病毒感染,就可能被盗取root密码并且可以修改它。
所以如何实现这层“不随意的调用”呢?
将内核程序和用户程序隔离
为了确保系统的安全性,计算机硬件通过一些方法来定义此时计算机是工作在内核态和用户态。
内核态可以访问用户态信息,而用户态不能访问内核态信息。
CPL(Current Privilege Level)寄存器表示当前程序执行在什么态,0表示内核态,3表示用户态;
DPL(Descriptor Privilege Level)寄存器表示即将访问的数据在什么段,同样0表示内核段,3表示用户段。
每一次jmp和mov都要访问GDT,DPL就在GDT中,CPL在CS选择子中。
系统初始化最后要推倒用户态去执行,这时将用户程序的CPL初始化结果是3,而head.s将操作系统内核里函数的DPL是0,所以用户对内核的访问权限不够。
每次访问数据的时候检查两个寄存器的大小关系,若DPL≥CPL,则可以访问,反之,则不能访问
执行ppt程序时处于用户态CPL=3无法访问内核态的DPL=0。
对于intel x86,硬件提供了“主动进入内核的方法“:中断指令int:
int指令将使得CS中的CPL改成0,“进入内核”,这是用户程序发起的调用内核的唯一方式。
系统调用的核心:
(1)用户程序中包含一段包好int指令的代码
(2)操作系统写中断处理,获取想调用程序的编号
(3)操作系统根据编号执行响应的代码
这种能够进入内核态的中断并不多,只有int 0x80可以
应用程序调用printf---->C库函数printf—>库函数write()—>系统OS内核调用write()
最终展开成包含int指令的代码:
#include <unistd.h>
_syscall3(int, write,int ,fd ,const char *buf , off_t ,count)#define _syscall3(type,name,...) typename(...) \{__asm__ ("int 0x80" : "=a"(__res)...}
int 0x80实现的细节
在linux/include/unistd.h中,对write有声明:
int write(int fildes, const char * buf, off_t count);
在write.c中
/** linux/lib/write.c** (C) 1991 Linus Torvalds*/
#define __LIBRARY__
#include <unistd.h>//定义write的实现
_syscall3(int,write,int,fd,const char *,buf,off_t,count)
为什么要有#define LIBRARY:
因为在unistd.h有
#ifdef __LIBRARY__/*中间省略*/#define __NR_write 4/*中间省略*///有3个參数的系统调用宏函数
#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) \: "0" (__NR_##name),"b" ((long)(a)),"c" ((long)(b)),"d" ((long)(c))); \if (__res>=0) \return (type) __res; \errno=-__res; \return -1; \
}#endif /* __LIBRARY__ */
为了搞懂这段代码的运行机制,做了如下简化:
这种宏的写法值得学习!
显然,__NR_write是系统调用号,放在eax中
#define __NR_write 4 // 一一堆连续正整数(数组下表,函数表索引)
同时eax也存放返回值,ebx,ecx,edx存放3个参数
将一个系统调用号置给eax然后调用0x80
int 0x80之后就意味着我们进入了内核态,这就是进入内核的唯一方法
int 0x80要查IDT表,和GDT表很像,查到中断要到哪儿个地方执行。int 0x80的中断的处理执行过程:
void sched_init(void)
{set_system_gate(0x80,&system_call); //设置中断处理门,此后0x80代表的中断处理函数就是system_call
}
linux/include/asm/system.h中
#define set_system_gate(n,addr) \ //n就是中断号,addr就是中断处理函数的地址_set_gate(&idt[n],15,3,addr); //idt是中断向量表基地址,DPL置为3,降低门槛了,用户程序CPL=3可以进来了
#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))), //gate_addr低四位"o"(*(4+(char*)(gate_addr))),\ //gate_addr高四位"d"((char*)(addr),"a"(0x00080000)) //
上面的代码就是在给IDT初始化,初始化后一般遇到0x80中断,就可以通过IDT表找到中断处理函数,从而执行中断处理
处理函数入口点偏移就是IDT中的每个表项
用段和偏移形成行的PC,此时CS=8,IP=system_call (还记得jmpi 0,8吗?) 8是内核的代码段
CS的最后两位bit 0 和bit 1就是CPL,CS等于8则CPL就变为0,也就是说DPL=3让用户态能进来之后又让CPL=0,就什么都可以做了。返回的时候CPL又会变为3
#在linux/kernel/system_call.s中:
nr_system_calls=72
.global _system_call
_system_call:cmpl $nr_system_calls-1,%eax //eax中存放的是系统调用号ja bad_sys_callpush %ds push %es push %fspushl $edx pushl pushl %ebx //调用的参数movl $0x10,%edxmov %dx,%dxmov %dx,%es //内核数据 0x10 16 内核的数据段movl $0x17,%edxmov %dx,%fs //fs可以找到用户数据call _sys_call_table(,%eax,4) //a(,%eax,4)=a+4*eax _sys_call_table+4*%eax就是系统调用处理函数的入口pushl %eax //返回值压栈,留着ret_from_sys_call时使用*** //其他代码
ret_from_sys_call:popl %eax,//还有其他popiret
在include/linux/sys.h中
fn_ptr sys_table[]={sys_setup,sys_exit,sys_fork,sys_read,sys_write,...} //sys_write对应的数组下表为4,__NR_write=4
在include/linux/sched.h中
typedef int (*fn_ptr)();
call_sys_call_table(,%eax,4)就是在call sys_write
综上所述-直观过程:
操作系统4---接口以及实现相关推荐
- LwIP 之三 操作系统隔离接口 sys_arch
目前,网络上多数文章所使用的 LwIP 版本为1.4.1.最新版本为 2.0.3.从 1.4.1 到 2.0.3(貌似从2.0.0开始), LwIP 的源码有了一定的变化,甚至于源码的文件结构也不 ...
- 超详细|一篇搞定操作系统——用户接口
文章目录 6.1 用户接口 6.2 其他特殊操作系统 6.2.1 嵌入式操作系统 6.2.2 分布式操作系统 操作系统全家桶:传送门 一.操作系统引述:https://blog.csdn.net/di ...
- 地址池命令 思科理由_思科互联网络操作系统 ——路由器接口
点击蓝字 关注我们 路由器接口 接口配置是最重要的路由器配置之一,因为若没有接口,路由器几乎就毫无用处.另外,要与其他设备通信,接口配置必须绝对精确.配置接口时,我们需要指定网络层地址.介质类型和带宽 ...
- 操作系统用户接口与计算机接口有什么区别,1.操作系统既是硬件与其他软件的接口,又是用户与计算机之间的接口。...
[判断题]以手指动作所需时间为一个单位时间成为10mod() [单选题]The Gilded Age in the States exerted either positive or negative ...
- 服务器系统装usb没有用,服务器全包安装RHEL6.x操作系统USB接口使用异常
问题描述 现场NF5466M5主机,产线预装操作系统RHEL6.7,软件包使用全包安装的方式,现场实施发现USB设备无法使用,并且有接入USB设备后宕机的情况.收集日志发现有如下报错. Sep 22 ...
- 20961操作系统接口
操作系统接口 9.1 用 户 接 口 9.1.1 字符显示式联机用户接口 不同的OS,其联机用户接口是不同的,即它们的命令形式和用法各不相同,甚至在同一系统中,命令的不同形式构成了不同的用户界面, ...
- linux操作系统实验教程费翔林,实验一操作系统接口实验.doc
实验一 操作系统交互式接口使用 (一)实验环境:linux 用户名和密码:user (二)实验的目的:了解linux的各种操作命令的使用 (三)实验要求 1.按照指导书完成各种命令的使用 2.写实验报 ...
- 操作系统2--操作系统结构
操作系统结构 操作系统的结构需要从这几个方面来考虑:他为用户提供了哪些服务和界面,系统各个组成部分及其相互关系 操作系统的操作 大致可分为:进程管理,主存管理,文件管理,辅存管理和IO管理 进程管理 ...
- 操作系统(科普章节)
目标 了解操作系统及作用 1. 操作系统(Operation System,OS) 一个例子说明操作系统 操作系统作为接口的示意图 没有安装操作系统的计算机,通常被称为裸机 如果想在裸机上运行自己所编 ...
- Nmap源码分析(操作系统扫描)
Nmap第四个核心功能是操作系统侦测,包括识别出操作系统类型.版本号.目标机硬件平台类型及附加信息(如TCP序号产生方式.IPID产生方式.启动时间等).目前Nmap 拥有丰富的系统指纹数据库 (nm ...
最新文章
- Apache配置文件的帮助查询
- FireWork 制作android 应用程序 icon
- 组合数学-- 放回取样基础公式证明
- select count(*) from返回的类型_数据分析面试题类型汇总
- 计算机绘图模型的参数方程,关于曲线绘图与运动控制问题的研究.doc
- 怎么在ASP.NET 2.0中使用Membership
- 安卓程序运行后控件不显示_智能镜子显示屏掀起了智能家居行业的新潮流
- 设计模式学习——代理模式(Proxy Pattern)
- Excel的设置 .net
- 软件工程 第三章 需求分析
- python--multiprocessing多进程总结
- 吉林大学计算机游戏程序设计,吉林大学在2018年大学生程序设计竞赛中夺得佳绩...
- 安装打印机时出现无法安装,打印处理器不存在
- 微信小程序使用iconfont图标 微信小程序上传图片
- python中import string是什么意思_python string是什么
- 网易云音乐下线:什么都想要,什么都别想要
- Python 条件控制 — if语句
- 龙芯3A4000 pmon编译方法
- JAVA classpath设置方式启动详解:java class名、java -jar
- 竖排文字垂直居中css样式