6

I have a Wi-Fi driver (a .ko file) for embedded Linux system and there are two identical Wi-Fi devices on my board. After insmod-ing the .ko file into the kernel, the system is able to drive these two Wi-Fi devices.

My question is: if the driver's source code contains global variables (and static variables), do these two devices share the same set of variables? Or, there will be two driver instances for each device?

Thanks!

guan boshen
  • 724
  • 7
  • 15
  • I tested on my board last week. The driver is initialized (module_init) only once, and probed twice because two devices are attached on the board. Global variables (static variables on the top of the .c file) are shared by two devices. I further copy the code to another directory and change the driver name (as well as resources' name inside the code) and compile. Linux is able to load two .ko drivers, and each one is init-ed once. The first insmod-ed driver is probed twice, while the second one is not probed. – guan boshen May 17 '16 at 06:34

2 Answers2

8

Linux kernel modules are linked into the kernel the same as any files would be normally in C. If they have global variables, there is only one copy of each global variable. They can even use global variables from other modules.

user253751
  • 57,427
  • 7
  • 48
  • 90
  • Thanks. If I define `int a;` in one .c file of one driver and defined another `int a;` in another .c file of another driver, will redefinition error be issued when I compile the kernel? – guan boshen May 09 '16 at 05:20
  • @guanboshen I'm not too familiar with building kernel modules, but I would expect that you'll get an error at compile-time if both drivers are compiled into the kernel, and an error at module load time if either or both is a module. – user253751 May 09 '16 at 05:21
  • 4
    No, global variables with same name but from **different modules** are *not shared*. When module is loaded into the kernel using `insmod`, linking is performed according to set of *exported symbols*, collected from the kernel and all modules already loaded. One cannot load module, which exports (using EXPORT_SYMBOL) symbol, which is exported by already loaded module. Symbols with global visibility are not exported by default, so they are not shared. – Tsyvarev May 09 '16 at 16:43
  • 2
    Yes, as said @Tsyvarev you'll need `EXPORT_SYMBOL` to make it visible out to others modules. – Aif May 09 '16 at 17:17
  • 2
    The usual is to have a single `.c` create a single `.o` that generates a single `.ko`. But, it is possible to have a module created from multiple `.c` files (i.e. multiple `.o` files). These need global symbols to communicate/link. The globals are mostly for the [internal] linking of the final `.ko`. The ones that should be visible/usable by other modules are marked with `EXPORT_SYMBOL`. This is similar to a shared library that is built from multiple `.o` files. Not all the globals are part of the `.so` ABI, so the non-ABI ones are elided [usually by a linker script] – Craig Estey May 09 '16 at 17:57
  • @CraigEstey So, as my first comment says, there will be OK (no redefinition error) in that case? – guan boshen May 12 '16 at 01:41
  • 1
    @guanboshen Yes, no worries ... As I [and others] have pointed out, when the final `.ko` link is done, only `EXPORT_SYMBOL` symbol _definitions_ are globally visible (e.g. if a `.o` had an ordinary global, it gets "magically" downgraded to [the equivalent of] a static definition). However, if a module X had an _extern_ to symbol `foo` [but _no_ definition] and module Y had an `EXPORT_SYMBOL(foo)`, then `Y` _must_ be loaded first and then `X` will use Y's `foo` definition – Craig Estey May 12 '16 at 04:33
  • @CraigEstey Thank you, Craig! – guan boshen May 12 '16 at 15:28
4

It is normal for single driver to support several devices.

While some module's variables are shared between different devices, most of variables are stored in device-specific structures.

When driver's function is called for device "A", it accepts pointer to device-specific structure "data-A". Using this pointer, the function extracts parameters of "A". When same function is called for device "B", it accepts pointer to another device-specific structure "data-B".

Tsyvarev
  • 60,011
  • 17
  • 110
  • 153
  • Thank you for your reply. I know it should use device-specific structure instead of global variables. However, some existing drivers even deliveried by some 'large' chip vendors using global variables massively, which is really a pain. – guan boshen Feb 08 '22 at 05:13