If I load a kernel module and list the loaded modules with lsmod
, I can get the "use count" of the module (number of other modules with a reference to the module). Is there a way to figure out what is using a module, though?
The issue is that a module I am developing insists its use count is 1 and thus I cannot use rmmod
to unload it, but its "by" column is empty. This means that every time I want to re-compile and re-load the module, I have to reboot the machine (or, at least, I can't figure out any other way to unload it).
It says on the Linux Kernel Module Programming Guide that the use count of a module is controlled by the functions
try_module_get
andtry_module_put
. Perhaps you can find where these functions are called for your module.try kgdb and set breakpoint to your module
For anyone desperate to figure out why they can't reload modules, I was able to work around this problem by
Actually, there seems to be a way to list processes that claim a module/driver - however, I haven't seen it advertised (outside of Linux kernel documentation), so I'll jot down my notes here:
First of all, many thanks for @haggai_e's answer; the pointer to the functions
try_module_get
andtry_module_put
as those responsible for managing the use count (refcount) was the key that allowed me to track down the procedure.Looking further for this online, I somehow stumbled upon the post Linux-Kernel Archive: [PATCH 1/2] tracing: Reduce overhead of module tracepoints; which finally pointed to a facility present in the kernel, known as (I guess) "tracing"; the documentation for this is in the directory Documentation/trace - Linux kernel source tree. In particular, two files explain the tracing facility, events.txt and ftrace.txt.
But, there is also a short "tracing mini-HOWTO" on a running Linux system in
/sys/kernel/debug/tracing/README
(see also I'm really really tired of people saying that there's no documentation…); note that in the kernel source tree, this file is actually generated by the file kernel/trace/trace.c. I've tested this on Ubuntunatty
, and note that since/sys
is owned by root, you have to usesudo
to read this file, as insudo cat
or... and that goes for pretty much all other operations under
/sys
which will be described here.First of all, here is a simple minimal module/driver code (which I put together from the referred resources), which simply creates a
/proc/testmod-sample
file node, which returns the string "This is testmod." when it is being read; this istestmod.c
:This module can be built with the following
Makefile
(just have it placed in the same directory astestmod.c
, and then runmake
in that same directory):When this module/driver is built, the output is a kernel object file,
testmod.ko
.At this point, we can prepare the event tracing related to
try_module_get
andtry_module_put
; those are in/sys/kernel/debug/tracing/events/module
:Note that on my system, tracing is by default enabled:
... however, the module tracing (specifically) is not:
Now, we should first make a filter, that will react on the
module_get
,module_put
etc events, but only for thetestmod
module. To do that, we should first check the format of the event:Here we can see that there is a field called
name
, which holds the driver name, which we can filter against. To create a filter, we simplyecho
the filter string into the corresponding file:Here, first note that since we have to call
sudo
, we have to wrap the wholeecho
redirection as an argument command of asudo
-edbash
. Second, note that since we wrote to the "parent"module/filter
, not the specific events (which would bemodule/module_put/filter
etc), this filter will be applied to all events listed as "children" ofmodule
directory.Finally, we enable tracing for module:
From this point on, we can read the trace log file; for me, reading the blocking, "piped" version of the trace file worked - like this:
At this point, we will not see anything in the log - so it is time to load (and utilize, and remove) the driver (in a different terminal from where
trace_pipe
is being read):If we go back to the terminal where
trace_pipe
is being read, we should see something like:That is pretty much all we will obtain for our
testmod
driver - the refcount changes only when the driver is loaded (insmod
) or unloaded (rmmod
), not when we do a read throughcat
. So we can simply interrupt the read fromtrace_pipe
with CTRL+C in that terminal; and to stop the tracing altogether:Here, note that most examples refer to reading the file
/sys/kernel/debug/tracing/trace
instead oftrace_pipe
as here. However, one problem is that this file is not meant to be "piped" (so you shouldn't run atail -f
on thistrace
file); but instead you should re-read thetrace
after each operation. After the firstinsmod
, we would obtain the same output fromcat
-ing bothtrace
andtrace_pipe
; however, after thermmod
, reading thetrace
file would give:... that is: at this point, the
insmod
had already been exited for long, and so it doesn't exist anymore in the process list - and therefore cannot be found via the recorded process ID (PID) at the time - thus we get a blank<...>
as process name. Therefore, it is better to log (viatee
) a running output fromtrace_pipe
in this case. Also, note that in order to clear/reset/erase thetrace
file, one simply writes a 0 to it:If this seems counterintuitive, note that
trace
is a special file, and will always report a file size of zero anyways:... even if it is "full".
Finally, note that if we didn't implement a filter, we would have obtained a log of all module calls on the running system - which would log any call (also background) to
grep
and such, as those use thebinfmt_misc
module:... which adds quite a bit of overhead (in both log data ammount, and processing time required to generate it).
While looking this up, I stumbled upon Debugging Linux Kernel by Ftrace PDF, which refers to a tool trace-cmd, which pretty much does the similar as above - but through an easier command line interface. There is also a "front-end reader" GUI for
trace-cmd
called KernelShark; both of these are also in Debian/Ubuntu repositories viasudo apt-get install trace-cmd kernelshark
. These tools could be an alternative to the procedure described above.Finally, I'd just note that, while the above
testmod
example doesn't really show use in context of multiple claims, I have used the same tracing procedure to discover that an USB module I'm coding, was repeatedly claimed bypulseaudio
as soon as the USB device was plugged in - so the procedure seems to work for such use cases.All you get are a list of which modules depend on which other modules (the
Used by
column in lsmod). You can't write a program to tell why the module was loaded, if it is still needed for anything, or what might break if you unload it and everything that depends on it.If you use rmmod WITHOUT the --force option, it will tell you what is using a module. Example: