上篇介绍了基础的Makefile使用和如何加载到镜像中, 此篇来介绍一下内核的软件包
openwrt软件包 1

内核软件包

首先第一个问题就是: 为什么区分了openwrt软件包和内核软件包?

其实这就是openwrt这个系统的一个问题, 它把整个系统分成了用户态和内核态, 内核态有更高的操作权限, 以及访问各种硬件设备等的权限, 而用户态则有所限制.

体现到代码中, 内核态和用户态也有完全不同的库函数, 这就导致了你运行在内核的软件包不是说改个makefile就可以放到用户态运行了, 最简单的例子, 打印函数在用户态和内核态就完全不同:

//用户态, openwrt软件包
printf("hello, world!\n");

//内核态, kernel软件包
printk("hello, world!\n");

所以这就区分了内核软件包和openwrt软件包了.

向内核加入软件包我把他分为两种方法, 一个是在openwrt的package下添加, 另一个则是直接向linux代码中加入. 二者的区分就是上层对于这个软件包的管理不相同, 具体后面会提到. 本篇先介绍在linux代码中加入内核软件包的方法

文件结构

内核软件包的结构和openwrt软件包的结构类似, 下面是我在linux和openwrt下面找到的一些软件包结构:

linux下内核软件包

linux-5.15.134/drivers/net/ethernet$ tree huawei/
huawei/
├── hinic
│   ├── hinic_common.c
│   ├── hinic_common.h
...
│   ├── Kconfig
│   └── Makefile
├── Kconfig
└── Makefile

linux-5.15.134/drivers/net/ethernet$ realtek/
realtek/
├── 8139cp.c
├── 8139too.c
├── atp.c
├── atp.h
├── Kconfig
├── Makefile
├── r8169_firmware.c
├── r8169_firmware.h
├── r8169.h
├── r8169_main.c
└── r8169_phy_config.c

openwrt下内核软件包

openwrt/package/kernel$ tree gpio-button-hotplug/
gpio-button-hotplug/
├── Makefile
└── src
    ├── gpio-button-hotplug.c
    └── Makefile

从前两个示例可以看出来, 其实放在linux目录的软件包就是比在openwrt下的软件包多了一个Kconfig的文件, 我们先从差异部分入手

Kconfig

我们展开一个Kconfig文件:

# SPDX-License-Identifier: GPL-2.0-only
#
# Huawei driver configuration
#

config NET_VENDOR_HUAWEI
	bool "Huawei devices"
	default y
	help
	  If you have a network (Ethernet) card belonging to this class, say Y.
	  Note that the answer to this question doesn't directly affect the
	  kernel: saying N will just cause the configurator to skip all
	  the questions about Huawei cards. If you say Y, you will be asked
	  for your specific card in the following questions.

if NET_VENDOR_HUAWEI

source "drivers/net/ethernet/huawei/hinic/Kconfig"

endif # NET_VENDOR_HUAWEI

我们去掉别的无关部分, 其实这个文件就是向kernel添加一个config, 添加的格式则和上面展示相同, 其中

  1. bool: 后面一般简要说明
  2. defult: 默认是否开启config
  3. help: 描述, 一般就是详细的使用说明了

后面的source "drivers/net/ethernet/huawei/hinic/Kconfig"其实是个控制选项, 这里是相对于linux目录的kconfig路径, 这样相当于需要加入这个路径下的kconfig文件.

openwrt路径下的软件包则不需要这个文件, 因为openwrt通过makefile编写config时, 已经将其自动加入了, 但kernel下的软件包如果没有添加这个kconfig文件并对软件包进行说明的话, 内核是不知道有这个软件包存在的, 这一点, 等后续进行两者的Makefile分析也可以体现出来它的必要性.

linux 内核软件包

就直接分析内核huawei这个吧, 文件结构如下所示, 省略了一些.c .h文件

linux-5.15.134/drivers/net/ethernet/huawei/
├── hinic
│   ├── hinic_common.c
│   ├── hinic_common.h
...
│   ├── Kconfig
│   └── Makefile
├── Kconfig
└── Makefile

关于Kconfig文件在上文已经提到了, 这里不再赘述, 接下来建议展开这个文件中的两个Makefile文件

首先这个是顶层的Makefile

# SPDX-License-Identifier: GPL-2.0-only
#
# Makefile for the Huawei device drivers.
#

obj-$(CONFIG_HINIC) += hinic/

这个是在hinic/目录下的Makefile

# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_HINIC) += hinic.o

hinic-y := hinic_main.o hinic_tx.o hinic_rx.o hinic_port.o hinic_hw_dev.o \
	   hinic_hw_io.o hinic_hw_qp.o hinic_hw_cmdq.o hinic_hw_wq.o \
	   hinic_hw_mgmt.o hinic_hw_api_cmd.o hinic_hw_eqs.o hinic_hw_if.o \
	   hinic_common.o hinic_ethtool.o hinic_devlink.o hinic_hw_mbox.o \
	   hinic_sriov.o hinic_debugfs.o

其实这里就可以发现, linux内核的软件包, Makefile的写法和openwrt下的非常.

首先是顶层的Makefile, obj-$(CONFIG_HINIC) += hinic/, 这一行表示就是CONFIG_HINIC被选中编译, 即设置为CONFIG_HINIC=y时, 会编译 hinic/下的文件.

注意这里用的"+=", Makefile很多地方都推荐使用+=而非=, 因为+=是添加, 而=则可能导致你的改动覆盖了别人的改动, 可能会有意想不到的报错.

然后说底层的Makefile, 这里相当于是一个编译说明, 不过比起上次提到的openwrt下软件包的编译, 这里就显得简单很多, 首先obj-$(CONFIG_HINIC) += hinic.o, 这个和顶层Makefile的语法相同, 就是这个宏选中宏会编译一个hinic.o的文件.

注意, 当没有后面那些hinic-y := 的部分时, 这个生成的文件的名字一定要和你当前目录下.c文件的名字相同, 它会根据这个.c来生成.o文件

hinic-y := hinic_main.o ...这部分则是说明编译这个hinic.o的依赖文件, 编译逻辑其实和openwrt下软件包是一样的, 只是这里写得更简单罢了

BTW, 这里的-y也可以用宏控制, 写成上个命令 -$(CONFIG_XXX) 的形式, 相当于再增加宏控制来决定最终生成文件到底依赖哪些文件, 在Debug或者功能较复杂的软件包中可以看到这种使用. 这个就自己去探索吧

当然, 这里还需要说明的是, 你要加任意的控制宏, 都是需要在Kconfig文件对这个宏进行说明的.

此外, 其实从这里顶层Makefile也可以猜到, 内核对于软件包的控制其实是类似套娃的, 所以当你创建一个新的软件包目录的时候, 还需要在你自定义的目录上层加入你的软件包说明.

我们还是以这个软件包为例. 可以在他上层的目录中找到对于这个软件包的描述.

linux-5.15.134/drivers/net/ethernet/Makefile
obj-$(CONFIG_NET_VENDOR_HUAWEI) += huawei/
linux-5.15.134/drivers/net/ethernet/Kconfig
source "drivers/net/ethernet/huawei/Kconfig"

结语

好的, 本篇到此为止, 下篇再更新关于如何在openwrt路径下添加内核软件包.

Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐