代码之家  ›  专栏  ›  技术社区  ›  matcheek

为Linux内核模块生成文件?

  •  9
  • matcheek  · 技术社区  · 14 年前

    我刚读了Linux内核模块编程指南,就被卡住了。 character device drivers example .

    提供了以前示例的makefile,但没有提供这个示例的makefile,因此我尝试创建一个:

    obj-m += chardev.o
    
    all:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
    
    clean:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
    

    我得到的结果是:

    maciej@jadwiga:~/Projects/os/chardev$ make
    make -C /lib/modules/2.6.26-2-686/build M=/home/maciej/Projects/os/chardev modules
    make[1]: Entering directory `/usr/src/linux-headers-2.6.26-2-686'
      CC [M]  /home/maciej/Projects/os/chardev/chardev.o
    /home/maciej/Projects/os/chardev/chardev.c: In function ‘cleanup_module’:
    /home/maciej/Projects/os/chardev/chardev.c:72: error: void value not ignored as it ought to be
    make[2]: *** [/home/maciej/Projects/os/chardev/chardev.o] Error 1
    make[1]: *** [_module_/home/maciej/Projects/os/chardev] Error 2
    make[1]: Leaving directory `/usr/src/linux-headers-2.6.26-2-686'
    make: *** [all] Error 2
    

    有人能帮忙吗?

    我要编译的文件:

    /*
     *  chardev.c: Creates a read-only char device that says how many times
     *  you've read from the dev file
     */
    
    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/fs.h>
    #include <asm/uaccess.h>    /* for put_user */
    
    /*  
     *  Prototypes - this would normally go in a .h file
     */
    int init_module(void);
    void cleanup_module(void);
    static int device_open(struct inode *, struct file *);
    static int device_release(struct inode *, struct file *);
    static ssize_t device_read(struct file *, char *, size_t, loff_t *);
    static ssize_t device_write(struct file *, const char *, size_t, loff_t *);
    
    #define SUCCESS 0
    #define DEVICE_NAME "chardev"   /* Dev name as it appears in /proc/devices   */
    #define BUF_LEN 80      /* Max length of the message from the device */
    
    /* 
     * Global variables are declared as static, so are global within the file. 
     */
    
    static int Major;       /* Major number assigned to our device driver */
    static int Device_Open = 0; /* Is device open?  
                     * Used to prevent multiple access to device */
    static char msg[BUF_LEN];   /* The msg the device will give when asked */
    static char *msg_Ptr;
    
    static struct file_operations fops = {
        .read = device_read,
        .write = device_write,
        .open = device_open,
        .release = device_release
    };
    
    /*
     * This function is called when the module is loaded
     */
    int init_module(void)
    {
            Major = register_chrdev(0, DEVICE_NAME, &fops);
    
        if (Major < 0) {
          printk(KERN_ALERT "Registering char device failed with %d\n", Major);
          return Major;
        }
    
        printk(KERN_INFO "I was assigned major number %d. To talk to\n", Major);
        printk(KERN_INFO "the driver, create a dev file with\n");
        printk(KERN_INFO "'mknod /dev/%s c %d 0'.\n", DEVICE_NAME, Major);
        printk(KERN_INFO "Try various minor numbers. Try to cat and echo to\n");
        printk(KERN_INFO "the device file.\n");
        printk(KERN_INFO "Remove the device file and module when done.\n");
    
        return SUCCESS;
    }
    
    /*
     * This function is called when the module is unloaded
     */
    void cleanup_module(void)
    {
        /* 
         * Unregister the device 
         */
        int ret = unregister_chrdev(Major, DEVICE_NAME);
        if (ret < 0)
            printk(KERN_ALERT "Error in unregister_chrdev: %d\n", ret);
    }
    
    /*
     * Methods
     */
    
    /* 
     * Called when a process tries to open the device file, like
     * "cat /dev/mycharfile"
     */
    static int device_open(struct inode *inode, struct file *file)
    {
        static int counter = 0;
    
        if (Device_Open)
            return -EBUSY;
    
        Device_Open++;
        sprintf(msg, "I already told you %d times Hello world!\n", counter++);
        msg_Ptr = msg;
        try_module_get(THIS_MODULE);
    
        return SUCCESS;
    }
    
    /* 
     * Called when a process closes the device file.
     */
    static int device_release(struct inode *inode, struct file *file)
    {
        Device_Open--;      /* We're now ready for our next caller */
    
        /* 
         * Decrement the usage count, or else once you opened the file, you'll
         * never get get rid of the module. 
         */
        module_put(THIS_MODULE);
    
        return 0;
    }
    
    /* 
     * Called when a process, which already opened the dev file, attempts to
     * read from it.
     */
    static ssize_t device_read(struct file *filp,   /* see include/linux/fs.h   */
                   char *buffer,    /* buffer to fill with data */
                   size_t length,   /* length of the buffer     */
                   loff_t * offset)
    {
        /*
         * Number of bytes actually written to the buffer 
         */
        int bytes_read = 0;
    
        /*
         * If we're at the end of the message, 
         * return 0 signifying end of file 
         */
        if (*msg_Ptr == 0)
            return 0;
    
        /* 
         * Actually put the data into the buffer 
         */
        while (length && *msg_Ptr) {
    
            /* 
             * The buffer is in the user data segment, not the kernel 
             * segment so "*" assignment won't work.  We have to use 
             * put_user which copies data from the kernel data segment to
             * the user data segment. 
             */
            put_user(*(msg_Ptr++), buffer++);
    
            length--;
            bytes_read++;
        }
    
        /* 
         * Most read functions return the number of bytes put into the buffer
         */
        return bytes_read;
    }
    
    /*  
     * Called when a process writes to dev file: echo "hi" > /dev/hello 
     */
    static ssize_t
    device_write(struct file *filp, const char *buff, size_t len, loff_t * off)
    {
        printk(KERN_ALERT "Sorry, this operation isn't supported.\n");
        return -EINVAL;
    }
    
    3 回复  |  直到 11 年前
        1
  •  5
  •   Ignacio Vazquez-Abrams    14 年前
    obj-m += chardev.o
    
        2
  •  2
  •   ranganath    11 年前

    实际上,驱动程序是由宏模块init(myinit)加载的; 这里 我的初始化 “可以是用户指定的函数,并且 Mudule_出口(我的清理); 在这里 我的出口 可以是用户指定的函数。上面的代码中缺少这两个宏。

    生成文件: 这个 obj-m+=chardev.o 将替换为 obj-m:=chardev.o .

    我也是法学博士的初学者。如果有什么错误,请告诉我。

        3
  •  0
  •   Lam Hai Son    11 年前

    因为函数unregister不返回值。这是一个有用的链接。 http://forum.kernelnewbies.org/read.php?17,1114