linux module charactor device deamon code.

    技术2022-05-19  41

    声明:在注明出处的情况下可以随意转载(blog.csdn.net/innotech)

     

    本代码修改自the linux kernel module programming guaid version 2.6

    原本的代码是在2.6.10中编写的。调试的时候出现了错误。

    经过修改在2.6.32内核下编译运行。本代码只是实现了一个虚拟的字符型驱动。

    需要自己手动设置mknod major数需要通过查看/var/log/message得到。然后就是

    mknod /dev/<device name> c major 进行设置。

     

    具体修改为将

    init_module(void) -> module_init(function)

    cleanup_module(void) ->module_exit(function)

    更符合新版本内核模块风格。

     

    还有就是unregister_chrdev是否有返回,原文代码是有返回的并且测试了返回值。但是我编译却出现了错误。

    然后查看了内核中其他驱动程序的代码。发现都没有返回。因此我就取消了返回。没有错误,不知的为什么。

     

     

    /* * ===================================================================================== * * Filename: chardev.c * * Description: this a driver of a charactor device, which can return the number of * the times you have open the device whice you have mknod youself with 'mknod /dev/ * mychar major 0'. and then you can 'cat /dev/mychar or echo 'hi'>/dev/mychar which * will not used. * * Version: 1.0 * Created: 03/05/2011 03:02:55 PM * Revision: none * Compiler: gcc * * Author: WYong, yongwc@yeah.net * Company: InnoTech * * ===================================================================================== */ #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <asm/uaccess.h> #include <linux/fs.h> /*----------------------------------------------------------------------------- * Prototypes- this would normally go into a .h file *-----------------------------------------------------------------------------*/ int __init device_init(void); void __exit device_exit(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 part which define some macro which will used later *-----------------------------------------------------------------------------*/ #define SUCCESS 0 #define DEVICE_NAME "mychar" /* 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, which are just a global within thie * file. *-----------------------------------------------------------------------------*/ static int Major; /* the Major num of the device */ static int Device_open =0; /* wether the device is opened */ static char msg[BUF_LEN]; /* used to store the message */ static char *msg_Ptr; /* pointer of the start of msg */ static struct file_operations fops={ .read=device_read, .write=device_write, .open=device_open, .release=device_release }; /* * === FUNCTION ====================================================================== * Name: device_init * Description: this is the init of the device, just begin when the module is loaded. * ===================================================================================== */ int device_init(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; } /* * === FUNCTION ====================================================================== * Name: void device_exit(void) * Description: This function is called when the module is unloaded * ===================================================================================== */ void device_exit(void) { //Unregisted the device unregister_chrdev(Major, DEVICE_NAME); } /*----------------------------------------------------------------------------- * The follows define the method of the proccessing *-----------------------------------------------------------------------------*/ /* * === FUNCTION ====================================================================== * Name: device_open * Description: Called when a process tries to open the device file, like * "cat /dev/mychar" * ===================================================================================== */ static int device_open(struct inode *inode, struct file *file) { static int counter=0; if(Device_open) return -EBUSY; Device_open++; sprintf(msg, "I alread told you %d times Hello world!/n", counter++); msg_Ptr=msg; try_module_get(THIS_MODULE); return SUCCESS; } /* * === FUNCTION ====================================================================== * Name: device_release * Description: 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 rid of the module. module_put(THIS_MODULE); return 0; } /* * === FUNCTION ====================================================================== * Name: device_read * Description: Called when a process, which already opened the dev file, attempt 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 whice copies data //from kernel data segment to the user data segment. put_user(*(msg_Ptr++), buffer++); length--; bytes_read++; } //Most read function return the number of bytes put into the buffer return bytes_read; } /* * === FUNCTION ====================================================================== * Name: device_write * Description: Called when a process writes to dev file: echo "hi" > /dev/mychar * ===================================================================================== */ 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; } /*----------------------------------------------------------------------------- * The belows are just the init and exit macro used to init and exit funciton *-----------------------------------------------------------------------------*/ module_init(device_init); module_exit(device_exit);

     


    最新回复(0)