001-从LINUX系统开发转为内核开发的思想转变

前言

应用程序开发者(系统开发)和内核开发者对于程序的理解会稍微有些不同,因此在转变的过程中需要先从思想上作一些转变。首先应该先了解一下两者各自的特点,以便理解两者的不同。

工作思路上的差异

  • 系统开发:
    1. 理解业务
    2. 抽象业务逻辑和对象
    3. 设计程序流程和算法
    4. 编码:基本上业务逻辑代码需要从0开始构建
  • 内核驱动开发
    1. 理解硬件原理图(硬件的数量和连接方式)
    2. 必要时需要了解芯片手册和各种bus协议(如USB协议,I2C协议)
    3. 编码:基本上都有可以参照的代码,基本上都是通过移植和修改来构建

两者在工作思路上的差异,主要是由工作对象和编码环境不同造成的。
系统开发的对象是用户,目的是为了解决用户的实际需求。用户的需求是千差万别的,除非你的公司在某个应用领域深耕多年由丰富的代码积累,否则很难找到可以参照的代码。因此通常代码都需要从0开始构建。
内核驱动开发,内核驱动开发的对象是为了硬件可以正常工作。为了提高协助效率和提高市场占有率,各芯片厂商(FAE)都会让自己的硬件设备符合统一的标准协议,以降低模组厂商的学习成本和开发效率。比如别人家的USB控制芯片都符合统一标准,而你家的不符合势必你家的芯片不会受市场欢迎。因此只要是同一类芯片,其驱动代码的逻辑不会相差很多,因此不需要从0开始构建代码,而只需要用别人的代码作移植修改即可。

对于程序理解的不同

  • 系统开发:

    1. 程序分为进程和线程
    2. 进程之间是相互独立的,进程之间必须通过各种进程间通信技术(socket、共享内存、信号等)才能进行数据的共享。
    3. 同一进程内的线程的执行是独立的,但是资源可以相互访问(如两个线程可以访问同一个变量)。
    4. 无论是线程还是进程,之间的协作必须做好同步和排他控制。
    5. 进程和线程都需要先建立再执行。执行完后需要进行销毁。
  • linux内核开发

    1. 没有进程和线程的概念。只有task概念。对于系统开发者来说,可以简单的将task理解为一个线程。
    2. 每个task都可以访问内核的所有地址空间。即不需要像进程那样通信,各种变量或函数可以在各task之间随意访问。
    3. task的入口可以仅仅是一个函数,而不需要向进程或线程那样需要建立和销毁。
    4. task之间同样需要像进程或线程那样做好同步和排他控制。

两者的差异是由于LINUX的设计造成的,如下图:
001-从LINUX系统开发转为内核开发的思想转变_第1张图片
整个Linux分为两个空间,用户空间和kernel空间。用户空间即application运行的空间,kernel空间即kernel运行的空间。每个用户空间的线程都对应kernel空间中的一个task,除此之外kernel空间中还有仅存在kernel内部的task。
用户进程在用户空间是相互独立的,他们可以通过系统调用进入内核空间。进入内核空间后他们便可以访问整个kernel空间的数据了。

举一个简单的例子,读写文件。

001-从LINUX系统开发转为内核开发的思想转变_第2张图片

两个客户进程都想读取文件"/tmp/myfile.txt"。根据经验我们知道,如果一个进程先以写的形式把文件打开之后,另一个进程也去以写的形式打开这个文件就会报错。那么第二个进程是怎么知道文件已经被打开了呢? 根本原因就是两个进程通过open系统调用进入kernel空间后就可以访问内核中任何位置的数据了。而内核中有一个名为filepace的空间,它保存了一个文件是否已经被打开了,线程对应的task只要去读这个空间便可以知道文件是否被打开了。 注意这只是简单举个例子,真实的kernel实现虽然原理是一样的,但是要复杂一些。

总结

认识了以上两点不同后,便做好了从系统开发到内核开发的思想转变了。

你可能感兴趣的:(linux)