1,318
社区成员
发帖
与我相关
我的任务
分享
my_chrdev.c
#include <linux/init.h>//初始化头文件
#include <linux/module.h>//动态的将模块加载到内核中去常用的宏定义如 MODULE_LICESENCE(),MODULE_AUTHOR(),
#include <linux/kernel.h>
#include <linux/cdev.h>//包含了cdev 结构及相关函数的定义
#include <linux/types.h>//对一些特殊类型的定义,例如dev_t, off_t, pid_t
#include <linux/fs.h> //包含文件操作相关struct的定义,例struct file_operations
#include <linux/errno.h>//包含了对返回值的宏定义,这样用户程序可以用perror输出错误信息。
#include <linux/sched.h>//内核等待队列中要使用的TASK_NORMAL、TASK_INTERRUPTIBLE包含在这个头文件
#include <linux/mm.h>//内存管理头文件,含有页面大小定义和一些页面释放函数原型
#include <linux/slab.h>//包含了kcalloc、kzalloc内存分配函数的定义
#include <asm/io.h>//I/O头文件,以宏的嵌入汇编程序形式定义对I/O端口操作的函数
#include <asm/system.h>//系统头文件,定义了设置或修改描述符/中断门等的嵌入式汇编宏
#include <asm/uaccess.h>//与处理器相关的入口
#define MY_CHRDEV_SIZE 1024 //设备申请的内存空间1k
struct cdev cdev; //字符设备结构体
static int mychrdev_major=0; //主设备号变量
struct Device
{
char *data; //char数组指针,用于存放从用户读入的数据
long data_size; //存储的数据长度
} *pdev;
static int my_open(struct inode *inode, struct file *file)
{
file->private_data = pdev;
return 0;
}
static loff_t my_llseek(struct file *file, loff_t offset, int orig)
{
loff_t cfo=0; //current file offset
switch(orig)
{
case 0: cfo = offset; //SEEK_SET
break;
case 1: cfo = file->f_pos + offset; //SEEK_CUR
break;
case 2: cfo = MY_CHRDEV_SIZE - 1 + offset; //SEEK_END
break;
}
if ((cfo < 0) || (cfo > MY_CHRDEV_SIZE))
{
return -EINVAL;
}
file->f_pos = cfo;
return cfo;
}
//对应用户态的read,写数据到用户空间
static ssize_t my_read(struct file *file, const char __user *buf,
size_t count, loff_t *p_cfo)
{
int val=0;
struct Device *dev = file->private_data;//设备描述结构体指针,获取设备信息
if(copy_to_user(buf, (void *)(dev->data + *p_cfo), count))
val = -EFAULT;
else
{
*p_cfo += count;
val = count;
}
return val;
}
//对应用户态的write,从用户空间读入数据
static ssize_t my_write(struct file *file, const char __user *buf,
size_t count,loff_t *p_cfo)
{
int val = 0;
struct Device *dev = file->private_data;
if(copy_from_user(dev->data + *p_cfo), buf, count))
val = -EFAULT;
else
{
*p_cfo += count;
val = count;
}
return val;
}
struct int file_operations fops =
{
.owner = THIS_MODULE,
.llseek = my_llseek,
.read = my_read,
.write = my_write;
.open = my_open,
}
int __init init_module(void)
{
int dev_no;
if((dev_no= register_chrdev(0, "MyChrDev", &fops) < 0)
{
printk(KERN_INFO "MyChrDev: Fail to get major num.\n");
return dev_no;
}
if(mychrdev_major == 0)
mychrdev_major = dev_no;
cdev_init(&cdev, &fops);
cdev.owner = THIS_MODULE;
cdev.ops = &fops;
cdev_add(&cdev, MKDEV(mychrdev_major, 0), 1); //注册1个字符设备
//为设备描述结构体分配内存
pdev = kmalloc(sizeof(struct Device), GFP_KERNEL);
if(!pdev)
{
dev_no = -ENOMEM;
printk(KERN_INFO "MyChrDev: Fail to get memory.\n");
return dev_no;
}
(*pdev).size = MY_CHRDEV_SIZE;
(*pdev).data = kmalloc(MY_CHRDEV_SIZE, GFP_KERNEL);
memset((*pdev).data, 0, (*pdev).size);
return 0;
}
void __exit cleanup_module(void)
{
cdev_del(&cdev);//注销设备
kfree(pdev);//注销设备结构体
kfree((*pdev).data);//注销设备内存空间
unregister_chrdev(mychrdev_major, "MyChrDev");//卸载主设备号
}
MODULE_LICESENCE("Dual BSD/GLPL");
MODULE_AUTHOR("Lipeng Wan");
module_init(init_module);
module_exit(cleanup_module);
ifneq ($(KERNELRELEASE),)
#kbuild syntax
#the source file
mymodule-objs := my_chrdev.o
#the target file
obj-m := my_chrdev.o
else
#def some macros
PWD := $(shell pwd)
KVER ?= $(shell uname -r)
KDIR := /lib/modules/$(KVER)/build
all:
$(MAKE) -C $(KDIR) M=$(PWD)
clean:
rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions
endif
Makefile:1: *** recipe commences before first target。 停止。
#ifneq ($(KERNELRELEASE),)
#kbuild syntax
#the source file
mymodule-objs := my_chrdev.o
#the target file
obj-m := my_chrdev.o
#else
#def some macros
PWD := $(shell pwd)
KVER := $(shell uname -r)
KDIR := /lib/modules/$(KVER)/build
all:
$(MAKE) -C $(KDIR) M=$(PWD)
clean:
rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions
#endif
我之前已经注意了tab键的问题,检查后确认不是tab键的问题
我把那个判断注释掉之后,貌似可以消除前面的错误,但是又出现了一堆新的报错
我看到提示里面是Makefile,我重建的是makefile,于是更改过来(即把makefile重命名为Makefile)。
执行make后产生了一个build-in.o文件,仍然报错,但错误不一样了,报的都是一堆源码错误(这个我可以再改)。
觉得诡异的地方就是:为什么加了ifneq那个部分就有问题?难道是和版本有关?还是说这ubuntu kylin系统的原因?
总之,还是感谢回答。