?
Solved

driver compilation gives warning,and insmod gives error

Posted on 2003-02-28
11
Medium Priority
?
318 Views
Last Modified: 2010-04-21
Hi,

   I have built a very small diver in linux kernel 2.2. When I compile with the following command:

"gcc -c -D__KERNEL__ -DMODULE -I/usr/src/linux-2.2.16/include -O -Wall xxx_drv.c"

  it flashes the warning "At top level: warning: initialization from incompatible pointer type".
   
And on running "insmod xxx_drv.o" it gives message
"xxx_drv.o: couldn't find the kernel version the module was compiled for.", though i have used the line

"#define __NO_VERSION__".

So, trying to be specific, my questions are:

1. What should I do for the above problem. ;-)
2. What to do to integrate it with the kernel, i.e., I don't want to run insmod everytime? It should be loaded at boot-up time.
3. Why do different file_operations structures have different no. of enteries???

------------------------------

As the code is short, I am pasting it below:

/////////////////////////////////////////////////////////

#include <linux/config.h>

#ifndef __KERNEL__
#define __KERNEL__
#endif

#define __NO_VERSION__

#include <linux/config.h>

#ifdef CONFIG_SMP
#define __SMP__
#endif

/* system include files */
#include "linux/kernel.h"
#include "linux/sched.h"
#include "linux/tty.h"
#include "linux/signal.h"
#include "linux/errno.h"
#include "asm/io.h"
#include "asm/segment.h"
#include "asm/system.h"
#include "asm/irq.h"

#include <linux/ioport.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/fcntl.h>



int
xxx_write(struct inode *inode, struct file *file, char *buffer, int count) {

     int          offset = 0;

    if (count > 4095)
        return(-ENOMEM);
    if (count <= 0)
        return(-EINVAL);

    while (count > 0) {
         outb( *(buffer++),0x378); /*0x378 is the starting address of the parallel port.*/
         offset++;
    }
    return offset; /* return number of bytes written */
}



/* This is the structure I found at a site*/

static struct file_operations xxx_fops = {
    NULL,         /* lseek()   */
    NULL,     /* read()    */
    xxx_write,    /* write()   */
    NULL,         /* readdir() */
    NULL,         /* select()  */
    NULL,    /* ioctl()   */
    NULL,         /* mmap()    */
   NULL,     /* open()    */    
    NULL     /* close()   */
    };



long
xxx_init(long kmem_start) {
     EXPORT_NO_SYMBOLS;
    printk("Sample Device Driver Initialization\n");

    if (register_chrdev(22, "xxx", &xxx_fops))
        printk("error--cannot register to major device 22!\n");
    /* detect hardware and initialize it */
    return kmem_start;
}



void cleanup_module(void)
   {
      unregister_chrdev(22, "xxx");
   }
/////////////////////////////////////////////////////////
0
Comment
Question by:adija
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 5
11 Comments
 
LVL 5

Expert Comment

by:bryanh
ID: 8050213
>"xxx_drv.o: couldn't find the kernel version the module
>was compiled for.", though i have used the line
>
>"#define __NO_VERSION__".

__NO_VERSION__ means "don't generate the kernel version in the module."  But Insmod will not load a module that doesn't contain the kernel version.  So take that out.

(Why would anyone code #define __NO_VERSION__?  Because he is going to link two object files together to create an LKM, and he wants only one kernel version generated).

>At top level: warning: initialization from incompatible pointer type".
 
This is just about impossible to debug without looking at the source code line number in the message and then the source line.  One of your data structures is probably used in a macro that requires a different data type.

>I don't want to run insmod everytime? It should be loaded at boot-up time.

So put an 'insmod' command in one of your startup scripts.  People often use a more complex method to do this, but it isn't any better.

>Why do different file_operations structures have different no. of enteries???

Entry?  Do you mean member initializer?  Structures don't have entries.  If you mean some drivers initialize different numbers of members in their file_operations structures, the answer is because not all drivers care to provide all the possible file operations.  In GNU C, when you specify an initializer for some members and not others, the others get initialized to NULL.


By the way, EE works best when you post separate questions separately.  There are different experts for different questions, even in the same area.
0
 

Author Comment

by:adija
ID: 8057396
Hi,
  I'll keep inmind to send different questions the next time. The "insmod" style in startup files seems good to me.

This reply corresponds to my first problem,i.e., -
1. What should I do ...

      I deleted the line "#define __NO_VERSION__" from the source file, but still the same error message flashes on screen:
"xxx_drv.o: couldn't find the kernel version the module was compiled for."

I am using kernel 2.2

0
 

Author Comment

by:adija
ID: 8057450
Hi,

  This query is with respect to my first question's second problem,i.e.:

"While comipling the source file with the command
gcc -c -D__KERNEL__ -DMODULE -I/usr/src/linux-2.2.16/include -O -Wall xxx_drv.c"

the compiler flashes a warning:
"xxx_drv.o: couldn't find the kernel version the module was compiled for."

I've seen it, and the line number corresponding to the error contains the member initializer xxx_write of file_operations structure. To make it clear, my pasting my xxx_fops structure from the source code indicating the line that triggers the warning.

static struct file_operations xxx_fops = {
   NULL,         /* lseek()   */
   NULL,     /* read()    */
   xxx_write,    /* write()   */  //THIS IS THE LINE THAT
//CORRESPONDS TO THE SOURCE OF THE WARNING
   NULL,         /* readdir() */
   NULL,         /* select()  */
   NULL,    /* ioctl()   */
   NULL,         /* mmap()    */
  NULL,     /* open()    */    
   NULL     /* close()   */
   };


Thanks in advance.

aditya
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 5

Expert Comment

by:bryanh
ID: 8062279
>"xxx_drv.o: couldn't find the kernel version the module was compiled for."

OK, this is pretty simple then.  You're loading an object module which is not an LKM.  The surest way to differentiate a loadable kernel module from some random .o file is to do 'objdump --headers xxx_drv.o'.  That lists all the sections in the .o file.  If it's an LKM, one of those sections is called ".modinfo".  I bet xxx_drv.o doesn't have one.

So how does an LKM get a .modinfo section?  By having its source code include <linux/module.h>.  That's what makes an LKM an LKM.

I recommend reading the MODULE-HOWTO (which I wrote).  It isn't really geared to developing LKMs as much as toward using them, but it has some valuable background information like this.
0
 
LVL 5

Expert Comment

by:bryanh
ID: 8062298
>I've seen it, and the line number corresponding to the
>error contains the member initializer xxx_write of
>file_operations structure.

OK, that's a pretty common error.  If you don't get the parameter list and return type of your xxx_write() function exactly right, this is the error message (and note that the message was incorrectly pasted into the above reply -- the real error, from the original posting, is about a type mismatch).

You need to compare your declaration of xxx_write() to the write routine from a working module.  Here's one I found in drivers/char/tty_io.c:

static ssize_t tty_write(struct file *, const char *, size_t, loff_t *);

(Really, you're supposed just to look at the declaration of struct file_ops, but looking at an example is probably easier here).
0
 

Author Comment

by:adija
ID: 8071686
Hi,
  Thanks for the second one, I added "const" and the compilation error has gone. But as I made a mistake of posting several questions at once, I can't accpet it until I get all answers this time. sorry.

aditya
0
 

Author Comment

by:adija
ID: 8071701
Hi,
  I have already added <linux/module.h>. And now I've also added <linux/version.h>. But the insmod error reamins as is.

  What's your link to LKM files? And any other suggestions.

Thanks.

aditya
0
 
LVL 5

Accepted Solution

by:
bryanh earned 210 total points
ID: 8077193
First, you really should do the objdump I mentioned to narrow the problem down.  If you don't have a .modinfo section, there's no point in even trying to load it.

I think you're probably missing the -DMODULE on the compile command.  Defining the MODULE macro is what tells the source code that it's supposed to generate a loadable module instead of one that can be statically bound into the base kernel (many modules can be built both ways).

You shouldn't include <linux/version.h> unless you have code that refers to the symbol in it.  module.h has such code, but includes version.h itself.
0
 

Author Comment

by:adija
ID: 8085951
Hi,
  I ran objdump. You were right. It doesn't have a .modinfo.  This was kernel 2.4
  And when yesterday I complied it on kernel 2.2, it gave the following messages:
/tmp/cc1rWGVn.s: Assembler messages:
/tmp/cc1rWGVn.s:9:Warning: Ignoring changed section attributes for .modinfo

    And when I ran insmod, it have error that resource is busy.  I want to use the address of parallel port, i.e., 0x378. You can read my init function for that matter.
 
Thanks
0
 
LVL 5

Expert Comment

by:bryanh
ID: 8092813
Are you saying you've solved the missing version problem and now your module init function is running and the init function is returning an error?

The xxx_init() function above is strange.  It takes an argument even though a module init function doesn't have arguments.  And it returns that argument as its return code.  The return code is supposed to be 0 if the initialization succeeded and a negative errno  error code if it didn't succeed.  In the latter case, Linux unloads the module.

For some reason I don't understand, if the init function returns a positive number (which means it's broken, like this one), the module loader proceeds as if it returned -EBUSY, which would result in the busy message you see.
0
 

Author Comment

by:adija
ID: 8097604
Hi,
  I think this is just a small problem left, so I'm accepting our comment as answer. Moreover, with your courtesy we can talk about it with less severity.

Thanks.
0

Featured Post

Linux Academy Android App Now Supports Chromecast

We have some fantastic news for our Android fans. We’re so excited to announce that the Linux Academy Android app is now available with Chromecast support. That’s right – simply download the latest update of the Linux Academy App and start casting your favorite course videos!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Have you ever been frustrated by having to click seven times in order to retrieve a small bit of information from the web, always the same seven clicks, scrolling down and down until you reach your target? When you know the benefits of the command l…
The purpose of this article is to demonstrate how we can upgrade Python from version 2.7.6 to Python 2.7.10 on the Linux Mint operating system. I am using an Oracle Virtual Box where I have installed Linux Mint operating system version 17.2. Once yo…
Monitoring a network: how to monitor network services and why? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the philosophy behind service monitoring and why a handshake validation is critical in network monitoring. Software utilized …
In this video, Percona Solutions Engineer Barrett Chambers discusses some of the basic syntax differences between MySQL and MongoDB. To learn more check out our webinar on MongoDB administration for MySQL DBA: https://www.percona.com/resources/we…

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question