Linux 驱动软件测试,ldd(linux设备驱动程序)scull驱动程序测试

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define SCULL_QUANTUM 4000  //16*1024

#define SCULL_QSET  1000

//4*1024

int scull_major = 0; //动态分配主设备号

int scull_minor = 0;

typedef struct scull_qset Scull_Qset;

struct scull_qset {

void **data;

Scull_Qset *next;

};

struct scull_dev {

struct scull_qset *data;

struct cdev cdev;

int quantum;

int qset;

unsigned long size;

struct semaphore sem;

};

struct scull_dev* scull_devs;

static int scull_trim(struct scull_dev *dev)

{

int i;

struct scull_qset *next, *dptr;

int qset = dev->qset;

for(dptr = dev->data; dptr; dptr=next) //

{

if(dptr->data) {

for(i=0; i

kfree(dptr->data[i]);

kfree(dptr->data);

dptr->data = NULL;

}

next = dptr->next;

kfree(dptr);

}

dev->size = 0;

dev->quantum = SCULL_QUANTUM;

dev->qset  =

SCULL_QSET;

dev->data  =

NULL;

return 0;

}

//long sign;

Scull_Qset *scull_flow(struct scull_dev *dev, int count)

{

Scull_Qset *qset = dev->data;

if(!qset)

{

qset = kmalloc(sizeof(struct scull_qset), GFP_KERNEL);

if(qset == NULL)

return NULL;

memset(qset, 0, sizeof(struct scull_qset));

dev->data = qset;

}

while(count--)

{

if(!qset->next)

{

qset->next = kmalloc(sizeof(struct scull_qset),

GFP_KERNEL);

if(qset->next == NULL)

return NULL;

memset(qset->next, 0, sizeof(struct scull_qset));

}

qset = qset->next;

continue;

}

// sign = qset;

printk("the addr %x\n", qset);

return qset;

}

int scull_open(struct inode *inode, struct file *filp)

{

struct scull_dev *dev;

dev = container_of(inode->i_cdev, struct scull_dev,

cdev);

filp->private_data = dev;

if((filp->f_flags & O_ACCMODE) == O_WRONLY)

{

if (down_interruptible(&dev->sem))

return -ERESTARTSYS;

scull_trim(dev);

up(&dev->sem);

}

return 0;

}

int scull_release(struct inode *inode, struct file

*filp)

{

return 0;

}

ssize_t scull_read(struct file *filp, char __user *buf, size_t

count, loff_t *f_pos)

{

struct scull_dev *dev = filp->private_data;

struct scull_qset *dptr;

int quantum = dev->quantum, qset = dev->qset;

int itemsize = quantum*qset;

int item, s_pos, q_pos, rest;

ssize_t retval = 0;

if(down_interruptible(&dev->sem))

return -ERESTARTSYS;

if(*f_pos >= dev->size)

goto out;

if(*f_pos + count > dev->size)

count = dev->size - *f_pos;

item = (long)*f_pos / itemsize;

rest = (long)*f_pos % itemsize;

s_pos = rest / quantum; q_pos = rest % quantum;

dptr = scull_flow(dev, item);

printk("the addr %x\n",

dptr);

// dptr = sign;

if(dptr == NULL || !dptr->data ||

!dptr->data[s_pos])

goto out;

if(count > quantum - q_pos)

count = quantum - q_pos;

if(copy_to_user(buf, dptr->data[s_pos]+q_pos, count))

{

retval = -EFAULT;

goto out;

}

*f_pos += count;

retval = count;

out:

up(&dev->sem);

return retval;

}

ssize_t scull_write(struct file *filp, const char __user *buf,

size_t count, loff_t *f_pos)

{

struct scull_dev *dev = filp->private_data;

struct scull_qset *dptr;

int quantum = dev->quantum, qset = dev->qset;

int itemsize = quantum*qset;

int item, s_pos, q_pos, rest;

ssize_t retval = -ENOMEM;

if(down_interruptible(&dev->sem))

return -ERESTARTSYS;

item = (long)*f_pos / itemsize;

rest = (long)*f_pos % itemsize;

s_pos = rest / quantum; q_pos = rest % quantum;

dptr = scull_flow(dev, item);

if(dptr == NULL)

goto out;

if(!dptr->data) {

dptr->data = kmalloc(qset * sizeof(char*),

GFP_KERNEL);

if(!dptr->data)

goto out;

memset(dptr->data, 0, qset * sizeof(char*));

}

if(!dptr->data[s_pos]) {

dptr->data[s_pos] = kmalloc(quantum, GFP_KERNEL);

if(!dptr->data[s_pos])

goto out;

memset(dptr->data[s_pos], 0, quantum);

}

if(count > quantum - q_pos)

count = quantum - q_pos;

if(copy_from_user(dptr->data[s_pos]+q_pos, buf, count))

{

retval = -EFAULT;

goto out;

}

*f_pos += count;

retval = count;

if(dev->size < *f_pos)

dev->size = *f_pos;

out:

up(&dev->sem);

return retval;

}

struct file_operations scull_fops = {

.owner  = THIS_MODULE,

.open  = scull_open,

.release = scull_release,

.read  = scull_read,

.write  = scull_write,

};

static void scull_setup_cdev(struct scull_dev *dev, int

index)

{

int err, devno = MKDEV(scull_major, scull_minor +

index);

cdev_init(&dev->cdev, &scull_fops);

dev->cdev.owner = THIS_MODULE;

dev->cdev.ops = &scull_fops;

err = cdev_add(&dev->cdev, devno, 1);

if(err)

printk(KERN_NOTICE "Error %d adding scull%d", err,

index);

}

static  struct

class *scull_class;

static  struct

device

*scull_class_dev[4];

int scull_init_module(void)

{

int result, i;

dev_t dev = 0; //保存设备编号

result = alloc_chrdev_region(&dev, scull_minor, 4,

"scull");

scull_major = MAJOR(dev);

scull_devs = kmalloc(4*sizeof(struct scull_dev),

GFP_KERNEL);

memset(scull_devs, 0, 4*sizeof(struct scull_dev));

for(i=0; i<4; i++)

{

scull_devs[i].quantum = SCULL_QUANTUM;

scull_devs[i].qset  =

SCULL_QSET;

init_MUTEX(&scull_devs[i].sem);

scull_setup_cdev(&scull_devs[i], i);

}

//创建类

scull_class = class_create(THIS_MODULE, "SCULL");

//创建设备节点

for(i=0; i<4; i++)

{

scull_class_dev[i] = device_create(scull_class, NULL,

MKDEV(scull_major, scull_minor+i), NULL, "scull%d", i); //

"/dev/xyz"

}

return 0;

}

void scull_exit_module(void)

{

int i;

dev_t devno = MKDEV(scull_major, scull_minor);

if(scull_devs){

for(i=0; i<4; i++)

{

scull_trim(scull_devs + i);

cdev_del(&scull_devs[i].cdev);

}

}

kfree(scull_devs);

unregister_chrdev_region(devno, 4);

for(i=0; i<4; i++)

device_unregister(scull_class_dev[i]);

class_destroy(scull_class);

}

module_init(scull_init_module);

module_exit(scull_exit_module);

MODULE_LICENSE("GPL");

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值