Hello World 5

本文装载自:http://www.cnblogs.com/xuqiang/archive/2010/03/29/1953689.html

微笑

系统调用实现

参考文章:

http://docs.huihoo.com/joyfire.net/6-1.html

 

操作系统为在用户态运行的进程与硬件的通信提供了一组接口,然而用户进程是不能直接和硬件交互的,而是通过系统调用来实现和硬件的交互。

 

首先来说明的是“用户态”和“内核态”。

http://blog.csdn.net/fatsandwich/archive/2008/02/29/2131707.aspx

当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态(或简称为内核态)。此时处理器处于特权级最高的(0级)内核代码中执行。当进程处于内核态时,执行的内核代码会使用当前进程的内核栈。每个进程都有自己的内核栈。当进程在执行用户自己的代码时,则称其处于用户运行态(用户态)。即此时处理器在特权级最低的(3级)用户代码中运行。当正在执行用户程序而突然被中断程序中断时,此时用户程序也可以象征性地称为处于进程的内核态。因为中断处理程序将使用当前进程的内核栈。这与处于内核态的进程的状态有些类似。 

内核态与用户态是操作系统的两种运行级别,跟intel cpu没有必然的联系, intel cpu提供Ring0-Ring3三种级别的运行模式,Ring0级别最高,Ring3最低。Linux使用了Ring3级别运行用户态,Ring0作为 内核态,没有使用Ring1和Ring2。Ring3状态不能访问Ring0的地址空间,包括代码和数据。Linux进程的4GB地址空间,3G-4G部 分大家是共享的,是内核态的地址空间,这里存放在整个内核的代码和所有的内核模块,以及内核所维护

的数据。用户运行一个程序,该程序所创建的进程开始是运 行在用户态的,如果要执行文件操作,网络数据发送等操作,必须通过write,send等系统调用,这些系统调用会调用内核中的代码来完成操作,这时,必 须切换到Ring0,然后进入3GB-4GB中的内核地址空间去执行这些代码完成操作,完成后,切换回Ring3,回到用户态。这样,用户态的程序就不能 随意操作内核地址空间,具有一定的安全保护作用。
    至于说保护模式,是说通过内存页表操作等机制,保证进程间的地址空间不会互相冲突,一个进程的操作不会修改另一个进程的地址空间中的数据。

 

总结上面的:由于intel cpu的硬件保护机制的存在,在特权级低的情况下,进程是不能访问一些操作系统资源的,所以linux采用了系统调用的机制来允许应用进程来访问一些硬件资源。所有的进程是共享的一个内核空间的实际物理ram。

 

http://tmdnet.nothave.com/man/aka/Lecture-4/index.html

中断通常是被定义为一个事件,该事件改编程序执行的顺序,这是与cpu的硬件是相关的。在每种平台上,都有特定的指令可以使进程的执行由用户态转换为核心态,这种指令称作操作系统陷入。进程通过陷入指令便进入了内核态。

 

linux系统的中断的硬件基础首先是idt表。中断描述符表idt是一个系统表,它与每个中断异常向量相联系,在intel的cpu中使用寄存器idtr来保存idt表在内存中的位置。

 

当执行了一条指令之后,cs和eip寄存器会指向下一条将要执行的指令的逻辑地址,在执行那条指令之前,cpu会检查时候发生了中断或者是异常,如果发生了中断或者是异常的话。

 

1.确定中断或者是异常相关联的i

2.读取idt中的第i项(其中保存的是中断描述符)

3.从gdt中查找gdt基址,在gdt中查找,读取idt表项中的选择描述符所标识的段描述符,这个描述符指定了中断处理程序所在的段的基址。事实上

idt的初始化在系统启动时,对INT 0x80进行一定的初始化。

 

使用汇编子程序setup_idt(linux/arch/i386/kernel/head.S)初始化idt表(中断描述符表),这时所有的入口函数偏移地址都被设为ignore_int

setup_idt:

lea ignore_int,%edx

movl $(__KERNEL_CS << 16),%eax

movw %dx,%ax /* selector = 0x0010 = cs */

movw $0x8E00,%dx /* interrupt gate - dpl=0, present */

lea SYMBOL_NAME(idt_table),%edi

mov $256,%ecx

rp_sidt:

movl %eax,(%edi)

movl %edx,4(%edi)

addl $8,%edi

dec %ecx

jne rp_sidt

ret

selector = __KERNEL_CS, DPL = 0, TYPE = E, P = 1);

 

Start_kernel()(linux/init/main.c)调用trap_init()(linux/arch/i386/kernel/trap.c)函数设置中断描述符表。在该函数里,实际上是通过调用函数set_system_gate(SYSCALL_VECTOR,&system_call)来完成该项的设置的。其中的SYSCALL_VECTOR就是0x80,而system_call则是一个汇编子函数,它即是中断0x80的处理函数,主要完成两项工作:a. 寄存器上下文的保存;b. 跳转到系统调用处理函数。

 

 

4.确定中断源的特权级能够发出这个中断

5.检查是否发生了特权级的变化,如果需要的话,改变特权级。

6.保存相关寄存器

7.现在装载cs和eip,从而指定了中断的处理程序的第一条指令

 

现在程序已经执行到了system_call:

8.保存相关的寄存器

9.判断当前调用是否是合法系统调用(EAX是系统调用号,它应该小于NR_syscalls)

10.在系统调用表sys_call_table中查找处理函数入口地址,并跳转到该入口地址。 

于是开始中断处理函数。

 

现在中断处理程序开始运行。。。。

 

当中断处理程序执行完毕之后,开始中断返回。其中最主要的就是:使用用RESTORE_ALL来弹出所有被SAVE_ALL压入核心栈的内容并且使用iret返回用户态。

 

当然上面的过程中忽略了中断中一个比较重要的部分“参数的传递”:

SAVE_ALL是系统调用参数的传入过程,当执行完SAVE_ALL并且再由CALL指令调用其处理函数时,堆栈的结构应该如上图所示。这时的堆栈结构看起来和执行一个普通带参数的函数调用是一样的,参数在堆栈中对应的顺序是(arg1, ebx),(arg2, ecx),(arg3, edx). . . . . .,这正是SAVE_ALL压栈的反顺序,这些参数正是用户在使用系统调用时试图传送给核心的参数。

 

总结上面:显然在内核态中的中断处理函数使用“寄存器”来传递参数。现在来看一个例子:

int sys_write (unsigned int fd, const char* buf, unsigned int count)

显然在执行这个函数时(运行在内核态),该函数需要在栈顶的位置寻找函数的参数。所以需要在SAVE_ALL宏之后,还需要保存其他的寄存器,

http://blog.csdn.net/TopEmbedded/archive/2009/02/24/3933683.aspx

“这样就意味着我们只要巧妙地设置好堆栈,让sys_fork()产生一种错觉,好像是上层的一个函数直接调用sys_fork()一样。事实上sys_fork()也的确可以在内核态直接调用。”

 ”通过巧妙的构造堆栈,达到调用内核函数的目的。“

 

好吧整个中断就算完成了。。。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ava实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),可运行高分资源 Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。下面详细介绍C语言的基本概念和语法。 1. 变量和数据类型 在C语言中,变量用于存储数据,数据类型用于定义变量的类型和范围。C语言支持多种数据类型,包括基本数据类型(如int、float、char等)和复合数据类型(如结构体、联合等)。 2. 运算符 C语言中常用的运算符包括算术运算符(如+、、、/等)、关系运算符(如==、!=、、=、<、<=等)、逻辑运算符(如&&、||、!等)。此外,还有位运算符(如&、|、^等)和指针运算符(如、等)。 3. 控制结构 C语言中常用的控制结构包括if语句、循环语句(如for、while等)和switch语句。通过这些控制结构,可以实现程序的分支、循环和多路选择等功能。 4. 函数 函数是C语言中用于封装代码的单元,可以实现代码的复用和模块化。C语言中定义函数使用关键字“void”或返回值类型(如int、float等),并通过“{”和“}”括起来的代码块来实现函数的功能。 5. 指针 指针是C语言中用于存储变量地址的变量。通过指针,可以实现对内存的间接访问和修改。C语言中定义指针使用星号()符号,指向数组、字符串和结构体等数据结构时,还需要注意数组名和字符串常量的特殊性质。 6. 数组和字符串 数组是C语言中用于存储同类型数据的结构,可以通过索引访问和修改数组中的元素。字符串是C语言中用于存储文本数据的特殊类型,通常以字符串常量的形式出现,用双引号("...")括起来,末尾自动添加'\0'字符。 7. 结构体和联合 结构体和联合是C语言中用于存储不同类型数据的复合数据类型。结构体由多个成员组成,每个成员可以是不同的数据类型;联合由多个变量组成,它们共用同一块内存空间。通过结构体和联合,可以实现数据的封装和抽象。 8. 文件操作 C语言中通过文件操作函数(如fopen、fclose、fread、fwrite等)实现对文件的读写操作。文件操作函数通常返回文件指针,用于表示打开的文件。通过文件指针,可以进行文件的定位、读写等操作。 总之,C语言是一种功能强大、灵活高效的编程语言,广泛应用于各种领域。掌握C语言的基本语法和数据结构,可以为编程学习和实践打下坚实的基础。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值