驱动练习 阻塞

该博客展示了如何编写一个简单的Linux字符设备驱动程序,该程序包括打开、读取、写入和关闭操作。驱动程序使用wait_queue_head_t进行同步,并在用户空间通过/dev/mycdev0设备文件进行交互。用户空间程序打开设备文件,父进程写入数据,子进程读取并打印数据。
摘要由CSDN通过智能技术生成

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

#define CDEVNAME  "mycdev"
const int count = 3;
int major = 0;
int minor = 0;
struct class *cls;
struct device *dev;

struct cdev *cdev;
char kbuf[128] = {0};
int condition=0;
wait_queue_head_t wq; 
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 *offs)
{
        int ret;
        printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
        //1.¿¿¿¿¿¿
        if(file->f_flags&O_NONBLOCK)
        {
                //¿¿¿
                return -EINVAL;
        }
        else
        {

  ret=wait_event_interruptible(wq,condition);
                if(ret)
                {
                        printk("wait err\n");
                        return ret;
                }
        }
        //3.¿¿¿¿,¿¿¿¿¿¿¿
        if(size > sizeof(kbuf)) size = sizeof(kbuf);

        ret = copy_to_user(ubuf,kbuf,size);
        if(ret){
                printk("copy data to user error\n");
                return -EINVAL;
        }
        //4.¿¿¿condition¿¿¿¿¿

  condition=0;
        return size;

}
ssize_t mycdev_write(struct file *file, const char __user *ubuf,
        size_t size, loff_t *offs)
{
        int ret;
        printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);


        if(size > sizeof(kbuf)) size = sizeof(kbuf);

        ret = copy_from_user(kbuf,ubuf,size);
        if(ret){
                printk("copy data from user error\n");
                return -EINVAL;
        }

  condition=1;
        wake_up_interruptible(&wq);
        return size;
}

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

const struct file_operations fops = {
        .open    = mycdev_open,
        .read    = mycdev_read,
        .write   = mycdev_write,
        .release = mycdev_close,
};

static int __init mycdev_init(void)

  int ret,i;
        dev_t devm;
        //1.·ÖÅä¶ÔÏó
        cdev = cdev_alloc();
        if(cdev == NULL){
                printk("alloc memory error\n");
                ret = -ENOMEM;
                goto ERR_STEP0;
        }

        //2.³õʼ»¯
        cdev_init(cdev,&fops);

        //3.É豸ºÅµÄÉêÇë

        if(major > 0){

  //ÊÖ¶¯Ö¸¶¨
                ret = register_chrdev_region(MKDEV(major,minor),
                        count,CDEVNAME);
                if(ret){
                        printk("static:alloc device number error\n");
                        goto ERR_STEP1;
                }
        }else{
                //×Ô¶¯ÉêÇë
                ret = alloc_chrdev_region(&devm,minor,count,CDEVNAME);
                if(ret){
                        printk("dynaimc:alloc device number error\n");
                        goto ERR_STEP1;
                }
                major = MAJOR(devm);
                minor = MINOR(devm);
        }

        //4.×¢²á
        ret = cdev_add(cdev,MKDEV(major,minor),count);
        if(ret){
                printk("char device register error\n");
                goto ERR_STEP2;
        }

        //5.´´½¨class
        cls = class_create(THIS_MODULE,CDEVNAME);
        if(IS_ERR(cls)){
                printk("class create error\n");
                ret = PTR_ERR(cls);
                goto ERR_STEP3;
        }

        //6.´´½¨device
        for(i=0; i<count; i++){
                dev = device_create(cls,NULL,MKDEV(major,i),NULL,"mycdev%d",i);
                if(IS_ERR(dev)){
                        printk("device%d create error\n",i);
                        ret = PTR_ERR(dev);
                        goto ERR_STEP4;
                }
        }
        init_waitqueue_head(&wq);
        return 0; //²»ÄܺöÂÔ

ERR_STEP4:
        for(--i; i>=0; i--){
                device_destroy(cls,MKDEV(major,i));
        }
        class_destroy(cls);
ERR_STEP3:
        cdev_del(cdev);
ERR_STEP2:
        unregister_chrdev_region(MKDEV(major,minor),count);
ERR_STEP1:
        kfree(cdev);
ERR_STEP0:
        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");
———————————————————————————————————————————

#include <stdio.h>
  2 #include <sys/types.h>
  3 #include <sys/stat.h>
  4 #include <fcntl.h>
  5 #include <unistd.h>
  6 #include <string.h>
  7 
  8 char buf[128] = {0};
  9 
 10 int main(int argc, const char *argv[])
 11 {
 12         int fd;
 13         pid_t pid;
 14         fd=open("/dev/mycdev0",O_RDWR);
 15         pid=fork();
 16         if(pid<0)
 17         {
 18                 perror("fork fail\n");
 19                 return -1;
 20         }
 21         else if(pid==0)
 22         {
 23                 while(1)
 24                 {
 25                         memset(buf,0,sizeof(buf));
 26                         read(fd,buf,sizeof(buf));
 27                         printf("read data = %s\n",buf);
 28                 }
 29         }
 30         else
 31         {
 32                 while(1)
 33                 {
 34                 sleep(5);
 35 //              write(fd,buf,sizeof(buf));
 36                 }
 37         }

             close(fd);
 40 
 41         return 0;
 42 }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值