I'm running linux kernel no. 2.6.15.51 on a ubuntu system.
I created a custom system call and added it to the kernel (containing a struct), compiled, and booted into the new kernel. Now I'm trying to create a c file that calls that system call (for testing purposes). Because I have a struct declared in my system call file, I am including the header in my test file so I can use that same struct. However, when I try including my system call file (which makes a call to access_ok() method), I get an error saying asm/uaccess.h (the file where access_ok() is declared) does not exist. Any ideas why I could be having this problem? Thank you!
Related
I've written a character device driver that, I believe, should work.
I want to test the read/write functions. On another stack overflow question, apparently this can be done by writing to the device file in /dev and echoing the output.
I don't understand how this works:
When I load up my device driver by allocating a major number and calling mknod to create the file, is the file "open"? If it isn't open, then reading/writing shouldn't work like that from the command line, or so I thought?
What state is the device driver in when it has been initialized in /proc/devices and a file created in /dev?
Does this initialization need to happen before attempting to open the device file in a c program?
These answer are extremely difficult to find online, and many resources are outdated. Thanks
One good resource is Linux device driver. A shorter and simpler explanation can be found here.
When you create a file driver, you will implement some functions among file operations (fops):
open
close
read
write
seek
...
Not all function have to be implemented. If write is not implemented for instance, your device won't support writting.
When I load up my device driver by allocating a major number and calling mknod to create the file, is the file "open"?
When the /dev file is created, your module is only inited. A function like init_module is called
When the file is removed, your module is deinited. A function like module_cleanup is called.
What state is the device driver in when it has been initialized in /proc/devices and a file created in /dev?
In that case, the module is inited, the file are not open.
If it isn't open, then reading/writing shouldn't work like that from the command line, or so I thought?
When you read a file from command line, the file is open, read then closed, as a user, you don't have to care to open/close file explicitly.
Things are different if you are a C programmer, in that case, you explicitly have to open, read, close the files.
You can check that adding traces in your kernel code (using printk to print some info to kernel console, reading it with dmesg) or using strace that will trace the system calls.
Does this initialization need to happen before attempting to open the device file in a c program?
Let's resume:
The first function called will be module_init before it's called, the file doesnot exist in /dev
The last function called will be module_cleanup after it's called, the file doesnot exist in /dev
between init and cleanup, you can call the different open, close, read and write function.
Generally read/write are called between open and close.
I am currently learning the C programming language and I'm having some issues with importing modules I created.
I created a small module to read with fgets and flush the buffer from stdin perfectly and I don't want to keep writing the code every single time. I just want to import this small module like I used to do in Python. I didn't knew how because I'm not using an IDE. I'm just compiling with gcc in terminal and using a text editor. I tried to search with Google,but in vain.
You should create a header for your module that declares the functions in the module – and any other information that a consumer of the module needs. You might call that header weekly.h, a pun on your name, but you can choose any name you like within reason.
You should create a library (shared or static — that's up to you) that contains the functions (and any global variables, if you're so gauche as to have any) defined by your module. You might call it libweekly.so or libweekly.a — or using the extensions appropriate to your machine (.dylib and .a on macOS, for example). The source files might or might not be weekly.c — if there's more than one function, you'll probably have multiple source files, so they won't all be weekly.c. You should put this code (the header and the source files and their makefile) into a separate source directory.
You should install the header(s) and the library in a well-known location (e.g. $HOME/include for headers and $HOME/lib for the library — or maybe in the corresponding directories under /usr/local), and then ensure that the right options are used when compiling (-I$HOME/include for the headers) or linking (-L$HOME/lib and -lweekly).
Your source code using the module would contain:
#include "weekly.h"
and your code would be available. With shared libraries in $HOME/lib, you would have to ensure that the runtime system knows where to find the library. If you install it in /usr/local, that is done for you already. If you install it in $HOME/lib, you have to investigate things like /etc/ld.so.conf or the LD_LIBRARY_PATH or DYLIB_LIBRARY_PATH environment variables, etc.
You need to create a header file (.h) with your function declarations types and extern variables. Then in the program where you want to use those functions include this .h file and and add the compiled .o file (with your functions) to the object file list. And you are done.
I am trying to get notification when USB is connected and disconnected.
So I am trying to implement signals. I created a file "file1" in debugfs. Then I provided a simple write file operation.
In user space there is a user space application, which will write its PID in the "file1" of debugfs.
In kernel space I can get the PID passed using the write method mentioned above. But I want to use this PID in a different kernel module. So I tried using EXPORT_SYMBOL();, but if I don't include the common header file, I get a compilation error. If I include the header file, when I flash the image, I see that PID is '0'.
Can anybody tell me, if this the right way? Or tell me where am I going wrong. Or can I get notification in different kernel module when PID is written to the file. If so how?
EXPORT_SYMBOL() is the correct approach. I do not quite understand what you mean by "if I don't include the common header file". It sounds like you are including the EXPORT_SYMBOL() in a shared header file which is not what you want to do. You want to do something like the following:
module1.c (compiles into module1.ko)
int my_exported_variable;
EXPORT_SYMBOL(my_exported_variable);
// The rest of module1.c
And then in module2.c (compiles into module2.ko which must be insmod-ed after module1.ko)
extern int my_exported_variable; // Note the extern, it is declaring but not defining it, the definition is in module1
// The rest of module2.c
After you insmod the first module you can check that the symbol is exported by doing a grep my_exported_variable /proc/kallsyms, assuming you have /proc/kallsyms on your system. If you don't see your variable there then the insmod of module2.ko will fail do to an unresolved symbol.
I have to write a linux module and I can't find a proper function to list all mounted file system and their information. I know command "df -T" can achieve this and sadly I can't use that. Is there a kernel function that can do this or other way?
Why not see the kernel code which fills /proc/mounts
mountstats_open() in base.c
refer get filesystem mount point in kernel module
Your code could open/read the /proc/mounts file, line by line. It contains everything that is mounted, including many mount points that you would not expect.
In general, the format is the same as the /etc/fstab file, but will also include all the mounts that the OS adds.
In my c++ program, I used Tcl library and linked libtcl8.5.so, but the target hosts don't have tcl8.5, so I copied the libtcl8.5.so and tcl8.5 dir which contains init.tcl there, and set the environmet variable TCLLIBPATH to path/to/copied/tcl8.5, but when my program call Tcl_Init, it failed and said “package not known”.
It seems the copied tcl8.5/ cannot be init correctly.
How can I solve this problem?
If you change the location of the script library directory (tcl8.5/ in your case), you need to tell the shared library part of Tcl where it is. You do this using the TCL_LIBRARY environment variable, which if set should contain the absolute path that is the location of that directory (technically, the directory that contains init.tcl).
In a normal installation of Tcl, the correct location of that directory is baked directly into the shared library, but when you move things round (or when you are running Tcl's make test) the environment variable allows you to override.
You might wish to look into alternate packaging mechanisms; there have already been a few questions in the tcl tag on this matter (but the usual favorite — a starkit — is probably not suitable for your case given the fact that the program is mainly C++).