《Linux内核设计与实现》课本第五章学习笔记

By20135203齐岳

与内核通信

用户空间进程和硬件设备之间通过系统调用来交互,其主要作用有三个。

  • 为用户空间提供了硬件的抽象接口。
  • 保证了系统的稳定和安全。
  • 实现多任务和虚拟内存。保证良好的稳定性和安全性。

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

API、POSIX和C库

应用程序通过在用户空间实现的应用编程接口(API)而非直接通过系统调用来编程。

POSIX是应用编程接口的一个国际标准,C库提供了POSIX的绝大部分API。

Unix接口设计的特点:提供机制(需要实现什么功能)而非策略(怎样实现这些功能)。Unix系统调用抽象出了用于完成某种确定的目的的函数,而至于函数是如何实现功能的则并不关心,从程序员的角度来看,只需通过接口便可实现功能。

系统调用

要访问系统调用,通常通过C库定义的函数调用来进行。例如,getpid()系统调用,在内核中的实现为:

SYSCALL_DEFINED0(getpid)
{
return task_tgid_vnr(current);//return current->tgid
}

SYSCALL _ DEFINED0只是一个宏,定义一个无参数的系统调用,展开后的代码如下

asmlinkage long sys_getpid(void)

asmlinkage为限定词,是一个编译指令,通知编译器仅从栈中提取该函数的参数。函数返回值在用户态时为int,在内核态为long。

系统调用号

在Linux系统中每个系统调用被赋予一个系统调用号,当用户空间的进程执行一个系统调用时,系统调用号用来指明执行哪个系统调用

系统调用号一旦分配就不会再更改,被删除的系统调用号也不许再回收。

sys _ ni _ syscall()专门针对无效的系统调用而设立的,只负责返回-ENOSYS。

系统调用号被定义在arch/i386/kernel/syscall_64.c文件中。

指定恰当的系统调用

X86中,系统调用号通过eax寄存器传递给内核,system _ call()函数通过将给定的系统调用与NR _syscalls作比较来检查其有效性,如果大于或等于NR _syscalls就返回-ENOSYS,否则就执行相应的系统调用:

call *sys_call_table(,%eax,8)//基址+偏移量*8

参数传递

上一篇博客中有详细的记录,这里不再赘述。见http://www.cnblogs.com/July0207/p/5277774.html

系统调用的实现

参数验证

由于系统调用在内核空间执行,所以必须验证其参数是否合法有效,而且必须是正确的。

检查指针是否有效

检查用户提供的指针是否有效,在接收这个指针之前,必须保证:

  • 指针所指向的内存区域属于用户空间。
  • 指针所指向的内存区域在进程的地址空间之内。
  • 如果是读,该内存应被标记为可读,如果是写,该内存应被标记为可写,如果是可执行,该内存应被标记为可执行。进程决不能绕过内存访问限制。
检查内核空间与用户空间数据的来回拷贝

内核提供了两个方法来完成必须的检查内核空间与用户空间数据的来回拷贝。

  • 为了向用户空间写数据,内核提供了copy _ to _user(),它需要三个参数,第一个是进程空间中的目的内存地址,第二个是内核空间内的源地址,第三个是需要拷贝的数据长度(字节数)。

  • 为了从用户空间读数据,内核提供了copy _ from _user(),该函数把第二个参数指定位置上的数据拷贝到第一个参数的指定位置,第三个是需要拷贝的数据长度(字节数)。

如果运行成功,则返回0,如果失败,则返回没能拷贝成功的字节数。

检查针对是否有合法权限

调用capable()函数检查用户是否有权对指定资源进行操作,返回非0值则有权限,返回0无权限。

<linux/capability.h>中包含一份所有权能和其对应的权限列表。

系统调用上下文

内核在执行系统调用时处于进程上下文。在进程上下文中,内核可以:

  • 休眠:说明系统调用可以使用内核提供的绝大部分功能。
  • 可以被抢占:要求保证该系统调用是可重入的。

绑定一个系统调用的最后步骤

  1. 在系统调用表的最后加入一个表项。
  2. 对于所支持的各种体系结构,系统调用号都必须定义于<asm/unistd.h>中。
  3. 系统调用必须被编译进内核映像,不能被编译成模块。只要将其放进kernel/下的一个相关文件中即可,例如sys.c。

从用户空间访问系统调用

Linux本身提供了一组宏,用于直接对系统调用进行访问。他会设置好寄存器并调用陷入指令。该宏必须了解到底有多少参数按照怎样的顺序压入寄存器。

	_syscalln()     //n的范围从0到6,代表需要传递给系统调用的参数个数。

例如,open()系统调用的形式是:

long open(const char *filename, int flags, int mode)

等价于

#define NR_open 5
_syscall3(long,open,const char*,filename, int,flags, int,mode)

对于每个宏来说,都有(2+2xn)个参数:

1.系统调用的返回值类型

2.系统调用的名称

3及以后是按照系统调用参数的顺序排列每个参数的类型和名称。

_ NR _open在<asm/unistd.h>中定义。这个宏会被扩展成为内嵌汇编的C函数。

建立一个新系统调用

好处:

  • 系统调用创建容易并且使用方便
  • linux系统调用的高性能

问题:

  • 占用系统调用号
  • 固化,不允许改动接口
  • 需要分别注册到每个需要支持的体系结构中
  • 脚本中不易调用,文件系统中也不能直接访问
  • 在主内核树外难以维护使用

替代方法:

  • 某些接口,例如信号量,用文件描述符表示
  • 把增加的信息作为一个文件放在sysfs的合适位置。

《Linux内核设计与实现》课本第五章学习笔记——20135203齐岳的更多相关文章

  1. 《Linux内核设计与实现》第五章学习笔记

    <Linux内核设计与实现>第五章学习笔记 姓名:王玮怡  学号:20135116 一.与内核通信     在Linux中,系统调用是用户空间访问内核的唯一手段:除异常和陷入外,它们是内核 ...

  2. 《Linux内核设计与实现》 第五章学习笔记

    第五章 系统调用 在现代操作系统中,内核提供了进程与内核进行交互的一组接口.有如下作用: 让应用程序受限的访问硬件设备 提供了创新进程并与已有进程进行通信的机制 提供了申请操作系统其它资源的能力 保证 ...

  3. 《Linux内核设计与实现》第四章学习笔记

    <Linux内核设计与实现>第四章学习笔记           ——进程调度 姓名:王玮怡  学号:20135116 一.多任务 1.多任务操作系统的含义 多任务操作系统就是能同时并发地交 ...

  4. 《Linux内核设计与实现》第四章学习笔记——进程调度

                                                                        <Linux内核设计与实现>第四章学习笔记——进程调 ...

  5. 《Linux内核设计与实现》 第一二章学习笔记

    <Linux内核设计与实现> 第一二章学习笔记 第一章 Linux内核简介 1.1 Unix的历史 Unix的特点 Unix很简洁,所提供的系统调用都有很明确的设计目的. Unix中一切皆 ...

  6. 《Linux内核设计与实现》课本第三章自学笔记——20135203齐岳

    <Linux内核设计与实现>课本第三章自学笔记 进程管理 By20135203齐岳 进程 进程:处于执行期的程序.包括代码段和打开的文件.挂起的信号.内核内部数据.处理器状态一个或多个具有 ...

  7. 《Linux内核设计与实现》课本第四章自学笔记——20135203齐岳

    <Linux内核设计与实现>课本第四章自学笔记 进程调度 By20135203齐岳 4.1 多任务 多任务操作系统就是能同时并发的交互执行多个进程的操作系统.多任务操作系统使多个进程处于堵 ...

  8. 《Linux内核设计与实现》第五章读书笔记

    第五章  系统调用 5.1与内核通信 1. 系统调用 让应用程序受限的访问硬件设备 提供创建新进程并与已有进程通信的机制 提供申请操作系统其他资源能力是用户空间进程和硬件设备之间的中间层 2. 系统调 ...

  9. 《Linux内核设计与实现》第三章学习笔记

    第三章  进程管理 姓名:王玮怡  学号:20135116 一.进程 1.进程的含义 进程是处于执行期的程序以及相关资源的总称,程序本身并不是进程,实际上就是正在执行的代码的实时结果.Linux内核通 ...

随机推荐

  1. $().each 和表单事件的坑

    在用each循环时 1.想结束循环 return false 2.想跳过某循环 return 3.想跳出function 不行,请切换成其他循环如 for 使用form表单事件 1.必须要有submi ...

  2. [转]struts1.2的action参数配置

    转载地址:http://chenfeng0104.iteye.com/blog/796870 <struts-config>     <form-beans>         ...

  3. phpMyAdmin的配置

    好久没写东西了,上来记录一下今天学的一点小东西吧~ 之前搞php开发的时候,一直用的是SQLyog来操作mysql数据库的,但是今天发现sqlyog功能不是很完善,主要是我想修改数据库名,但是sqly ...

  4. IDEA UTF-8 中含 bom 运行报错 批量处理将bom移除

    将eclipse中的项目导入到idea或者as的环境中,遇到UTF-8含有BOM编码报错的问题,之前每次遇到这样的问题都特么用EditPlus一个一个的转换,感觉太烦了,后面就自己写了一个批量处理的工 ...

  5. tomcat作为服务器的配置

    tomcat在启动时,会读取环境变量的信息,需要一个CATALINA_HOME 与JAVA_HOME的信息,CATALINA_HOME即tomcat的主目录,JAVA_HOME即java安装的主目录, ...

  6. [程序设计语言]-[核心概念]-02:名字、作用域和约束(Bindings)

    本系列导航 本系列其他文章目录请戳这里. 1.名字.约束时间(Binding Time) 在本篇博文开始前先介绍两个约定:第一个是“对象”,除非在介绍面向对象语言时,本系列中出现的对象均是指任何可以有 ...

  7. 【转】Checkpoint--与lazy writer区别

      checkpoint目的是减少数据库的恢复时间(服务奔溃或重启服务后的恢复),而lazy writer的目的是保证SQL OS 有空闲缓存块和系统有一定可用内存. Checkpoint和lazyW ...

  8. smarty模板引擎

    1.    使用smarty 1.1 项目引入 // 3, 连接数据库,提取相关数据 $title = "Smarty模板引擎"; $content = "Smarty模 ...

  9. 存储过程里面使用in变量列表异常的处理

    在写一个存储过程的时候,由于需要用到类似:select id,name from tablename where id in(id1,id2,id3...)的查询语句,同时括号里面的变量是拼接得到的, ...

  10. python学习之深入

    一.迭代器和生成器 1.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退. ...