跟我一起学习Linux系统编程001-架构、内核概要

Linux系统编程学习001-架构、内核概要

了解Linux系统架构、内核、基本原理,才是进入Linux平台下编程学习的前提。不了解这些,调用C/C++库来开发,可能表面上会学用一些库函数接口,实则可能是代码处处缺陷,一旦遇到有点深度的故障,程序开发寸步难行。

1 Linux的分层架构

Linux系统编程学习001-架构、内核概要

不管是Linux、Windows,还是其它的操作系统,采用分层结构模型,这几乎是一个通行做法了。不仅是大系统,小的嵌入式系统,往往程序员也会不由自主地采用分层模型,就像上面的图上所示,通常的操作系统会分为这样几层:硬件层、系统层和应用层。系统层内部一般情况下,大概再细分为驱动层、操作系统内核和系统扩展层。

分层结构是为了模块化、分工协作、降低代码耦合度的需要,也是功能优化、易维护、高效率低成本的一个自然选择。

Linux系统编程学习001-架构、内核概要

Linux也类似,分硬件层hardware、内核层Linux-kernal和用户层user space。如上图所示,Linux系统的内核采用的是大包大揽的宏内核结构:核中的所有模块,进程管理、任务调度、内存管理、任务调度、设备驱动和文件系统,统统运行在相同的地址空间中,通过系统调用system calls来响应用户层服务。

2用户空间与内核空间

Linux系统编程学习001-架构、内核概要

从硬件层往上,是软件层。总体上方面讲,Linux软件体系结构可以分为两块:

(1)用户空间用户空间中又包含了,用户的应用程序,C库

(2)内核空间内核空间包括,系统调用,内核,以及与平台架构相关的代码

内核具有很高的权限,可以控制 cpu、内存、硬盘等硬件,而应用程序具有的权限很小。

操作系统相应的,也会把内存分成两个区域,一个是内核区,另一个是用户区。

我们也可以近似地把上面所说的用户空间等同于用户内存区,内核空间等于内核内存区。

用户空间的代码只能访问一个局部的内存空间,而内核空间的代码可以访问所有内存空间。用户应用程序不可直接访问内核空间的任何资源,包括内核内存区在内。一旦试图直接访问,就是越界,会引发Linux系统错误。

3用户态和内核态

为什么要分成用户态和内核态呢?这是因为安全的需要。

CPU一般会设计多种工作模式,ARM实现了7种工作模式,不同模式下CPU可以执行的指令或者访问的寄存器不同。X86实现了4个不同级别的权限:Ring0—Ring3。Ring0下可以执行特权指令,可以访问IO设备,Ring3则有很多的限制。

所以,从CPU的角度出发,为了保护内核的安全,把系统分成了2部分。内核运行在CPU的特权级别下,称之为内核态。用户程序运行在CPU一般权限模式下,称之为用户态。所以,程序的运行状态,用户态和内核态,主要是针对CPU当前工作模式来说的。

用户态:用户程序运行在用户内存空间,也可以说是用户空间(user space),且不能越界。应用运行在CPU普通权限模式下

内核态:内核模块运行在内核空间(kernel space),能完全访问所有资源,处于运行在CPU特权模式下。

综合上面所述,空间是指代资源而言的,而状态是指代CPU权限模式而言的。所以,一个普通应用,只能处于用户空间。但指令可以引发内核服务,从而由用户态进入内核态。

4Linux一个应用是怎么工作的?

运行在用户内存空间的一个应用程序,其指令一般运行CPU的普通权限模式下。但必要时,应用要请求内核调用。然后内核开始响应,在内核调用已经开始,尙未返回的期间,就处于内核态。

用户程序的指令如果需要内核响应,就必须就需要通过「系统调用」,才进入内核空间,下面来看看系统调用的过程:

Linux系统编程学习001-架构、内核概要

内核程序执行在内核态,用户程序执行在用户态。用户态和内核态是程序执行的两种不同状态,我们可以通过“系统调用”和“硬件中断“来完成用户态到内核态间的转移,转移的同时,程序工作空间,也由用户空间(用户内存区)转为内核空间(内核资源区)。

当应用程序使用系统调用时,会产生一个中断。发生中断后, CPU 会中断当前在执行的用户程序,转而跳转到中断处理程序,也就是开始执行内核程序。内核处理完后,主动触发中断,把 CPU 执行权限交回给用户程序,回到用户态继续工作。

5以进程为视角

什么是程序?完成特定任务的一系列指令集合就是程序。用更俗更简单的话来说,你使用gcc编译成的那个可执行文件,就是程序。

什么是进程?程序在操作系统执行后的过程,就是进程。更简单的说法,你用gcc编译成的可执行文件,真的运行起来了,操作系统给其分配了资源,这就是进程。

程序放在磁盘上,包含的是指令(代码段+数据段),是静态概念。进程运行在内存中,操作系统给其分配了运行时环境,是动态概念。

普通用户只知找到可执行文件并执行起来,为已所用。但程序员则要用进程的视角,来创建、调试、编译代码。

6内核视角

一个进程在Linux系统上运行了,然而普通进程在Linux操作系统上,它的占用的资源极其有限,能力极其低下。可以说是“低三下四”。《Linux系统编程手册》上有段这样的话:

Linux系统编程学习001-架构、内核概要

你看看,进程的不能,都是内核的能耐。内核对系统所有的资源,无所不知、无所不能,掌管着进程的生死特权。进程想干点啥事,稍微有所越轨,必须通过系统调用向内核申请。

所以,必须站在内核的视角,才能在liunx上深度玩转编程。那种面向进程的方式,在Linux平台上的深度开发,是不可取的。

7Linux系统编程学什么?

在进行Linux系统编程学习的过程中,我们大多数情况下,如果不涉及硬件细节,撑握200多个System calls(系统调用)API函数的使用方法,来验证和领悟Linux系统的内核各个部分的设计原理,这样就可以了

这一点要提一下windows,相比LInux而言,windows平台的系统级API高达数千个,我看到一个2009年汇总的WIN API大全,已经2248个了,此后还在不断增加之中。(传言现在已经高达上万了,不过我懒得考证。)这背后的原因就是windows没有像Linux那样抽象而统一的设计思路和模型,各模块、各组件、各层次均为易用而生。

在Ubuntu20上,
/usr/src/linux-headers-5.4.0-48/arch/sh/include/uapi/asm/unistd_64.h中有系统API调用号定义,现在也不过394个,常用的也只会有200多个。如果你局限在某一行业进行LInux应用开发,可能面临常用的也就30到50个左右。

更何况Linux平台是开源的,个人可以学无止境。而在windows,个人几乎无法深度进阶。所以拥抱Linux平台,在Linux平台下训练开发,才是系统级开发的光明大道。

再说一点,微软公司经常放弃自已的架构、工具、及各项技术,除了不敢放弃windows界面之外,我看微软都没有啥它不敢放弃的了。别的不敢说,在国内如此内卷的情况下,做程序,跟着微软混,年纪大了,超过35岁,很有可能日子过的一天不如一天。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

虎哥的世界

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值