open和release

//如下是一段增加了open和release的scull代码,还不完整,只是编译通过,暂时保存到这里,一会儿再修改。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/kernel.h>
//命令行参数
static char *whom="world";
static int howmany=1;
module_param(howmany,int,S_IRUGO);
module_param(whom,charp,S_IRUGO);
//命令行参数结束

//申请设备号需要的设备编号,主设备号,次设备号,申请结果
dev_t dev;
unsigned int scull_nr_devs=4;
unsigned int scull_major=0;  //全局变量,用来保存选择的主设备号
unsigned int scull_minor=0;  //保存次设备号
int result;
//申请设备号结束
loff_t scull_llseek(struct file *,loff_t, int);
ssize_t scull_read(struct file *,char __user *,size_t,loff_t *);
ssize_t scull_write(struct file *,const char __user *,size_t,loff_t *);
int scull_ioctl(struct inode *,struct file *,unsigned int,unsigned long);
int scull_open(struct inode *,struct file *);
int scull_release(struct inode *,struct file *);

struct scull_cdev{
    struct scull_qset *data;//指向第一个量子集的指针
    int quantum;//当前量子的大小
    int qset;//当前数组的大小
    unsigned long size;//保存其中的数据总量
    unsigned int access_key;//由sculluid和scullpriv使用
    struct semaphore sem;//互斥信号量
    struct cdev cdev;//字符设备结构
};

struct scull_cdev my_scull_cdev;  //一个scull_cdev设备
struct file_operations scull_fops={
    .owner=THIS_MODULE,
    .llseek=scull_llseek,
    .read=scull_read,
    .write=scull_write,
    .ioctl=scull_ioctl,
    .open=scull_open,
    .release=scull_release };    //fops
   
static void scull_setup_cdev(struct scull_cdev *dev,int index);  //完成将字符设备和设备编号连接起来   
void scull_cdev_del(struct scull_cdev *dev);  //注销字符设备

struct scull_qset;
//scull_trim方法实现
int scull_trim(struct scull_cdev *dev);

static int hello_init(void)//装载时运行
{
    int i;
    for(i=0;i<howmany;i++)
        printk(KERN_ALERT "hello %s./n",whom);//printk()内核态的输出函数;KERN_ALERT,显示的优先级

    if(scull_major)  //若默认的不是0,则
    {
        dev=MKDEV(scull_major,scull_minor);  //通过主设备号和次设备号得到设备编号
        result=register_chrdev_region(dev,scull_nr_devs, "scull");  //申请该设备编号
    }
    else    //若默认的主设备号是0,则
    {
        result=alloc_chrdev_region(&dev,scull_minor,scull_nr_devs,"scull");  //动态申请设备编号
        scull_major=MAJOR(dev);    //通过设备编号得到主设备号
        scull_minor=MINOR(dev);
    }  

    if(result<0) //申请设备编号失败
    {
        printk(KERN_WARNING "scull: can't get major %d/n",scull_major);
        return result;
    }
   
    //将设备编号和字符设备关联
    scull_setup_cdev(&my_scull_cdev,0);
    return 0;
}

static void hello_exit(void)//卸载时运行
{
    printk(KERN_ALERT "Goodbye,cruel world. My first drivers is over!/n");
    scull_cdev_del(&my_scull_cdev);
    unregister_chrdev_region(dev,scull_nr_devs);
}

static void scull_setup_cdev(struct scull_cdev *dev,int index)
{
    int err,devno=MKDEV(scull_major,scull_minor+index);
   
    cdev_init(&dev->cdev,&scull_fops);
    dev->cdev.ops=&scull_fops;
    err=cdev_add(&dev->cdev,devno,1);
    if(err)
        printk(KERN_NOTICE "Error %d adding scull %d",err,index);
}

//注销字符设备
void scull_cdev_del(struct scull_cdev *dev)
{
    cdev_del(&dev->cdev);
}

loff_t scull_llseek(struct file *f,loff_t l, int n){loff_t t=0;return t;}
ssize_t scull_read(struct file *f,char __user *s,size_t n,loff_t *l){ssize_t t=0;return t;}
ssize_t scull_write(struct file *f,const char __user *s,size_t n,loff_t *l){ssize_t t=0;return t;}
int scull_ioctl(struct inode *i,struct file *f,unsigned int n,unsigned long l){return 1;}
int scull_open(struct inode *inode,struct file *filp)
{
    struct scull_cdev *dev;
    dev=container_of(inode->i_cdev,struct scull_cdev,cdev);//从inode->i_cdev得到scull_dev的地址
    filp->private_data=dev;//为其它的方法
   
    //下面设置:若以写方式打开设备,则将它的长度截断为0
    if((filp->f_flags & O_ACCMODE)==O_WRONLY)
    {
        scull_trim(dev);//一个用于截短的宏
    }
   
    return 0;
}
int scull_release(struct inode *i,struct file *f)
{
    return 0;   
}

struct scull_qset
{
    void **data;
    struct scull_qset *next;
};
//scull_trim方法实现
int scull_trim(struct scull_cdev *dev)
{
    struct scull_qset *next,*dptr;
    int qset=dev->qset;
    int i;
    int scull_quantum=0;//自己加,因为原函数找不到
    int scull_qset=0;//自己加,因为原函数找不到
    for(dptr=dev->data;dptr;dptr=next)
    {
        if(dptr->data)
        {
            for(i=0;i<qset;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;
}
//声明init和exit方法
module_init(hello_init);    //指定装载时调用的函数
module_exit(hello_exit);    //指定卸载时调用的函数

//声明符合GPL
MODULE_LICENSE("Dual BSD/GPL");//告诉内核,该模块才用了自由许可证,否则转载时会遭到内核抱怨
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值