2022.12.30work

内核完成IO多路复用

驱动文件定义__poll_t函数,完成等待队列的提交,返回唤醒条件变量

mycdev.c

#include <linux/init.h>
#include <linux/module.h>
#include<linux/cdev.h>
#include<linux/fs.h>
#include<linux/uaccess.h>
#include<linux/slab.h>
#include<linux/io.h>
#include<linux/device.h>
#include<linux/poll.h>

//定义字符设备驱动结构体对象指针
struct cdev *cdev;
#if 1
unsigned int major=0;//进行动态申请设备号
#else
unsigned int major=500;//进行静态指定设备号
#endif
unsigned int minor=0;//次设备号
int count=3;//设备数量
struct class *cls;//指向设备目录的指针
struct device *dev;//指向设备节点的指针
char kbuf[128]={0};
unsigned int condition=0;//用来表示数据是否准备好的标识
//定义等待队列头
wait_queue_head_t wq_head;


int mycdev_open(struct inode *inode, struct file *file)
{
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    return 0;   
}

ssize_t mycdev_read(struct file *file, char __user *ubuf, size_t size, loff_t *off)
{
    int ret;//定义变量接收函数返回值
            //将进程2的数据拷贝给进程1,模拟硬件数据
            if(size>sizeof(kbuf))
                size=sizeof(kbuf);
            //将kbuf的数据拷贝给用户空间
            ret=copy_to_user(ubuf,kbuf,size);
            if(ret)
            {
                printk("copy_to_user filed\n");
                return -EIO;
            }
            condition=0;
     
    return 0;
}

ssize_t mycdev_write(struct file *file, const char __user *ubuf, size_t size, loff_t *off)
{
    int ret;//定义变量接收函数返回值
     printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
     //先判断size的大小是否大于内核kbuf的大小,如果比kbuf大,把size的数据修改 为kbuf的大小
     if(size>sizeof(kbuf))
        size=sizeof(kbuf);
    //从进程2拷贝数据,给进程1
     ret=copy_from_user(kbuf,ubuf,size);
    if(ret)
    {
        printk("copy_from_user filed\n");
        return -EIO;
    }
   
   //唤醒进程2
   condition=1;
   wake_up_interruptible(&wq_head);

    return 0;
}

 __poll_t mycdev_poll(struct file *file, struct poll_table_struct *wait)
 {
    __poll_t mask=0;
    //向上提交等待队列头
    poll_wait(file,&wq_head,wait);
    //返回数值
    if(condition)
    {
        mask |= POLLIN;
    }
    return mask;

 }
int mycdev_close(struct inode *inode, struct file *file)
{
   
     printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    return 0;
}

//定义操作方法结构体
struct file_operations fops =
{
    .open=mycdev_open,
    .read=mycdev_read,
    .write=mycdev_write,
    .release=mycdev_close,
    .poll= mycdev_poll,
};


static int __init mycdev_init(void)
{
    int ret,i;
    dev_t devno;//设备号
    //给字符设备驱动对象申请空间
    cdev=cdev_alloc();
    if(cdev==NULL)
    {
        printk("给字符设备驱动对象申请空间失败\n");
        ret=-ENOMEM;
        goto ERR1;
    }
    printk("给字符设备驱动对象申请空间成功\n");
    //对象的初始化
    cdev_init(cdev,&fops);
    //申请设备号
    if(major==0)//动态申请
    {
        ret=alloc_chrdev_region(&devno,minor,count,"mycdev");
        if(ret)
        {
            printk("动态指定设备号失败\n");
            goto ERR2;
        }
        //获取主设备号和次设备号
        major=MAJOR(devno);//获取主设备号
        minor=MINOR(devno);//获取次设备号
    }
    else if(major>0)//静态指定
    {
        ret=register_chrdev_region(MKDEV(major,minor),count,"mycdev");
        if(ret)
        {
            printk("静态指定设备号失败\n");
            goto ERR2;
        }
    }
    printk("设备号申请成功\n");
    //将字符设备驱动注册进内核
    ret=cdev_add(cdev,MKDEV(major,minor),count);
    if(ret)
    {
        printk("字符设备驱动注册失败\n");
        goto ERR3;
    }
    //自动创建设备节点
    //向上提交提交目录
    cls=class_create(THIS_MODULE,"mycdev");
    if(IS_ERR(cls))
    {
        printk("向上提交目录失败\n");
        ret=PTR_ERR(cls);
        goto ERR4;
    }
    printk("向上提交目录成功\n");
    //向上提交设备节点
    for(i=0;i<count;i++)
    {
        dev=device_create(cls,NULL,MKDEV(major,i),NULL,"mycdev%d",i);
        if(IS_ERR(dev))
        {
            printk("向上提交节点信息失败\n");
            ret=PTR_ERR(dev);
            goto ERR5;
        }
    }
    printk("向上提交节点信息成功\n");

    //初始化等待队列头
    init_waitqueue_head(&wq_head);

    return 0;

ERR5:
    for(--i;i>=0;i--)
    {
        device_destroy(cls,MKDEV(major,i));
    }
    class_destroy(cls);
ERR4:
    cdev_del(cdev);
ERR3:
    unregister_chrdev_region(MKDEV(major,minor),count);
ERR2:
    kfree(cdev);
ERR1:
    return ret;
}


static void __exit mycdev_exit(void)
{
    //销毁设备节点
    int i;
    for(i=0;i<count;i++)
    {
        device_destroy(cls,MKDEV(major,i));
    }
    //销毁目录
    class_destroy(cls);
    
    //删除驱动对象
    cdev_del(cdev);
    //销毁设备号
    unregister_chrdev_region(MKDEV(major,minor),count);
    //释放动态申请的字符设备驱动的对象空间
     kfree(cdev);

}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以考虑以下几点来优化该 SQL 语句的性能: 1. 索引优化:对于涉及到大量数据的查询,合理设置索引可以显著提升查询性能。在这个语句中,可以在宽带账号、受理时间两个字段上创建索引。 2. 子查询优化:在语句中使用了子查询,这会增加查询的时间。可以将子查询的结果存储在一个临时表中,然后再将临时表与其他表进行 JOIN 操作。 3. 数据过滤:在 WHERE 子句中添加合适的过滤条件,可以减少需要查询的数据量,提高查询效率。 4. 数据库参数调整:针对具体的数据库,可以适当调整一些参数,如缓存大小等,以提高查询效率。 最终优化后的语句如下: ``` CREATE TEMPORARY TABLE temp_table AS SELECT 宽带账号, MAX(受理时间) AS 最近时间 FROM work0519.装移维标签清单 WHERE 受理时间 >= '2022-12-01' GROUP BY 宽带账号; UPDATE work.全量0520 JOIN work0519.装移维标签清单 ON work.全量0520.宽带账号 = work0519.装移维标签清单.宽带账号 JOIN temp_table ON work0519.装移维标签清单.宽带账号 = temp_table.宽带账号 AND work0519.装移维标签清单.受理时间 = temp_table.最近时间 SET work.全量0520.装维最近评价时间 = work0519.装移维标签清单.受理时间, work.全量0520.装维最近评价 = work0519.装移维标签清单.回复满意度; ``` 这样可以通过临时表和 JOIN 操作减少子查询的使用,同时添加了过滤条件和索引,提高了查询效率。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值