📄 1.c
字号:
#include "MyDriver.h"
MODULE_AUTHOR("Chen Xiangpeng");
MODULE_LICENSE("Dual BSD/GPL");
/*--------------------------------------*/
#define MEM_DEV_MAJOR 0
#define MEM_NR_DEVS 1
//IOW说明是用户向驱动程序写入参数
//IOR说明用户从驱动程序读取参数
#define MEM_IOC_MAGIC 'M'
#define MEM_IOC_SETSIZE _IO(MEM_IOC_MAGIC, 0)
#define MEM_IOC_PRINT _IO(MEM_IOC_MAGIC, 1)
#define MEM_IOC_GETOFFSET _IOR(MEM_IOC_MAGIC,2,long)
#define MEM_IOC_MAXNR 3 //这个一定要和上面一致
#define TYPE(dev) (MINOR(dev) >> 4) /* high nibble */
#define NUM(dev) (MINOR(dev) & 0xf) /* low nibble */
typedef struct{
long offset; //offset of the mem file
long size; //size of this mem file
char *base; //a pointer.
long usernum; //The use num of this device
struct semaphore sem;
devfs_handle_t handle;
}MEM,*MEMP;
/*--------------------------------------*/
static void exit_mem(void);
static int init_mem(void);
int MemInit(MEM *mem);
int MemDestroy(MEM *mem);
int MemPrint(MEM *mem);
int MemSetSize(MEM *mem , long size);
int MemOpen(struct inode *inode, struct file *filp);
int MemRelease(struct inode *inode, struct file *filp);
int MemIoctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
loff_t MemLlseek(struct file *filp, loff_t off, int whence);
ssize_t MemRead(struct file *filp, char *buf, size_t count,loff_t *f_pos);
ssize_t MemWrite(struct file *filp, const char *buf, size_t count,loff_t *f_pos);
/*--------------------------------------*/
struct file_operations mem_fops={
llseek: MemLlseek,
read: MemRead,
write: MemWrite,
ioctl: MemIoctl,
open: MemOpen,
release: MemRelease,
};
MEMP mem_devs; //一个指针
devfs_handle_t mem_devfs_dir;
int mem_major = MEM_DEV_MAJOR;
int mem_nr_devs = MEM_NR_DEVS;
static char mem_dev_name[4];
char *device_name = "CXPMEM";
/*--------------------------------------*/
int MemInit(MEM *mem)
{
mem->offset=0;
mem->size=0;
mem->base=NULL;
sema_init(&(mem->sem), 1);
mem->usernum=0;
return 0;
}
/*--------------------------------------*/
int MemDestroy(MEM *mem)
{
if(mem->base)
{
kfree(mem->base);
mem->base=NULL;
}
mem->size=0;
mem->offset=0;
return 0;
}
/*--------------------------------------*/
int MemPrint(MEM *mem)
{
long i;
printk("\n");
for(i=0;i<mem->size;i++)
{
if(mem->base[i])
printk("%c",mem->base[i]);
else
printk("@");
}
printk("\nsize=%ld\n",mem->size);
printk("offset=%ld\n",mem->offset);
return 0;
}
/*--------------------------------------*/
int MemSetSize(MEM *mem , long size)
{
MemDestroy(mem);
mem->base = kmalloc(size , GFP_KERNEL);
if(mem->base==NULL)
{
printk("can not alloc kernel memory!\n");
return -2;
}
memset(mem->base,0,size);
mem->size=size;
mem->offset=0;
return 0;
}
/*--------------------------------------*/
int MemOpen(struct inode *inode, struct file *filp)
{
MEMP mem=mem_devs;
int num=GetDeviceNum(inode);
int type=GetDeviceType(inode);
return 0;
}
int MemRelease(struct inode *inode, struct file *filp)
{
printk("Hello i am closed!\n");
return 0;
}
ssize_t MemRead(struct file *filp, char *buf, size_t count,loff_t *f_pos)
{
ssize_t ret=0;
ssize_t real=0;
MEMP mem;
printk("Hi you are reading me!\n");
if (down_interruptible(&(mem->sem)))
return -ERESTARTSYS;
mem=mem_devs;
if(mem->offset<0 || mem->offset >= mem->size)
{
goto out;
}
mem->usernum++;
if(mem->offset+count > mem->size)
{
real = mem->size - mem->offset;
}
else
{
real = count;
}
copy_to_user(buf, mem->base + mem->offset , real);
printk("%ld bytes read!\n",real);
mem->offset+=real;
ret=real;
out:
up(&mem->sem);
mem->usernum--;
return ret;
}
ssize_t MemWrite(struct file *filp, const char *buf, size_t count,loff_t *f_pos)
{
ssize_t ret=0;
ssize_t real=0;
MEMP mem;
mem=mem_devs;
if (down_interruptible(&(mem->sem)))
return -ERESTARTSYS;
if(mem->offset<0 || mem->offset >= mem->size)
{
goto out;
}
mem->usernum++;
if(mem->offset+count > mem->size)
{
real = mem->size - mem->offset;
}
else
{
real = count;
}
copy_from_user(mem->base + mem->offset, buf, real);
mem->offset+=real;
ret=real;
out:
up(&mem->sem);
mem->usernum--;
return ret;
}
int MemIoctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
int ret = 0;
MEMP mem=mem_devs;
if (_IOC_TYPE(cmd) != MEM_IOC_MAGIC) return -ENOTTY;
if (_IOC_NR(cmd) > MEM_IOC_MAXNR) return -ENOTTY;
if (!CheckUserMemory(cmd, arg))
{
printk("Check user memory error!\n");
return -EFAULT;
}
//////////////////////////////////
if (down_interruptible(&(mem->sem)))
return -ERESTARTSYS;
if(cmd==MEM_IOC_PRINT)
{
MemPrint(mem);
goto out;
}
if(cmd==MEM_IOC_SETSIZE)
{
MemSetSize(mem,arg);
goto out;
}
if(cmd==MEM_IOC_GETOFFSET)
{
__put_user(mem->offset, (long *)arg);
goto out;
}
out:
up(&mem->sem);
return ret;
}
loff_t MemLlseek(struct file *filp, loff_t off, int whence)
{
return 0;
}
/*--------------------------------------*/
static int init_mem(void)
{
int result, i;
printk("Hello world\n");
result = register_chrdev(mem_major, device_name, &mem_fops);
if (result < 0)
{
printk(KERN_WARNING "mem: can't get major %d\n",mem_major);
return result;
}
//如果mem_major为0则动态分配设备号
if (mem_major == 0) mem_major = result;
printk("major=%d\n",mem_major);
//为设备申请内存
mem_devs = kmalloc(mem_nr_devs * sizeof(MEM), GFP_KERNEL);
if (!mem_devs) {
result = -ENOMEM;
goto fail;
}
for (i=0; i < mem_nr_devs; i++)
{
MemInit(mem_devs+i);
}
MemSetSize(&mem_devs[0], 256L);
printk("We are cuccess!!\n");
return 0;
fail:
exit_mem();
return result;
}
/*--------------------------------------*/
static void exit_mem(void)
{
int i;
printk(KERN_ALERT "Goodbye world\n");
unregister_chrdev(mem_major, device_name);
if (mem_devs)
{
for (i=0; i<mem_nr_devs; i++)
{
MemDestroy(mem_devs+i);
}
kfree(mem_devs);
}
}
/*--------------------------------------*/
module_init(init_mem);
module_exit(exit_mem);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -