Linux操作系统的概述与内核结构及编程

Posted AlexKing阁下

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux操作系统的概述与内核结构及编程相关的知识,希望对你有一定的参考价值。

人们常常说操作系统这个名词啊,Windows\\Linux\\MacOS可以说是世间三大巨头了。小众的我们就不说了。

     我们一般在生活中只能感受到应用层,像你打开微信等操作就是来自此次,当然你也可以直接操作屏幕,按键等硬件,但其实这些还是由操作系统进行管理,才能正常被使用的。

     简而言之,操作系统就做两件事情。

  1. 对于整个计算机系统的软硬件资源进行管理

  2. 给用户提供服务

    我们这些内核开发人员每次都在强调有什么最优解决方案。侧面说明了操作系统的目标就2个,一个是提高资源的利用率,另一个可不就是为了方便用户使用嘛~~

    欢迎各位大牛来指正!!

1、Linux的整体结构

     其实Linux的结构也非常简单,一般呢,我们将其分为用户空间与内核空间。大体上就如图所示喽。

 

      当一个应用发起请求,其实是在给系统调用请求,然后操作系统根据系统调用请求,提供相应的服务。

      在这里一定要有个概念,即计算机上操作系统中的核心设计理念--机制与策略分离。

     机制即提供什么功能,策略则是如何使用这些功能。这里也就明白了这边的机制与策略的隔离,用什么,不就是我们这边的系统调用嘛,那么多应用可都是调用同一个系统调用接口的。

2、单内核与微内核

    Linux就是一个单内核(又称宏内核)结构,所谓单内核就是操作系统的各个子系统(后续准备写一系列Linux子系统的文章,督催自己学习的同时,分享给大家)可以直接互相调用,而微内核的概念就核心的进程间的通信中断调度等放在微内核中,而其他像文件系统,内存管理等是以服务器的方式放在外面。

   单内核性能高,直接可以调用接口,但是它的维护性差。

   微内核呢由于它需要和服务器进行通信,那么性能差不可避免,但是维护性好啊,最具代表性的就是谷歌的Fuchsia操作系统。

   Linux可维护性差? 这时有人问了,差在哪里?那么告诉你如果你想加一个驱动,需要每次都编译Linux内核,而且它现在越来越大了,编译会变得很慢,而且冗杂在一起的代码,你不觉得可维护性比较差吗?

   为解决这个问题,提出了可加载的Linux内核模块(LKM)。哎,好熟悉啊。这个呢,其实就是moduel加载。这里我们不详细叙述,后面的文章介绍驱动加载方面的知识的时候,再做分析。

3、进程概述与内存概述

     运行在操作系统上的应用程序、服务及其他程序都被称为进程。由于Linux是多任务的系统,看上去是多任务并发的,其实真正正在运行的程序数量最多不过是CPU数目,原因是你所看到的各种进程是CPU不断在不同的进程间进行切换,所以感觉不出来罢了。

    一般内核启动第一个进行init进程为第一个进程,作为1号父进程,其他的每个进程依赖于它。

    我们可以用pstree命令看到进程树

# pstree -pinit(1)---sh(243)---pstree(346)

    在linux中创建进程有两个函数:fork与exec。

    除了重量级进程还有轻量级的子进程--线程,简而言之,进程可以看做是正在执行的程序,而线程则是与进程并行运行的程序函数与例程。在linux里面是使用clone方法创建线程,有关进程这块的具体调度,还是要出一版专题去讨论它。

    我们再从进程角度看待整个地址空间的话,对于任何进程来讲,它只有一个地址空间,无法感知到别的进程,这就是我们常说的虚拟地址空间,为什么说他是虚拟呢,很简单,因为Linux将其分为内核空间与用户空间。

但在由于64位的系统为了优化CPU的工作量,可能使用的地址空间位数小于64位,所以上图中的简单划分不一定是完全正确。

   那么如何能让虚拟地址与实际物理地址联系在一起呢,这需要将物理地址空间映射到虚拟地址空间去。Linux在这方面就是用页来表示的。而用来将虚拟地址空间映射到物理地址空间的数据结构称为页表。大家都知道内存是很大的,为每页都分配页表,这种情况很糟糕,因而产生了多级分页。Linux一般采用4级分页,PGD全局页目录;PMD中间页目录;PTE页表数组,然后再offset才能找到地址。

可以看到为了找到相应的地址,需要跨这么多数组列表,这影响效率啊,为了试图解决这个问题,CPU一般专门会有MMU与TLB。MMU优化内存访问操作,TLB是直接将访问最频繁的地址保存起来,然后直接访问即可。

   在内核中,我们知道分配内存的时候,你必须先标记这个页帧(物理地址内存页)已分配或是空闲状态。为了更加快速检测内存的连续区域,内核采用了一个方案,叫伙伴系统,其实非常简单理解,就是内存中的连续的内存库,可以单独分配,当空闲的时候呢,两个连续的内存变成更大的内存块,作为下一次内存块的伙伴。

    而内核还有可能要用到更小块的内存的时候,此时会用到在伙伴系统之上的一个内存管理层,我们称其为slab缓存,一般它可以用两种方法分配内存。一个是对于频繁使用的对象,内核会只定义对象实例缓存,slab自动与伙伴系统交互,并完成缓存用完后自动申请页帧。而另外一种就是我们常常在内核中使用的kmalloc和kfree。

4、系统调用

    在linux的应用编程中,更多的开发者们一般调用POSIX标准定义的系统调用。一般我们将其分为

     *  进程管理

     *  信号

     *  文件

     *  目录和文件系统

     *  保护机制

     *  定时器函数

   在系统调用这块,其实可以从一个小的ioctl的深入到内核的各个内部模块。还有BSD的套接字的抽象使用。文件系统的各类调用。这些在我的博文中应该不会讲的过于的多,后续会对网络的套接字做一份有关系统调用到最底下实现的文章。

5、后记

   说实话,linux内核是一个非常有意思的东西,我们常听说C# C++等都是面向对象编程,而linux内核有吗?其实有的,如果你细心关注过kobject.h,就是将内核抽象化的。还有一些类似于类型定义,数组对齐,字节对齐等等,绝对是值得深思的一些代码。

以上是关于Linux操作系统的概述与内核结构及编程的主要内容,如果未能解决你的问题,请参考以下文章

[linux-内核][转]内核日志及printk结构浅析

Linux系列概述和环境搭建及目录结构

shell编程概述

Shell编程

Linux系统编程Linux进程管理

《linux内核设计与分析》内核模块编程