Cdev—每个次设备一个缓冲

-------------driver----------------

cdev.c

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

MODULE_LICENSE("GPL");

dev_t devid;
char *name = "mychardev" ;
struct cdev cdev ;
struct file_operations ops;
struct class *cls ;
#define MINOR_NUM 3
#define GPECON 0x56000040

char * mybuff[MINOR_NUM]={NULL,NULL,NULL};
#define BUFFMAX 2048

unsigned int *gpecon,*gpedata ;

void mycdev_log(void)
{
    printk("hello_log");
   

}

int mychdev_open (struct inode * np, struct file * fp)
{
 //dev_t dev_id ;
// dev_id = MKDEV(imajor(np),iminor(np));
  fp->private_data = np ;
 
 if(mybuff[iminor(np)] == NULL)
     mybuff[iminor(np)] = (char *) kmalloc(BUFFMAX,GFP_KERNEL );
 
  printk("open mychdev =%d,%d=/n",imajor(np),iminor(np));
#if 0
  printk("open mychdev =%d,%d=/n",MAJOR(np->i_cdev->dev),MINOR(np->i_cdev->dev));
  printk("count =%d/n",np->i_cdev->count);   
 printk("open mychdev =%d,%d=/n",MAJOR(np->i_rdev),MINOR(np->i_rdev));
#endif
 return  0 ;           

}

int mechdev_release (struct inode * np , struct file * fp)
{
 
  kfree(mybuff[iminor(np)]);
  printk("release device :major:%d,minor:%d",imajor(np),iminor(np));
    return 0;

}

 ssize_t mychdev_read(struct file *file ,char __user * buff,size_t size, loff_t * off)
{
    *gpedata &= ~(0b11 << 12 );
    copy_to_user(buff,mybuff[iminor(file->private_data)],size);
    printk("usr private get: major:%d,minor:%d,and  read:%d/n",imajor(file->private_data),iminor(file->private_data),size);
    printk("usr dentry get: major:%d,minor:%d,and  read:%d/n",imajor(file->f_path.dentry->d_inode ),iminor(file->f_path.dentry->d_inode),size);
     return size ;
}

 ssize_t mychdev_write(struct file *file,const char __user *buff,size_t size,loff_t *off)
{
    *gpedata |= (0b11 << 12 );
        copy_from_user(mybuff[iminor(file->private_data)],buff,size);   
    printk("my cdev write:%d/n ",size);
    return size ;

}
int __init mycdev_init(void)
{

     size_t i ;
        printk(" mycdev init%s/n",__FUNCTION__);
       if( alloc_chrdev_region(&devid,0,MINOR_NUM,name) )       //分配驱动号(主设备号),次设备号
        {
         printk("alloc cdevid failed /n");
         return ENOMEM;
        }
     ops.read = mychdev_read ;
     ops.write = mychdev_write ;
     ops.open = mychdev_open ;
        //register_chrdev_region();
        cdev_init(&cdev,&ops);  //绑定设备与操作
        cdev_add(&cdev,devid,MINOR_NUM);

        cls = class_create(THIS_MODULE,name);    //创建类
    for(i=0;i<MINOR_NUM;i++)
        device_create(cls,NULL,MKDEV(MAJOR(devid),i),&cdev,"cdev%d",i);
    gpecon = ioremap(GPECON,8);
    gpedata = gpecon+1;
   
    *gpecon &= ~(0b1111<<24) ;
    *gpecon |=  (0b0101<<24) ;
   
    return 0;
}


void __exit mycdev_exit(void)
{
     size_t i ;
    cdev_del(&cdev);
    unregister_chrdev_region(devid,MINOR_NUM);

    for(i=0;i<MINOR_NUM;i++)
        device_destroy(cls,MKDEV(MAJOR(devid),i));
    class_destroy(cls);
   
        printk("hello exit %s/n",__FUNCTION__);
}

module_init(mycdev_init);
module_exit(mycdev_exit);

 

-------------------app------------

main.c

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
 int main()
{
 char * name = "/dev/cdev0";
 char * name1 = "/dev/cdev2";
 int fd ;
 int fd2 ;
 char buff[100] = "wakaka" ;
 char buff2[100] = "hahahah" ;
 char combuff[100];
 char combuff2[100];
 fd = open(name,O_RDWR);
 fd2 = open(name1,O_RDWR);
 
 if((fd < 0) || (fd2 < 0))
    {
    perror("open err:");
    return -1 ;
    }
 int i = 4;
 while( i -- )
    {
     printf("ops debug fd=%d /n",fd);
     write(fd,buff,9);
     write(fd2, buff2,23);   
     sleep(1);
     read(fd , combuff,9 );
     read(fd2 , combuff2,10 );   
     printf("from /dev/cdev0:%s/n",combuff);
     printf("from /dev/cdev2:%s/n",combuff2);
     sleep(1);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的字符设备驱动程序的C语言代码: ```c #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/cdev.h> #include <linux/uaccess.h> #define DEVICE_NAME "my_chardev" #define BUF_LEN 1024 static char msg[BUF_LEN]; static int msg_len = 0; static dev_t dev; static struct cdev c_dev; static struct class *cl; static int my_open(struct inode *i, struct file *f) { printk(KERN_INFO "my_chardev: open()\n"); return 0; } static int my_close(struct inode *i, struct file *f) { printk(KERN_INFO "my_chardev: close()\n"); return 0; } static ssize_t my_read(struct file *f, char __user *buf, size_t len, loff_t *off) { int bytes_read = 0; if (*off >= msg_len) return 0; if (*off + len > msg_len) len = msg_len - *off; bytes_read = copy_to_user(buf, msg + *off, len); *off += len - bytes_read; return len - bytes_read; } static ssize_t my_write(struct file *f, const char __user *buf, size_t len, loff_t *off) { int bytes_written = 0; if (*off + len > BUF_LEN) return -ENOSPC; bytes_written = copy_from_user(msg + *off, buf, len); *off += len - bytes_written; msg_len = *off; return len - bytes_written; } static struct file_operations my_fops = { .owner = THIS_MODULE, .open = my_open, .release = my_close, .read = my_read, .write = my_write }; static int __init my_chardev_init(void) { int ret = 0; printk(KERN_INFO "my_chardev: init()\n"); if ((ret = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME)) < 0) { return ret; } cdev_init(&c_dev, &my_fops); if ((ret = cdev_add(&c_dev, dev, 1)) < 0) { unregister_chrdev_region(dev, 1); return ret; } if (IS_ERR(cl = class_create(THIS_MODULE, DEVICE_NAME))) { cdev_del(&c_dev); unregister_chrdev_region(dev, 1); return PTR_ERR(cl); } if (IS_ERR(device_create(cl, NULL, dev, NULL, DEVICE_NAME))) { class_destroy(cl); cdev_del(&c_dev); unregister_chrdev_region(dev, 1); return PTR_ERR(cl); } return 0; } static void __exit my_chardev_exit(void) { printk(KERN_INFO "my_chardev: exit()\n"); device_destroy(cl, dev); class_destroy(cl); cdev_del(&c_dev); unregister_chrdev_region(dev, 1); } module_init(my_chardev_init); module_exit(my_chardev_exit); MODULE_LICENSE("GPL"); ``` 这个驱动程序创建了一个名为“my_chardev”的字符设备,它可以在用户空间中读取和写入数据。当用户打开设备文件时,驱动程序会在内核日志中输出“my_chardev: open()”信息;当用户关闭设备文件时,驱动程序会在内核日志中输出“my_chardev: close()”信息。 当用户读取设备文件时,驱动程序会将缓冲区中的数据复制到用户空间中,并返回实际读取的字节数。当用户写入设备文件时,驱动程序会将数据从用户空间复制到缓冲区中,并返回实际写入的字节数。 该驱动程序还使用了cdev结构体和class结构体来管理设备文件和设备节点。在模块初始化期间,它会申请一个设备号并将设备文件和设备节点添加到内核中。在模块退出期间,它会将设备文件和设备节点从内核中删除,并释放设备号。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值