LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 2716|回复: 4

第一个入门字符设备驱动程序的问题

[复制链接]
发表于 2007-5-5 21:33:11 | 显示全部楼层 |阅读模式
在Linux高级开发技术里面,第二章学了一点内核驱动,虽然里面排版巨烂,但勉强能很懂
按照它的程序,自己敲到机子上之后,编译总是能不过,提示
struct file_opterations有错不知道为啥,是不是结构体有问题???

请大虾看一下源码:

#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>

#define DEFAULT 0


unsigned int dev_major = 0;

static int dev_read(struct inode *node,struct file*file,char* buf,int i)
{
int a,b;
char* c = "hello";
int j;
if(verify_area(VERIFY_WRITE,buf,i) == DEFAULT)
return DEFAULT;
/* get_user(a,int(buf[0]));
get_user(b,int(buf[1]));
a = a+b;
*/
for(j = 0;j<i;j++)
{
buf[j] = c[j];
}
return i;
}

static int dev_write(struct inode *node,struct file*file,const char* buf,int count)
{
return count;
}

static int dev_open(struct inode *node,struct file*file)
{
/*MOD_INC_USE_COUNT;*/
return 0;
}

static void dev_release(struct inode *node,struct file*file)
{
/*MOD_DEC_USE_COUNT;*/
}

struct file_operations dev_fops = {
NULL,dev_read,dev_write,NULL,
NULL,NULL,NULL,dev_open,
dev_release,NULL,NULL,NULL,NULL
};

int init_module()
{
int result;
result = register_chrdev(0,"test",&dev_fops);
if(result < 0)
{
printk("Wrong!");
return result;
}
if(dev_major == 0)
dev_major = result;
return 0;
}

void cleanup_module()
{
unregister_chrdev(dev_major,"mydev");
}


应用程序的main函数:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
main()
{
int ret;
int buf[10];
ret = open("/dev/mydev",O_RDWR);
if(ret == -1)
{
printf("cann't open mydev");
exit(0);
}
/*printf("please input two number!");
scanf("%d",buf);
scanf("%d",buf+1);*/
read(ret,buf,1);
printf("the result is:%s",buf);
close(ret);
}


帮忙看下,有什么问题
还有呀,就是内核函数怎么查询???
用man put_user说查不到此函数,用man 2 put_user也查不到
不知道有什么手册没???

谢了
发表于 2007-5-11 23:40:55 | 显示全部楼层
应该是结构体问题,建议lz查一下源码,不同版本的内核结构体略有不同,以前的结构体赋值现在不一定能用
回复 支持 反对

使用道具 举报

发表于 2007-5-12 09:09:39 | 显示全部楼层
put_user()函数是在<asm/uaccess.h>头文件中的!
回复 支持 反对

使用道具 举报

发表于 2007-8-11 02:27:41 | 显示全部楼层
(尚观-linux开发小组成员)
1.你的驱动只能挂一个设备.
2.无法用udev生成,因为没有class.(register_chrdev已经过时了).
3.如果你想单独写一驱动包括子系统层.
#include "hello.h"

#define HELLO_MAX_DEVS 6

static dev_t         hello_base_id;
static int                 cur_dev_num = 0;
static struct class* hello_class;

typedef struct hello_dev {
        struct cdev chrdev;
        int dev_idx;
        u8* dma_buf;
        size_t cur_size;
}hello_dev_t;

static hello_dev_t* hi_dev[HELLO_MAX_DEVS];

static int __devinit hello_probe(struct platform_device *pdev);
static int __devexit hello_remove(struct platform_device *pdev);

static int hello_open(struct inode *inode, struct file *filp);
static int hello_close(struct inode *inode, struct file *filp);
static ssize_t hello_read(struct file *filp, char *buff, size_t count, loff_t *offp);
static ssize_t hello_write(struct file *filp, const char *buff, size_t count, loff_t *offp);


static int hello_open(struct inode *inode, struct file *filp)
{
        hello_dev_t* hdev;
        int idx;

        idx = iminor(inode) - MINOR(hello_base_id);
        hdev = hi_dev[idx];
       
        sprintf(hdev->dma_buf, "hello%d from kernel!", idx);
        hdev->cur_size = strlen(hdev->dma_buf);

        filp->private_data = hdev;

        return 0;
}

static int hello_close(struct inode *inode, struct file *filp)
{
        hello_dev_t* hdev;
        int idx;

        idx = iminor(inode) - MINOR(hello_base_id);
        hdev = hi_dev[idx];
       
        filp->private_data = NULL;

        printk("bye %d\n", hdev->dev_idx);
       
        return 0;
}

static ssize_t hello_read(struct file *filp, char *buff, size_t count, loff_t *offp)
{
        int ret;
        size_t len;
        hello_dev_t *hdev = filp->private_data;

        len = (count > hdev->cur_size) ? hdev->cur_size : count;

        ret = copy_to_user(buff, hdev->dma_buf, len);

        return len;
}

static ssize_t hello_write(struct file *filp, const char *buff, size_t count, loff_t *offp)
{
        int ret;
        size_t len;
        hello_dev_t *hdev = filp->private_data;

        len = (count < MEM_LEN) ? count : MEM_LEN;
       
        ret = copy_from_user(hdev->dma_buf, buff, len);

        hdev->cur_size = len;
       
        return len;
}


static struct platform_driver hello_driver = {
        .probe                = hello_probe,
        .remove                = hello_remove,
        .driver                = {
                .name        = HELLO_DEV_NAME,
                .owner        = THIS_MODULE,
        },
};


static struct file_operations hello_fops = {
        .owner         = THIS_MODULE,
        .open         = hello_open,
        .release = hello_close,
        .read        = hello_read,
        .write        = hello_write,
               
};

static int __devinit hello_probe(struct platform_device *pdev)
{
        int ret;
        dev_t dev_id;
        struct class_device* cls_dev;
        hello_dev_t *hdev;

        printk("device %s-%d detected!\n", pdev->name, pdev->id);

        hi_dev[cur_dev_num] = hdev = kzalloc(sizeof(hello_dev_t), GFP_KERNEL);

        hdev->dma_buf = kmalloc(MEM_LEN, GFP_KERNEL);
        hdev->dev_idx = cur_dev_num++;

        dev_id = MKDEV(MAJOR(hello_base_id), MINOR(hello_base_id) + hdev->dev_idx);
        pdev->dev.devt = dev_id;

        cdev_init(&hdev->chrdev, &hello_fops);
        hdev->chrdev.owner = THIS_MODULE;

        ret = cdev_add(&hdev->chrdev, dev_id, 1);
        if (ret)
        {
                printk("fail to register driver for " HELLO_DEV_NAME "%d!\n", pdev->id);
                return ret;
        }

        platform_set_drvdata(pdev, hdev);

       
        cls_dev = class_device_create(hello_class,
                                                 NULL,
                                                 dev_id,
                                                 &pdev->dev,
                                                 HELLO_DEV_NAME "%d", hdev->dev_idx
                                                 );
        if (IS_ERR(cls_dev))
                return PTR_ERR(cls_dev);


        printk("driver for "HELLO_DEV_NAME".%d (%d,%d) registered\n", hdev->dev_idx, MAJOR(dev_id), MINOR(dev_id));

        return ret;

}


static int __devexit hello_remove(struct platform_device *pdev)
{
        hello_dev_t* hdev;
       
        class_device_destroy(hello_class, pdev->dev.devt);

        hdev = platform_get_drvdata(pdev);

        if (hdev) cdev_del(&hdev->chrdev);

        kfree(hdev->dma_buf);
        kfree(hdev);

        platform_set_drvdata(pdev, NULL);
        pdev->dev.devt = 0;

        cur_dev_num--;
       
        printk(HELLO_DEV_NAME "%d removed!\n", pdev->id);       

        return 0;
}


static int __init hello_init(void)
{       
        int ret;

        cur_dev_num = 0;
       
        ret = alloc_chrdev_region(&hello_base_id,
                                                        10,
                                                        HELLO_MAX_DEVS,
                                                        HELLO_DEV_NAME
                                                        );
       
        if (ret)
                return ret;

        hello_class = class_create(THIS_MODULE, HELLO_DEV_NAME);
        if (IS_ERR(hello_class))
                return PTR_ERR(hello_class);

        ret = platform_driver_register(&hello_driver);

        return ret;
}

static void __exit hello_exit(void)
{
        platform_driver_unregister(&hello_driver);

        class_destroy(hello_class);

        unregister_chrdev_region(hello_base_id, HELLO_MAX_DEVS);
       
        printk("unregister driver " HELLO_DEV_NAME "\n");
}


module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");
回复 支持 反对

使用道具 举报

发表于 2007-8-11 02:40:49 | 显示全部楼层
udev自动生成设备名在/dev下,因为是模拟设备挂接在platform总线上.可以模拟1个和多个设备.
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表