您的位置:首页 > 其它

(7)x210:2.4之前的驱动--memdev模拟驱动-涉及阻塞

2017-10-13 17:25 218 查看
1 memdev.h

#ifndef _MEMDEV_H_

#define _MEMDEV_H_

#include <linux/ioctl.h>

#ifndef MEMDEV_MAJOR

#define MEMDEV_MAJOR 0    //默认为0,由系统分配主设备号

#endif

#ifndef MEMDEV_NR_DEVS

#define MEMDEV_NR_DEVS 3    

#endif

#ifndef MEMDEV_SIZE

#define MEMDEV_SIZE 4096

#endif

typedef struct Mem_Dev {

wait_queue_head_t inq, outq;           //阻塞队列,入对,出对

   int rp;                                                      //读的到的位子

  int wp;                                                     //写到的位子

   char *data;

   struct Mem_Dev *next;   /* next listitem */

   unsigned long size;

   unsigned long remain_size;

} Mem_Dev;

2.memdev.c

#ifndef __KERNEL__

#define __KERNEL__

#endif

#ifndef MODULE

#define MODULE

#endif

//#include <linux/config.h>

#include <linux/module.h>

#include <linux/sched.h>

#include <linux/kernel.h>   

#include <linux/init.h>     

#include <linux/slab.h>   

#include <linux/fs.h>       

#include <linux/errno.h>    

#include <linux/types.h>    

#include <linux/proc_fs.h>

//#include <asm/system.h>  

#include <asm/uaccess.h>

#include "memdev.h"

MODULE_LICENSE("GPL");

Mem_Dev *mem_devices;

int memdev_major = MEMDEV_MAJOR;

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

{

    Mem_Dev *dev;

    

   

    int num = MINOR(inode->i_rdev);

    dev = (Mem_Dev *)filp->private_data;

    if (!dev)

    {

        if (num >= MEMDEV_NR_DEVS)

            return -ENODEV;

        dev = &mem_devices[num];

        filp->private_data = dev;

    }

    

    return 0;          

}

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

{

printk(KERN_INFO "close module");

    return 0;

}

ssize_t memdev_read(struct file *filp, char *buf, size_t count,

                loff_t *f_pos)

{

    Mem_Dev *dev = filp->private_data;

    int pos = *f_pos;

    ssize_t ret = 0;

            

    while (dev->rp == dev->wp) //如果读与写头相遇,表示读完了

    {

        if (filp->f_flags & O_NONBLOCK) //如果是非阻塞,立即返回

            return -EAGAIN;

    

    interruptible_sleep_on(&(dev->inq));  //驱动进入睡眠,进程也即睡眠,进入阻塞队列等待

    }

    

    count = min(count, (ssize_t)(dev->wp - dev->rp));

    

   

    if (copy_to_user(buf, &(dev->data[pos]), count))

    {

        ret = -EFAULT;

    goto out;

    }

    *f_pos += count; //当前打开的文件指针位置加 count

    dev->rp += count;  //驱动的读头也加


    ret = count;

printk(KERN_INFO "read =%s,count =%d\n",buf,count);

    

 out:

    return ret;

}

/*ÎÄŒþÐŽ²Ù×÷*/

ssize_t memdev_write(struct file *filp, const char *buf, size_t count,

                loff_t *f_pos)

{

    Mem_Dev *dev = filp->private_data;

    int pos = *f_pos;

    ssize_t ret = -ENOMEM;

    /*ÅжÏЎλÖÃÊÇ·ñÓÐЧ*/

    if (dev->wp + count > dev->size)

        count = (dev->size) - (dev->wp);

    

    /*ŽÓÓû§¿ÕŒäÐŽÈëÊýŸÝ*/

    if (copy_from_user(&(dev->data[pos]), buf, count))

    {

        ret = -EFAULT;

    goto out;

    }

printk(KERN_INFO "write =%s,count =%d\n",buf,count);

    /* »œÐѶÁœø³Ì */

    wake_up(&dev->inq);

    

    *f_pos += count;

    dev->wp += count;

    ret = count;

  out:

    return ret;

}

/*ÎÄŒþ¶šÎ»*/

loff_t memdev_llseek(struct file *filp, loff_t off, int whence)

{

    Mem_Dev *dev = filp->private_data;

    loff_t newpos;

    switch(whence) {

      case 0: /* SEEK_SET */

        newpos = off;

        break;

      case 1: /* SEEK_CUR */

        newpos = filp->f_pos + off;

        break;

      case 2: /* SEEK_END */

        newpos = dev->size -1 + off;

        break;

      default: /* can't happen */

        return -EINVAL;

    }

    if (newpos<0)

        return -EINVAL;

        

    filp->f_pos = newpos;

    return newpos;

}

/*

 * The following wrappers are meant to make things work with 2.0 kernels

 */

struct file_operations memdev_fops = {

    llseek:     memdev_llseek,

    read:       memdev_read,

    write:      memdev_write,

    open:       memdev_open,

    release:    memdev_release,

};

/*жÔغ¯Êý*/

void memdev_cleanup_module(void)

{

    int i;

    

   

    unregister_chrdev(memdev_major, "memdev");

    /*ÊÍ·ÅÄÚŽæ*/

    if (mem_devices)

    {

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

        kfree(mem_devices[i].data);

        kfree(mem_devices);

    }

}

/*ŒÓÔغ¯Êý*/

int memdev_init_module(void)

{

    int result, i;

    

    

    /*×¢²á×Ö·ûÉ豞*/

    result = register_chrdev(memdev_major, "memdev", &memdev_fops);

    if (result < 0)

    {

        printk(KERN_WARNING "mem: can't get major %d\n",memdev_major);

        return result;

    }

    if (memdev_major == 0)

        memdev_major = result;

    mem_devices = kmalloc(MEMDEV_NR_DEVS * sizeof(Mem_Dev), GFP_KERNEL);

    if (!mem_devices)

    {

        result = -ENOMEM;

        goto fail;

    }

    memset(mem_devices, 0, MEMDEV_NR_DEVS * sizeof(Mem_Dev));

 

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

    {

        mem_devices[i].size = MEMDEV_SIZE;

        mem_devices[i].data = kmalloc(MEMDEV_SIZE, GFP_KERNEL);

        memset(mem_devices[i].data, 0, MEMDEV_SIZE);

        

        init_waitqueue_head(&(mem_devices[i].inq));

    }

    

    return 0;

  fail:

    memdev_cleanup_module();

    return result;

}

module_init(memdev_init_module);

module_exit(memdev_cleanup_module);

3. fork.c

   #include <unistd.h>  

    #include <stdio.h>   

    #include <stdlib.h>   

    int main ()   

    {   

        pid_t fpid; //fpid表示fork函数返回的值  

        int count=0;  

        fpid=fork();   

        if (fpid < 0)   

            printf("error in fork!");   

        else if (fpid == 0) {  

            printf("i am the child process, my process id is %d\n",getpid());   

            count++;  

      FILE *fp = NULL;

        FILE *fp2 = NULL;

        char Buf[128];

        int i=0;    

        

        fp = fopen("/dev/memdev","r+");

        if (fp == NULL)

        {

        printf("Open Dev memdev0 Error!\n");

        return -1;

        }

      

 

       while(i<5)

       {

            i++;

             memset(Buf,128,0);

            fflush(stdin);

            fflush(stdout);

            gets(Buf);

         

                fwrite(Buf, sizeof(Buf), 1, fp);

            

            fflush(fp);

        }   

       sleep(5);

       fclose(fp);

           fclose(fp2);

        }  

        else {  

        printf("i am the parent process, my process id is %d\n",getpid());   

        count++;  

        FILE *fp = NULL;

            char Buf[128];

        int i=0;    

    

            fp = fopen("/dev/memdev","r+");

            if (fp == NULL)

            {

            printf("Open memdev0 Error!\n");

            return -1;

            }

    

    

        while(i<5)

        {        i++;

            memset(Buf,128,0);

            fread(Buf, sizeof(Buf), 1, fp);

            

            printf("Read BUF: %s\n",Buf);

         }   

            fclose(fp);

    }  

        printf("count=: %d/n",count);  

        return 0;  

    }  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: