Linux Device Driver Tutorial Part 29 – EXPORT_SYMBOL in Linux Device Driver

This is the Series on Linux Device Driver. The aim of this series is to provide easy and practical examples that anyone can understand. This is the Linux Device Driver Tutorial Part 29 – EXPORT_SYMBOL in Linux Device Driver.

Note: In this article, I assume that you already know the basic routines for kernel module development.

When you are writing multiple drivers (modules) in the same device, you may want to use some of the functions form one module to another module. How will we do that? If we use only extern then it won’t help you. We must have used some advanced things. So, We have to tell the kernel, that I want to share this function to other modules.

For example, take printk() function. This function will be defined in source/kernel/printk/printk.c. Then how can we able to access that printk() in our driver?

In this article, we will see how to do it.

EXPORT_SYMBOL in Linux Device Driver


In a programming language, a symbol is either a variable or a function. Or more generally, we can say, a symbol is a name representing space in the memory, which stores data (variable, for reading and writing) or instructions (function, for executing).

When you look at some kernel codes, you may find EXPORT_SYMBOL() very often. Have you wondered any time what the heck is that?

In the Linux Kernel 2.4, all the non-static symbols are exported to the kernel space automatically. But later, in Linux Kernel 2.6 instead of exporting all non-static symbols, they wanted to export the only symbols which are marked by EXPORT_SYMBOL() macro.


When some symbols (variables or functions) are using EXPORT_SYMBOL macro (ex. EXPORT_SYMBOL(func_name)), those symbols are exposed to all the loadable kernel driver. You can call them directly in your kernel module without modifying the kernel code. In other words, It tells the kbuild mechanism that the symbol referred to should be part of the global list of kernel symbols. That allows the kernel modules to access them.

Only the symbols that have been explicitly exported can be used by other modules.

Another macro is also available to export the symbols like EXPORT_SYMBOL. That is EXPORT_SYMBOL_GPL().

EXPORT_SYMBOL exports the symbol to any loadable module.
EXPORT_SYMBOL_GPL exports the symbol only to GPL-licensed modules.


  • Declare and define the symbol (functions or variables) which you want to make it visible to other kernel modules. Then below the definition, use EXPORT_SYMBOL(symbol name). Now it is visible to all loadable modules.
  • Now take the kernel driver who is gonna use the above-exported symbol. Declare the symbol using extern. Then use the symbol directly.
  • Finally, load the module first, who has the definition of the export symbol. Then load the caller module using insmod“.


  • That symbol should not be static or inline.
  • Order of loading the driver is matter. ie. We should load the module which has the definition of the symbol, then only we can load the module who is using that symbol.

Driver Source Code – EXPORT_SYMBOL in Linux

First, I will explain to you the concept of driver code attached below.

In this tutorial, we have two drivers.

Driver 1 has one function called etx_shared_func and one global variable called etx_count. This function and variable has been shared among with all the loadable modules using EXPORT_SYMBOL.

Driver 2 will be using that variable and function which are shared by Driver 1. When we read this Driver 2, then it will call the shared function and we can read that variable also.

Let’s see the source code below.

[Get the source code from the GitHub]




Compiling and Testing Driver

  • Build the driver by using Makefile (sudo make)
  • After compiling, you can able to see the file named as “Module.symvers“. If you open that file, then our shared function and variable will be mentioned there.

  • Load the driver 1 using sudo insmod driver1.ko(Driver 1 should be loaded first. If you try to load the Driver 2 first, then you will get an error like “insmod: ERROR: could not insert module driver2.ko: Unknown symbol in module“).
  • Load the driver 1 using sudo insmod driver2.ko
  • Now check the dmesg

  • Then do cat /proc/kallsyms | grep etx_shared_funcorcat /proc/kallsyms | grep etx_countto check whether our shared function and variable become the part of kernel’s symbol table or not.
  • Now we can read the driver by using sudo cat /dev/etx_device2
  • Now check the dmesg

  • Now we can see the print from shared function and variable count also.
  • Unload module 2 using sudo rmmod driver2(Driver 2 should be unloaded first. If you unload the Driver 1 first, then you will get an error like “rmmod: ERROR: Module driver1 is in use by driver2“).
  • Unload module 1 using sudo rmmod driver1

In our next tutorial, we will discuss atomic variables in the Linux device driver.

0 0 vote
Article Rating
Notify of

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Inline Feedbacks
View all comments
Would love your thoughts, please comment.x
%d bloggers like this: