Newsgroup: it.comp.os.linux.development
Titolo: problema con esempio di linux kernel module programming guide

ho provato a compilare un esempio riportato in quella guida (il cui
sorgente è accodatoalla fine del messaggio).
In compilazione mi viene fuori "warning implicit declaration of function
`printk_R1b7d4074 " e "warning implicit declaration of function
`sprintf_R3c2c5af5` ". Perché? Cose c'è che non va? 
Poi quando lancio insmod chardev.o ottengo 
chardev.o: cannot resolv symbol __put_user_X
Perché? il file asm/uaccess.h dovrebbe essere incluso (ho il kernel
2.2.18)....
 
/* chardev.c 
 * Copyright (C) 1998-1999 by Ori Pomerantz
 * 
 * Create a character device (read only)
 */
/* The necessary header files */
/* Standard in kernel modules */
#include <linux/kernel.h>   /* We're doing kernel work */
#include <linux/module.h>   /* Specifically, a module */
/* Deal with CONFIG_MODVERSIONS */
#if CONFIG_MODVERSIONS==1
#define MODVERSIONS
#include <linux/modversions.h>
#endif        
/* For character devices */
#include <linux/fs.h>       /* The character device 
                             * definitions are here */
#include <linux/wrapper.h>  /* A wrapper which does 
                             * next to nothing at
                             * at present, but may 
                             * help for compatibility
                             * with future versions 
                             * of Linux */
/* In 2.2.3 /usr/include/linux/version.h includes 
 * a macro for this, but 2.0.35 doesn't - so I add 
 * it here if necessary. */
#ifndef KERNEL_VERSION
#define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c))
#endif
/* Conditional compilation. LINUX_VERSION_CODE is 
 * the code (as per KERNEL_VERSION) of this version. */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,0)
#include <asm/uaccess.h>  /* for put_user */
#endif
 
#define SUCCESS 0
/* Device Declarations **************************** */
/* The name for our device, as it will appear 
 * in /proc/devices */
#define DEVICE_NAME "char_dev"
/* The maximum length of the message from the device */
#define BUF_LEN 80
/* Is the device open right now? Used to prevent 
 * concurent access into the same device */
static int Device_Open = 0;
/* The message the device will give when asked */
static char Message[BUF_LEN];
/* How far did the process reading the message 
 * get? Useful if the message is larger than the size 
 * of the buffer we get to fill in device_read. */
static char *Message_Ptr;
/* This function is called whenever a process 
 * attempts to open the device file */
static int device_open(struct inode *inode, 
                       struct file *file)
{
  static int counter = 0;
#ifdef DEBUG
  printk ("device_open(%p,%p)\n", inode, file);
#endif
  /* This is how you get the minor device number in 
   * case you have more than one physical device using 
   * the driver. */
  printk("Device: %d.%d\n", 
         inode->i_rdev >> 8, inode->i_rdev & 0xFF);
  /* We don't want to talk to two processes at the 
   * same time */
  if (Device_Open)
    return -EBUSY;
  /* If this was a process, we would have had to be 
   * more careful here.
   *
   * In the case of processes, the danger would be 
   * that one process might have check Device_Open 
   * and then be replaced by the schedualer by another 
   * process which runs this function. Then, when the 
   * first process was back on the CPU, it would assume 
   * the device is still not open. 
   *
   * However, Linux guarantees that a process won't be 
   * replaced while it is running in kernel context. 
   *
   * In the case of SMP, one CPU might increment 
   * Device_Open while another CPU is here, right after 
   * the check. However, in version 2.0 of the 
   * kernel this is not a problem because there's a lock 
   * to guarantee only one CPU will be kernel module at 
   * the same time. This is bad in  terms of 
   * performance, so version 2.2 changed it. 
   * Unfortunately, I don't have access to an SMP box 
   * to check how it works with SMP.
   */
  Device_Open++;
  /* Initialize the message. */
  sprintf(Message, 
    "If I told you once, I told you %d times - %s",
    counter++,
    "Hello, world\n");
  /* The only reason we're allowed to do this sprintf 
   * is because the maximum length of the message 
   * (assuming 32 bit integers - up to 10 digits
   * with the minus sign) is less than BUF_LEN, which 
   * is 80. BE CAREFUL NOT TO OVERFLOW BUFFERS, 
   * ESPECIALLY IN THE KERNEL!!! 
   */ 
  Message_Ptr = Message;
  /* Make sure that the module isn't removed while 
   * the file is open by incrementing the usage count 
   * (the number of opened references to the module, if 
   * it's not zero rmmod will fail)
   */
  MOD_INC_USE_COUNT;
  return SUCCESS;
}
/* This function is called when a process closes the 
 * device file. It doesn't have a return value in 
 * version 2.0.x because it can't fail (you must ALWAYS
 * be able to close a device). In version 2.2.x it is 
 * allowed to fail - but we won't let it. 
 */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
static int device_release(struct inode *inode, 
                          struct file *file)
#else 
static void device_release(struct inode *inode, 
                           struct file *file)
#endif
{
#ifdef DEBUG
  printk ("device_release(%p,%p)\n", inode, file);
#endif
 
  /* We're now ready for our next caller */
  Device_Open --;
  /* Decrement the usage count, otherwise once you 
   * opened the file you'll never get rid of the module.
   */
  MOD_DEC_USE_COUNT;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
  return 0;
#endif
}
/* This function is called whenever a process which 
 * have already opened the device file attempts to 
 * read from it. */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
static ssize_t device_read(struct file *file,
    char *buffer,    /* The buffer to fill with data */
    size_t length,   /* The length of the buffer */
    loff_t *offset)  /* Our offset in the file */
#else
static int device_read(struct inode *inode,
                       struct file *file,
    char *buffer,   /* The buffer to fill with 
                     * the data */ 
    int length)     /* The length of the buffer 
                     * (mustn't write beyond that!) */
#endif
{
  /* Number of bytes actually written to the buffer */
  int bytes_read = 0;
  /* If we're at the end of the message, return 0 
   * (which signifies end of file) */
  if (*Message_Ptr == 0)
    return 0;
  /* Actually put the data into the buffer */
  while (length && *Message_Ptr)  {
    /* Because the buffer is in the user data segment, 
     * not the kernel data segment, assignment wouldn't 
     * work. Instead, we have to use put_user which 
     * copies data from the kernel data segment to the 
     * user data segment. */
    put_user(*(Message_Ptr++), buffer++);
    length --;
    bytes_read ++;
  }
#ifdef DEBUG
   printk ("Read %d bytes, %d left\n",
     bytes_read, length);
#endif
   /* Read functions are supposed to return the number 
    * of bytes actually inserted into the buffer */
  return bytes_read;
}
/* This function is called when somebody tries to write 
 * into our device file - unsupported in this example. */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
static ssize_t device_write(struct file *file,
    const char *buffer,    /* The buffer */
    size_t length,   /* The length of the buffer */
    loff_t *offset)  /* Our offset in the file */
#else
static int device_write(struct inode *inode,
                        struct file *file,
                        const char *buffer,
                        int length)
#endif
{
  return -EINVAL;
}
/* Module Declarations ***************************** */
/* The major device number for the device. This is 
 * global (well, static, which in this context is global
 * within this file) because it has to be accessible 
 * both for registration and for release. */
static int Major;
/* This structure will hold the functions to be 
 * called when a process does something to the device 
 * we created. Since a pointer to this structure is 
 * kept in the devices table, it can't be local to
 * init_module. NULL is for unimplemented functions. */
struct file_operations Fops = {
  NULL,   /* seek */
  device_read, 
  device_write,
  NULL,   /* readdir */
  NULL,   /* select */
  NULL,   /* ioctl */
  NULL,   /* mmap */
  device_open,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
  NULL,   /* flush */
#endif
  device_release  /* a.k.a. close */
};
/* Initialize the module - Register the character device */
int init_module()
{
  /* Register the character device (atleast try) */
  Major = module_register_chrdev(0, 
                                 DEVICE_NAME,
                                 &Fops);
  /* Negative values signify an error */
  if (Major < 0) {
    printk ("%s device failed with %d\n",
            "Sorry, registering the character",
            Major);
    return Major;
  }
  printk ("%s The major device number is %d.\n",
          "Registeration is a success.",
          Major);
  printk ("If you want to talk to the device driver,\n");
  printk ("you'll have to create a device file. \n");
  printk ("We suggest you use:\n");
  printk ("mknod <name> c %d <minor>\n", Major);
  printk ("You can try different minor numbers %s",
          "and see what happens.\n");
  return 0;
}
/* Cleanup - unregister the appropriate file from /proc */
void cleanup_module()
{
  int ret;
  /* Unregister the device */
  ret = module_unregister_chrdev(Major, DEVICE_NAME);
 
  /* If there's an error, report it */ 
  if (ret < 0)
    printk("Error in unregister_chrdev: %d\n", ret);
}
-- 
Non c'è più forza nella normalità, c'è solo monotonia.

`sprintf_R3c2c5af5` ". Perché? Cose c'è che non va? 
Secondo me c'e' che hai un processore che scalda troppo (overclocking?
No, vero? :) ), per cui la coerenza della cache va a donnine allegre e
il compilatore ti mostra il suo vero io :)
La compilazione che ha prodotto questo errore era l'ultima di una
lunga serie di cicli compilazione-errore-veloce botta di
editor-ricompilazione? 
(per me lunga valeva 3)

 (per me lunga valeva 3)
non ho capito una mazza......
1) il mio vecchio pII non è overclockato, non posso permettermi di
fottermelo perché non avrei i soldi per comprarne uno nuovo... :-)
2) spero non mi si sia fottuta la cache, sarebbe una tragedia
3) il codice è stato messo nel file con una bella botta di copia
incolla.


non ho capito una mazza......
Me ne sono accorto.
Vatti a leggere /usr/doc/FAQ/txt/GCC-SIG11-FAQ , il problema a cui mi
riferisco io e' quello. 

Zefram Cochrane wrote:

Scusa ma piu' probabilmente ci sono problemi con i moduli 
versionig/non-versioning. Mentre per il simbolo put_user ci sara' qualche 
header mancante ( purtroppo hanno il vizio di "aggiornarsi" molto 
velocemente.
Non vedo perche' scomodare il SIG11 ( nel senso che NON vedo neanche un 
sintomo: lui non  ha parlato di compilazioni ripetute ne tantomeno del 
fatidico messaggio ).
Morale dai pure un occhiata quanto ti suggerisce Zefram Cochrane ( scusa ma 
quale e' il nome, davvero e' una curiosita ), ma non credo che sia quello 
il problema.

 il problema.
ho chiesto all'autore della guida: mancava il flag di compilazione -O2 .
Adesso mi chiedo: accipicchia, ok, con quella il codice viene
ottimizzato, ma perché rima non andava? Bene o male doveva essere solo
un po' meno performante ma funzionante, o no?


quale e' il nome, davvero e' una curiosita )
Quello che viene per prima :)

 un po' meno performante ma funzionante, o no?
Beh' se ti interessa sappi che se non usi gli switch -O2 non hai a 
disposizioni funzioni tipo in/out ( quelle che inviano byte alle porte I/O 
per intenderci )