Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1181724
  • 博文数量: 181
  • 博客积分: 4968
  • 博客等级: 上校
  • 技术积分: 1867
  • 用 户 组: 普通用户
  • 注册时间: 2008-01-13 21:52
文章分类

全部博文(181)

文章存档

2015年(2)

2013年(6)

2012年(22)

2011年(41)

2010年(27)

2009年(51)

2008年(32)

我的朋友

分类: LINUX

2009-03-02 22:09:18

1、驱动源代码
/*
 * gobalvar.c -- A simple virtual char device driver
 */
#include
#include
#include
#include
#include

MODULE_LICENSE("GPL");
MODULE_AUTHOR("leander");

#define MINIOR_NUM 0
#define DEVICE_SUM 1
#define MAJOR_NUM 254 /* major device number */
#define MINOR_NUM 0 /* minor device number */

static int globalvar_open(struct inode *inode, struct file *filp);
static int globalvar_release(struct inode *, struct file *filp);
static ssize_t globalvar_read(struct file*, char*, size_t, loff_t*);
static ssize_t globalvar_write(struct file*, const char*, size_t, loff_t*);

/* the major device number */
static int globalvar_major = MAJOR_NUM;
static int globalvar_minor = MINOR_NUM;

/* init the file_operations structure */
struct file_operations globalvar_fops =
{
    .owner = THIS_MODULE,
    .open = globalvar_open,
    .release = globalvar_release,
    .read = globalvar_read,
    .write = globalvar_write,
};

/* define a cdev device */
struct cdev *cdev;

static int global_var = 0; /* global var */

/* module init */
static int __init globalvar_init(void)
{
    int ret = 0;
    dev_t devno = MKDEV(MAJOR_NUM, MINOR_NUM);
    cdev = cdev_alloc();

    /* register the device driver */
    /*ret = alloc_chrdev_region(MAJOR_NUM, "globalvar", &globalvar_fops);*/
    if(register_chrdev_region(devno, DEVICE_SUM, "globalvar"))
    {
        /* register fail, so use automatic allocate */
        if(alloc_chrdev_region(&devno, globalvar_minor, DEVICE_SUM, "globalvar"))
            printk("globalvar register failure.\n");
        globalvar_major = MAJOR(devno);
    }
    else
    {
        /*
         * cdev_init should be use if use the way of static statement.
         * struct cdev cdev;
         * cdev_init(&cdev, &globalvar_fops);
         * cdev.owner = THIS_MODULE;
         *
         * if using dymatic allocation.
         * struct cdev *cdev;
         * cdev = cdev_alloc();
         * cdev->owner = THIS_MODULE;
         * cdev->ops = &globalvar_fops;
         */

        cdev->owner = THIS_MODULE;
        cdev->ops = &globalvar_fops;
        if ((ret = cdev_add(cdev, devno, 1)))
            printk(KERN_NOTICE "Error %d adding globalvar.\n", ret);
        else
            printk("globalvar register success.\n");
    }

    return ret;
}

/* module exit */
static void __exit globalvar_exit(void)
{
    dev_t devno = MKDEV(globalvar_major, 0);

    /* remove cdev from kernel */
    cdev_del(cdev);

    /* unregister the device driver */
    unregister_chrdev_region(devno, 1);

    /* free the dev structure */
    if(cdev)
        kfree(cdev);
    cdev = NULL;
}

/* open device */
static int globalvar_open(struct inode *inode, struct file *filp)
{
    int ret = 0;
    printk("open success.\n");
    return ret;
}

/* release device */
static int globalvar_release(struct inode *inode, struct file *filp)
{
    printk("release success.\n");
    return 0;
}

/* read device */
static ssize_t globalvar_read(struct file *filp, char *buf, size_t len, loff_t *off)
{
    printk("reading...\n");
    if(copy_to_user(buf, &global_var, sizeof(int)))
    {
        return -EFAULT;
    }
    return sizeof(int);
}

/* write device */
static ssize_t globalvar_write(struct file *filp, const char *buf, size_t len, loff_t *off)
{
    printk("writing...\n");
    if(copy_from_user(&global_var, buf, sizeof(int)))
    {
        return -EFAULT;
    }
    return sizeof(int);
}

/* module register */
module_init(globalvar_init);
module_exit(globalvar_exit);

2、Makefile文件
#
# Makefile -- for driver
#

module=globalvar

ifneq ($(KERNELRELEASE),)
    obj-m := ${module}.o
else
    KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
    rm -f *.o *.ko *.mod.c *~
insmod:
    sudo insmod ${module}.ko
    dmesg | tail
rmmod:
    sudo rmmod ${module}
    dmesg | tail
endif

3、测试程序
/*
 * test.c -- a test file for globalvar reading and writing
 */

#include
#include
#include
#include

int main(void)
{
    int fd, num;
    /*打开"/dev/globalvar"*/
    fd = open("/dev/globalvar", O_RDWR, S_IRUSR | S_IWUSR);
    if (fd != -1 )
    {
        /*初次读globalvar*/
        read(fd, &num, sizeof(int));
        printf("The globalvar is %d\n", num);

        /*写globalvar*/
        printf("Please input the num written to globalvar\n");
        scanf("%d", &num);
        write(fd, &num, sizeof(int));

        /*再次读globalvar*/
        read(fd, &num, sizeof(int));
        printf("The globalvar is %d\n", num);

        /*关闭"/dev/globalvar"*/
        close(fd);
    }
    else
    {
        /* if not sudo, maybe come here */
        printf("Device open failure\n");
    }

    return 0;
}

阅读(4723) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~