系统编程的概念

系统编程概念

1.内核:管理计算机资源的程序

1.1内核功能特点:

  1. 进程调度:linux是抢占式多任务系统,多任务是指多个任务可以同时驻留在内存中,抢占式:是指某个任务在何时使用cpu,并且使用多长时间的规则。分配的是cpu资源
  2. 内存管理:为了合理的在任务间分配内存资源,linux也使用了虚拟内存技术,虚拟内存技术的优点:
  • 进程间相互隔离,一个进程无法访问或者修改另一个进程的内存
  • 进程仅需要部分程序留在内存中,降低了每个进程对内存的需求这样可以让更多的进程留在内存。
  1. 提供文件系统:在磁盘上提供一个文件系统,允许文件的创建,访问,更新,删除等等。管理分配的是磁盘资源
  2. 创建和暂停进程:内核可以加载一个新程序到内存里,给它提供其需要的资源(如内存,cpu)。个人认为是在对资源的综合管理分配。这样一个运行程序的实例叫进程。一旦进程开始执行,内存保证该进程用到的资源在之后被释放并且能够被其他进程使用。
  3. 访问各种设备:(显示器,鼠标,键盘,磁盘等),内核提供程序接口规范和简化这些设备的访问,与此同时协调多程序使用每个设备。
  4. 网络:内核代表用户程序传输并且接收网络包。包括将网络包路由到响应的程序。
  5. 提供系统访问接口。程序可以请求内核执行各种任务。即我们熟知的系统调用。

1.2用户态和内核态

现代处理器架构允许cpu至少在两种状态下工作。用户态和内核态。硬件允许从一个状态切换到另一个状态,同样的虚拟内存区域也可以被标记为用户空间或者内核空间。当程序运行在用户态,cpu只能访问用户空间的内存,当程序运行在内核态,cpu既可以访问用户空间也可以访问内核空间内存。这样用户空间的程序无法访问内核空间的数据,或者作出对操作系统有影响的操作。

1.3从普通程序和内核两个角度看系统

  1. 一个运行的系统有很多进程,对于一个进程来说许多事情是异步的。一个运行的程序不知道何时被剥夺cpu的使用权,哪个程序将会获得cpu的使用权,或者自己何时能再次使用cpu。信号的传递和进程间通信的过程都是内核在指导,对于进程来说可以发生在任何时候。许多事情的发生对于进程来说是透明的。一个进程不知道自己在内存中的位置,或者其使用的内存空间是驻留在内存中还是在swap区域(磁盘上的一块区域用来扩展电脑的内存)。相似的一个进程不知道它访问的文件在磁盘上的位置,它仅仅通过文件名来引用这个文件。进程的操作是隔离的。它无法直接的和其他进程通信,一个进程本省无法创建一个新的进程甚至是结束本进程的执行。最后,一个进程无法直接的和输入输出设备进行通信。
  2. 对应的,运行的系统有一个知道并且控制所有事情的内核。内核促成程序在系统上的运行。内核决定哪个程序使用cpu,何时使用以即使用多长时间。内核维护着包含着所有运行进程信息的数据结构,这些数据结构随着进程的创建,变更状态以及终止而进行更新。内核维护着所有底层的数据结构来确保程序使用的文件名能够被映射到磁盘位置。内核也维护着将进程使用的虚拟内存映射到物理内存和swap区域的数据结构。进程间通信也是通过内核来完成。如果普通进程有请求,内核可以创建新的进程和杀死已存在的进程。最后,内核直接和输入输出设备进行通信,将信息传递给需要的进程。

2.系统调用

系统调用使程序从用户态陷入内核态,请求内核为自己执行一些操作。比如创建新进程,执行io操作

对于系统调用的一些认知:

  1. 系统调用使程序从用户态陷入内核态,这样一来cpu可以访问受保护的内核内存
  2. 系统调用是固定的。每个系统调用对应一个唯一的数字。
  3. 系统调用可以指定一系列的参数,从用户空间(进程的虚拟内存地址)向内核空间传递信息,反之亦然。

系统调用过程,以x86-32为例

  1. 应用程序通过调用c语言库函数来执行一个系统调用
  2. 库函数保证所有的参数能被系统调用的处理程序获取。参数通过栈传递给库函数,但是系统调用从特定的寄存器中获取参数。所以库函数需要将参数从栈中拷贝到寄存器中。
  3. 所有的系统调用都是以相同的方式进入内核:内核需要一些方式来识别不同的系统调用。为了达到目的,库函数拷贝代表系统调用的唯一数字到特定的寄存器中。
  4. 库函数执行trap的机器指导(0x80),这样处理器从用户态切换到内核态,并执行地址(0x80)处的处理程序。
  5. 内核调用其处理系统调用的函数。这个过程涉及:
  • 将寄存器中的值存储到内核栈上
  • 检查代表系统调用的数字的有效性
  • 通过索引,从系统调用表中找到合适的处理函数。如果该系统调用需要参数,则先检查参数的有效性。然后执行相应的任务,在此期间可能会修改所给参数地址上的内容,并且在用户空间和内核空间传输数据(如I/O操作)
  • 将内核栈上的数据放到寄存器里,并且将系统调用的返回值放到栈上。
  • 返回库函数,同时返回到处理器的用户态
    6.如果系统调用返回一个错误值,库函数将这个值设置给全局的变量errno。然后库函数返回给调用者响应的数值表明调用是否成功。

注意: 系统调用时间花销是普通函数的20倍还要多,这个数字可能不准确,只是想体现,系统调用是非常重的操作。

以下图反应了系统调用的流程:

3.库函数的概念

库函数是标准c语言库众多功能之一。库函数是为了更方便的为调用者服务。许多库函数可能没有用到系统调用,也有很多是以库函数为基础方便用户的调用。比如malloc()和free()是以brk()系统调用为基础执行了许多固定的任务方便用户来分配和释放内存。

4.GNU c Library

标准c语言库有许多实现,最常用的GNU c语言库

5.处理系统调用和库函数返回的错误

5.1处理系统调用的错误

通常函数返回一个-1代表错误,当系统调用出错时,会给一个全局的变量errno设置一个正数值来代表具体的错误。如果调用成功不会重新设置errno的值。也有一些系统调用返回-1代表成功。

5.2处理库函数调用的错误

库函数错误返回的形式各式各样

  • 有一些是和系统调用一样,返回-1表示错误,设置errno表示具体的错误。
  • 有些库函数错误时不是返回-1,但是设置errno表示具体的错误。比如fopen错误时返回null
  • 还有一些不会使用errno
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值