LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Include kernel header files (https://www.linuxquestions.org/questions/programming-9/include-kernel-header-files-553144/)

fallen3019 05-11-2007 09:29 AM

Include kernel header files
 
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.

Is there a way that I can do this?

(i am using Suse 10.1 with kernel 2.6.16.13-4

osor 05-12-2007 10:02 AM

First, the easy part. offsetof is not a function, but rather a preprocessor macro. You can use it a few ways yourself:
  1. #include <linux/stddef.h>
  2. #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
  3. #define offsetof(TYPE,MEMBER) __builtin_offsetof(TYPE,MEMBER)
(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.

fallen3019 05-12-2007 11:03 AM

Hmmm... that could pose few problems...

Well, in short my code is the following:

Code:

#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

I am using this version of 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

osor 05-12-2007 12:04 PM

Quote:

Originally Posted by fallen3019
I am using this version of sched.h

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.

Look for code in np.

osor 05-12-2007 12:04 PM

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() { }

Makefile
Code:

ifndef KERNELDIR
        KERNELDIR  := /lib/modules/$(shell uname -r)/build
endif

obj-m := offset.o

all:
        $(MAKE) -C $(KERNELDIR) M=$(PWD)

clean:
        $(MAKE) -C $(KERNELDIR) M=$(PWD) clean

install:
        $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
        /sbin/depmod -ae

To run, just do something like:
Code:

$ make
make -C /lib/modules/2.6.21/build M=/home/osor/src/offset
make[1]: Entering directory `/usr/src/linux-2.6.21'
  LD      /home/osor/src/offset/built-in.o
  CC [M]  /home/osor/src/offset/offset.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /home/osor/src/offset/offset.mod.o
  LD [M]  /home/osor/src/offset/offset.ko
make[1]: Leaving directory `/usr/src/linux-2.6.21'
$ sudo insmod offset.ko
$ dmesg | tail -n 1
[ 5198.335455] offsetof tasks in task_struct is 200


fallen3019 05-12-2007 01:17 PM

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 :)

osor 05-12-2007 02:32 PM

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.

osor 05-12-2007 02:33 PM

Also, I’m not too familiar with SUSE, so if anyone else knows how it manages kernels and their source/buildtrees, feel free to chime in.

osor 05-12-2007 03:36 PM

If you haven’t already, see here and here for similar problems (and solutions).

fallen3019 05-12-2007 04:11 PM

I think you hit on the problem

Output from:
Code:

$ ls -ld /lib/modules/`uname -r`/build
lrwxrwxrwx 1 root root 43 2007-05-05 17:00 /lib/modules/2.6.16.13-4-default/build -> /usr/src/linux-2.6.16.13-4-obj/i386/default

$ ls -ld /lib/modules/`uname -r`/build
lrwxrwxrwx 1 root root 26 2007-05-05 17:00 /lib/modules/2.6.16.13-4-default/source -> /usr/src/linux- 2.6.16.13-4


$ ls -lH /lib/modules/`uname -r`/source
/bin/ls: /lib/modules/2.6.16.13-4-default/source: No such file or directory


$ ls -lH /lib/modules/`uname -r`/build
total 268
-rw-r--r-- 1 root root 270819 2006-05-03 12:44 Module.symvers

When i check in GUI, in /lib/modules/'uname -r'
the build directory only contains Module.symbers

and there is a source shortcut which has an invalid link :rolleyes:

That does not really bode well, does it?
If i'm not mistaken, source should link to /usr/src/'uname -r'

'uname -r' is actually 2.6.16.13-4-default, however /usr/src contains a direcory called 2.6.16.13-4-obj



also:
Code:

$ sudo insmod offset.ko
root's password
sudo: insmod: command not found

all these problems...this clearly does not desire to work!

osor 05-12-2007 08:35 PM

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).


All times are GMT -5. The time now is 03:42 AM.