ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I want to find the offset of a member of a structure within the kernel header file sched.h. (/usr/include/linux)
(i.e. I want to found out how many bytes the element 'tasks' is from the start of the task_struct which is declared in sched.h)
Is there a way I can do that?
My plan is to use the offsetof() function in C, but since sched.h is a kernel header file, I just inserting
Code:
#include <linux/sched.h>
does not work. It gives me a looong list of errors from the includes in sched.h.
(Number 3 can only be used on compilers that implement the __builtin_offsetof operator such as gcc-4.x)
Now for the not-so-easy part, including a linux header file from userspace is useful mostly for getting the values of certain preprocessor macros. You can’t try to access anything in between “#ifdef __KERNEL__” and its corresponding “#endif” unless you are in kernel space. Generally, a distro will “sanitize” the kernel headers (i.e., removing those sections you can’t viably use) and put them in /usr/include/linux. As you can see in an unsanitized version of sched.h, struct task_struct is armored by #ifdef __KERNEL__/#endif (for various reasons). So you can’t do operations on a task_struct unless you are in kernelspace. As for the errors from including sched.h, that is odd. You might not have good, sanitized kernel headers, or you might be inadvertently using headers from your actual kernel source. If this is still puzzling you, can you give us some output from you attempt to compile such a file.
#include <stddef.h>
#include <linux/sched.h>
/*i've tried with #include </usr/include/linux/sched.h> too*/
main ()
{
int A;
A = offsetof(struct task_struct, tasks);
printf ("d = %d \n", A);
}
the offsetof () macro isn't really the issue, because it worked when I used test data structs with it.
My problem is as you said, including sched.h to work on the task_struct.
The errors that I get, when I compile this with gcc 4.1.0
are the following:
Code:
In file included from /usr/include/linux/timex.h:61,
from /usr/include/linux/sched.h:11,
from task.c:2:
/usr/include/asm/timex.h: In function 'get_cycles':
/usr/include/asm/timex.h:40: error: 'cpu_has_tsc' undeclared (first use in this function)
/usr/include/asm/timex.h:40: error: (Each undeclared identifier is reported only once
/usr/include/asm/timex.h:40: error: for each function it appears in.)
In file included from /usr/include/linux/sched.h:12,
from task.c:2:
/usr/include/linux/jiffies.h: At top level:
/usr/include/linux/jiffies.h:75: error: expected ',' or ';' before 'jiffies_64'
/usr/include/linux/jiffies.h:79: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'get_jiffies_64'
In file included from /usr/include/linux/sched.h:12,
from task.c:2:
/usr/include/linux/jiffies.h:250:47: error: division by zero in #if
/usr/include/linux/jiffies.h: In function 'jiffies_to_msecs':
/usr/include/linux/jiffies.h:253: error: 'MSEC_PER_SEC' undeclared (first use in this function)
/usr/include/linux/jiffies.h:261:47: error: division by zero in #if
/usr/include/linux/jiffies.h: In function 'jiffies_to_usecs':
/usr/include/linux/jiffies.h:264: error: 'USEC_PER_SEC' undeclared (first use in this function)
/usr/include/linux/jiffies.h:274:47: error: division by zero in #if
/usr/include/linux/jiffies.h: In function 'msecs_to_jiffies':
/usr/include/linux/jiffies.h:277: error: 'MSEC_PER_SEC' undeclared (first use in this function)
/usr/include/linux/jiffies.h:287:47: error: division by zero in #if
/usr/include/linux/jiffies.h: In function 'usecs_to_jiffies':
/usr/include/linux/jiffies.h:290: error: 'USEC_PER_SEC' undeclared (first use in this function)
/usr/include/linux/jiffies.h: In function 'timespec_to_jiffies':
/usr/include/linux/jiffies.h:311: error: called object 'u64' is not a function
/usr/include/linux/jiffies.h:311: error: called object 'u64' is not a function
/usr/include/linux/jiffies.h:311: error: 'NSEC_PER_SEC' undeclared (first use in this function)
/usr/include/linux/jiffies.h:312: error: called object 'u64' is not a function
/usr/include/linux/jiffies.h:312: error: called object 'u64' is not a function
/usr/include/linux/jiffies.h:315: error: expected ')' before 'sec'
/usr/include/linux/jiffies.h:316: error: expected ')' before 'nsec'
/usr/include/linux/jiffies.h: In function 'jiffies_to_timespec':
and this is just a sample... it goes on to about 300 errors from the following files jiffies.h, nodemask.h, cpumask.h, bitmap.h ...these are only some of them, however all these h files that i get errors from are included in sched.h
So, what you said about the kernel space, is there a way I can do that in my program? Do i have to #define something? or create some sort of makefile?
Or perhaps you can point me somewhere that explains to me how to do this?
I would also need to get this working to use the sizeof() on the struct page, as mentioned here i imagine...
Thanks
Last edited by fallen3019; 05-12-2007 at 11:06 AM.
If you look at that version of sched.h, you see “#ifdef __KERNEL__” occurs on line 171 (with its corresponding “#endif” on line 1479), surrounding the definition of “struct task_struct” on line 696. So even if you didn’t have those errors, you still wouldn’t have access to the struct. It also appears that at the beginning, various files are included that shouldn’t be included (this has subsequently been fixed) such that one cannot sanely include “linux/sched.h” in a userspace program without the errors that you describe.
Here’s (rather simple) sample code that does what you want:
offset.c
Code:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/stddef.h>
#include <linux/sched.h>
MODULE_AUTHOR("osor");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Finds the offset of the element tasks in struct "
"task_struct and relays the information to userspace "
"through the kernel message buffer (dmesg)");
int init_module()
{
printk(KERN_INFO "offsetof tasks in task_struct is %d\n", offsetof(struct task_struct, tasks));
return 0;
}
void cleanup_module() { }
Ah, the kernel modules... Yes, I should have known... what better way than to use Kernel space?
Though.... those caused me another branch of problems with the makefiles.
But i think its a small one actually....
When i create a makefile, I always get the same error...
Code:
make -C /lib/modules/2.6.16.13-4-default/build M=/home/fallen/code/offset
make[1]: Entering directory '/usr/src/linux-2.6.16.13-4-obj/i386/default'
make[1]: *** No targets specified and no makefile found. Stop.
make[1]: Leaving directory '/usr/src/linux-2.6.16.13-4-obj/i386/default'
make: ***[all] Error 2
I think it has something to do with the directories though...
Because the sched.h i need is in /usr/include/linux rather than
/usr/src/linux-2.6.16.13-4-obj/i386/default.
I actually have this problem with any kernel module i try... including those in the LKMPG tutorial...
I have never been well acquanted with makefiles, only what i know from tinkering with them here and there, and that wasn't that much...
thanks loads, your help is proving invaluble, seriously. I have been stuck on this problem for ages
My first question is this: do you have the buildtree for the kernel you are running? Perhaps you might elucidate the situation by posting the output of the following:
Code:
$ ls -ld /lib/modules/`uname -r`/{build,source}
$ ls -lH /lib/modules/`uname -r`/{build,source}
Without knowing the output of the previous commands, I will make a blind suggestion of changing one line in the Makefile: in line 2, change “build” to “source”. Alternatively, if you already know the kernel buildtree location, pass it to the make command (e.g., for me, I would say “KERNELDIR=/usr/src/linux-2.6.21 make” instead of “make”).
Quote:
Originally Posted by fallen3019
Because the sched.h i need is in /usr/include/linux rather than
/usr/src/linux-2.6.16.13-4-obj/i386/default.
I sincerely doubt it. The headers in /usr/include/linux are santized for userspace. The kernel tree has its own headers (on which the aforementioned headers are based). Generally, these would reside in /lib/modules/`uname -r`/build/include/linux.
It seems you don’t have the correct package(s) for building kernel modules. Here is a guide for doing kernel related stuff in SUSE (check specifically the section entitled “Building additional (external) modules”).
Quote:
Originally Posted by fallen3019
If i'm not mistaken, source should link to /usr/src/'uname -r'
This is not necessarily true (in fact, that’s why we use “/lib/modules/`uname -r`/source” rather than “/usr/src/linux-`uname -r`”). Source is just a symlink to wherever you keep the kernel source. When people compile their own custom kernels, source and build often point to the same location (often somewhere in the $HOME directory). If you read the document I linked to, it explains the SUSE method of doing kernels (and the symlink naming scheme).
Quote:
Originally Posted by fallen3019
also:
Code:
$ sudo insmod offset.ko
root's password
sudo: insmod: command not found
That’s very odd (not to have insmod on a functional desktop)…
The insmod utility is generally part of the module-init-utils package. It is in the same boat as modprobe and depmod (I think). So find out if you have module-init-utils installed and if you do, find out what files are contributed by the package (and where they’re located). Or perhaps the problem is your sudo is somehow trying to preserve $PATH. Try as root or with the full path (or add /sbin to your PATH).
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.