(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;
}
#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;
}
相关文章推荐
- (5)x210:2.4之前的字符驱动-动态获得mymajor主设备号
- (4)x210: 2.4之前的字符驱动
- (6)2.4之前的字符驱动-用devfs_register自动生成设备文件(可能在2.6linux目录树下编译不了)
- Linux2.6 驱动设计――从 2.4 到 2.6(转)
- Java多线程之模拟一个阻塞队列
- linux字符设备驱动-同步互斥阻塞笔记
- memdev.c字符设备驱动分析(转载)
- 学习领域驱动之前的准备——事件驱动
- 国嵌memdev驱动试验
- 从 2.4 到 2.6:Linux 内核可装载模块机制的改变对设备驱动的影响
- Linux驱动之阻塞与非阻塞
- Linux设备驱动之mmap设备操作(memdev.c字符设备驱动分析)
- "阻塞--中断"驱动模型在i2c在子系统、uart驱动、spi子系统中的实现
- 手机驱动的涉及
- 从 2.4 到 2.6:Linux 内核可装载模块机制的改变对设备驱动的影响
- Vue数据驱动模拟实现1
- Tiny6410开发板下块设备驱动程序的编写驱动之用内存模拟磁盘(一)
- WinPcap所涉及的Windows驱动基础知识(1)
- 从 2.4 到 2.6:Linux 内核可装载模块机制的改变对设备驱动的影响
- UNIX网络编程读书笔记:I/O模型(阻塞、非阻塞、I/O复用、信号驱动、异步)