Linux内核分析——系统调用(上)

pianogirl 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

一、用户态、内核态、中断处理机制

intel x86 CPU有四个权限分级,0-3。Linux只取两种,0是内核态,3是用户态。区分权限级别使得系统更加稳定。

1.内核态

  • 高执行级别,代码可以执行特权指令,访问任意的物理地址。
  • 判断依据1:cs:eip。[代码段选择寄存器:偏移量寄存器]
    cs寄存器的最低两位为00,表示当前代码的特权为系统级别。
  • 判断依据2:访问的逻辑地址。0xc0000000以上的空间只能在内核态下访问。

2.用户态

  • 代码只能在级别允许的特定范围内活动。在日常操作下,执行系统调用的方式是通过库函数,库函数封装系统调用,为用户提供接口以便直接使用。
  • 判断依据1:cs:eip。[代码段选择寄存器:偏移量寄存器]
    cs寄存器的最低两位为11,表示当前代码的特权为用户级别。
  • 判断依据2:访问的逻辑地址。用户态只能访问0x00000000-0xbfffffff的空间。

3、两者如何切换?

Linux中,系统调用是用户空间访问内核的唯一手段。
除异常和陷入外,它们是内核唯一的合法入口。

4、中断

由于是不同操作级别的切换,所以需要在内核空间另辟一块栈空间,同时把用户空间栈的位置等信息保存下来。即:

用户态到内核态的切换:必须保存用户态的寄存器上下文,包括用户态栈顶地址、当时的状态字、cs:eip的值,以及内核态的栈顶地址、当时的状态字、中断处理程序入口。
这里写图片描述

二、系统调用

这张图非常清晰地描述了系统调用的层次和原理。
这里写图片描述
系统调用总控程序(system_call)是操作系统提供给应用程序的一个特殊接口,特殊之处在于是利用软中断陷入内核。对i386的CPU,就是执行INT 0x80中断(“系统调用”),同时将CPU切换到核心态。
进程在执行陷入前把系统调用号装入eax,接着系统调用总控程序负责将系统调用号派发到各自的服务例程,然后调用它执行。
这里写图片描述

三、实验

1、fork()用法

fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程。两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。

这里写图片描述

fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:

在父进程中,fork返回新创建子进程的进程ID;
在子进程中,fork返回0;
如果出现错误,fork返回一个负值;

2、代码

fork.c:

#include <unistd.h>
#include <stdio.h>
int main ()
{
    pid_t fpid;

    fpid = fork();
    if (fpid < 0)
        printf("error in fork!");
    else if (fpid == 0) {
        printf("i am the child process, my process id is %d\n",getpid());
    }
    else {
        printf("i am the parent process, my process id is %d\n",getpid());
    }
    return 0;
}

fork_asm.c: 将这一句系统调用替换成嵌入式汇编:

fpid = fork();

asm volatile (
            "mov $0x2, %%eax\n\t"//把2号系统调用号放入eax
            "int $0x80\n\t" //触发0x80号软中断
            "mov %%eax, %0\n\t"  //将eax中的返回值写入fpid
            : "=m" (fpid)
            );

3、实验截图

这里写图片描述
每执行一次fork,都会产生两个进程,父进程、子进程各自打印自己的信息。

四、思考

  1. 关于内核态和用户态。学习的重点和主题是内核。用户界面是操作系统的外在表象,内核才是操作系统的内在核心。根据操作、访问权限的不同,划分为内核态和用户态。打个比方,图书馆中,读者可以自由地检索目录、阅读书籍,却无权直接去书库取书,也无权修改图书馆的数据库。而工作人员就在特权状态,可以访问任意资源。这样的划分是为了系统的稳定和安全,也是免去了用户和系统底层打交道的麻烦。
  2. 在系统中运行的应用程序通过系统调用与内核通信,也是通过系统调用界面陷入内核。而“接口”是实现的关键。图书馆中,读者想要借书时,只能填写借书单,由工作人员完成登记和取书工作。“借书单”起到了一个“接口”的作用。

    参考资料:《Linux操作系统原理》
    http://blog.csdn.net/jason314/article/details/5640969

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值