linux 2.6 一个简单的字符驱动程序
//#globalvar.c
#include //模块所需的大量符号和函数定义
#include //指定初始化和清楚函数
#include //文件系统相关的函数和头文件
#include //cdev结构的头文件
#include //在内核和用户空间中移动数据的函数
MODULE_LICENSE("GPL"); //指定代码使用的许可证
//文件操作函数的声明
int globalvar_open(struct inode *, struct file *);
int globalvar_release(struct inode *, struct file *);
ssize_t globalvar_read(struct file *, char *, size_t, loff_t *);
ssize_t globalvar_write(struct file *, const char *, size_t, loff_t *);
int dev_major = 50; //指定主设备号
int dev_minor = 0; //指定次设备号
struct file_operations globalvar_fops= //将文件操作与分配的设备号相连
{
owner: THIS_MODULE, //指向拥有该模块结构的指针
open: globalvar_open,
release: globalvar_release,
read: globalvar_read,
write: globalvar_write,
};
struct globalvar_dev //用来表示我们定义设备的结构
{
int global_var; //这个变量代表要操作的设备
struct cdev cdev; //内核中表示字符设备的结构
};
struct globalvar_dev *my_dev; //设备结构的指针
static void __exit globalvar_exit(void) //退出模块时的操作
{
dev_t devno=MKDEV(dev_major, dev_minor); //dev_t是用来表示设备编号的结构
cdev_del(&my_dev->cdev); //从系统中移除一个字符设备
kfree(my_dev); //释放自定义的设备结构
unregister_chrdev_region(devno, 1); //注销已注册的驱动程序
printk("globalvar unregister success/n");
}
static int __init globalvar_init(void) //初始化模块的操作
{
int ret, err;
dev_t devno=MKDEV(dev_major, dev_minor);
//动态分配设备号,次设备号已经指定
ret=alloc_chrdev_region(&devno, dev_minor, 1, "globalvar");
//保存动态分配的主设备号
dev_major=MAJOR(devno);
//根据期望值分配设备号
//ret=register_chrdev_region(devno, 1, "globalvar");
if(ret<0)
{
printk("globalvar register failure/n");
globalvar_exit(); //如果注册设备号失败就退出系统
return ret;
}
else
{
printk("globalvar register success/n");
}
//为设备在内核空间分配空间
my_dev=kmalloc(sizeof(struct globalvar_dev), GFP_KERNEL);
if(!my_dev)
{
ret=-ENOMEM; //如果分配失败返回错误信息
printk("create device failed/n");
}
else //如果分配成功就可以完成设备的初始化
{
my_dev->global_var=0; //设备变量初始化为0
cdev_init(&my_dev->cdev, &globalvar_fops); //初始化设备中的cdev结构
my_dev->cdev.owner=THIS_MODULE; //初始化cdev中的所有者字段
//my_dev->cdev.ops=&globalvar_fops;
err=cdev_add(&my_dev->cdev, devno, 1); //向内核添加这个cdev结构的信息
if(err<0)
printk("add device failure/n"); //如果添加失败打印错误消息
}
return ret;
}
//打开设备文件系统调用对应的操作
int globalvar_open(struct inode *inode, struct file *filp)
{
struct globalvar_dev *dev;
//根据inode结构的cdev字段,获得整个设备结构的指针
dev=container_of(inode->i_cdev, struct globalvar_dev, cdev);
//将file结构中的private_data字段指向已分配的设备结构
filp->private_data=dev;
return 0;
}
//关闭设备文件系统调用对应的操作
int globalvar_release(struct inode *inode, struct file *filp)
{
return 0;
}
//读设备文件系统调用对应的操作
ssize_t globalvar_read(struct file *filp, char *buf, size_t len, loff_t *off)
{
//获取指向已分配数据的指针
struct globalvar_dev *dev=filp->private_data;
//将设备变量值复制到用户空间
if(copy_to_user(buf, &dev->global_var, sizeof(int)))
{
return -EFAULT;
}
return sizeof(int); //返回读取数据的大小
}
//写设备文件系统调用对应的操作
ssize_t globalvar_write(struct file *filp, const char *buf, size_t len, loff_t *off)
{
//获取指向已分配数据的指针
struct globalvar_dev *dev=filp->private_data;
//从用户空间复制数据到内核中的设备变量
if(copy_from_user(&dev->global_var, buf, sizeof(int)))
{
return -EFAULT;
}
return sizeof(int); //返回写数据的大小
}
module_init(globalvar_init); //模块被装载时调用globalvar_init
module_exit(globalvar_exit); //模块被卸载时调用globalvar_exit
++++++++++++++++++++++++++++++++++++++++++++++++++++
# Makefile
ifneq ((shell uname -r)/build
PWD := (MAKE) -C (PWD) modules
clean:
(KERNELDIR) M=$(PWD) clean
endif
++++++++++++++++++++++++++++++++++++++++++++++++++++
//#test.c
#include
#include
#include
#include
main()
{
int fd, num;
fd=open("/dev/globalvar", O_RDWR, S_IRUSR|S_IWUSR); //可读写方式打开设备文件
if(fd!=-1)
{
read(fd, &num, sizeof(int)); //读取设备变量
printf("The globalvar is %d/n", num);
printf("Please input the num written to globalvar/n");
scanf("%d", &num);
write(fd, &num, sizeof(int)); //写设备变量
read(fd, &num, sizeof(int)); //再次读取刚才写的值
printf("The globalvar is %d/n", num);
close(fd); //关闭设备文件
}
else
{
printf("Device open failure/n");
}
}
++++++++++++++++++++++++++++++++++++++++++++++++++++
# gcc test.c
# mknod /dev/globalvar c 251 0
# rmmod globalvar.ko
# insmod globalvar.ko
# ./a.out
阅读(362) | 评论(0) | 转发(1) |
<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
#include //模块所需的大量符号和函数定义
#include //指定初始化和清楚函数
#include //文件系统相关的函数和头文件
#include //cdev结构的头文件
#include //在内核和用户空间中移动数据的函数
MODULE_LICENSE("GPL"); //指定代码使用的许可证
//文件操作函数的声明
int globalvar_open(struct inode *, struct file *);
int globalvar_release(struct inode *, struct file *);
ssize_t globalvar_read(struct file *, char *, size_t, loff_t *);
ssize_t globalvar_write(struct file *, const char *, size_t, loff_t *);
int dev_major = 50; //指定主设备号
int dev_minor = 0; //指定次设备号
struct file_operations globalvar_fops= //将文件操作与分配的设备号相连
{
owner: THIS_MODULE, //指向拥有该模块结构的指针
open: globalvar_open,
release: globalvar_release,
read: globalvar_read,
write: globalvar_write,
};
struct globalvar_dev //用来表示我们定义设备的结构
{
int global_var; //这个变量代表要操作的设备
struct cdev cdev; //内核中表示字符设备的结构
};
struct globalvar_dev *my_dev; //设备结构的指针
static void __exit globalvar_exit(void) //退出模块时的操作
{
dev_t devno=MKDEV(dev_major, dev_minor); //dev_t是用来表示设备编号的结构
cdev_del(&my_dev->cdev); //从系统中移除一个字符设备
kfree(my_dev); //释放自定义的设备结构
unregister_chrdev_region(devno, 1); //注销已注册的驱动程序
printk("globalvar unregister success/n");
}
static int __init globalvar_init(void) //初始化模块的操作
{
int ret, err;
dev_t devno=MKDEV(dev_major, dev_minor);
//动态分配设备号,次设备号已经指定
ret=alloc_chrdev_region(&devno, dev_minor, 1, "globalvar");
//保存动态分配的主设备号
dev_major=MAJOR(devno);
//根据期望值分配设备号
//ret=register_chrdev_region(devno, 1, "globalvar");
if(ret<0)
{
printk("globalvar register failure/n");
globalvar_exit(); //如果注册设备号失败就退出系统
return ret;
}
else
{
printk("globalvar register success/n");
}
//为设备在内核空间分配空间
my_dev=kmalloc(sizeof(struct globalvar_dev), GFP_KERNEL);
if(!my_dev)
{
ret=-ENOMEM; //如果分配失败返回错误信息
printk("create device failed/n");
}
else //如果分配成功就可以完成设备的初始化
{
my_dev->global_var=0; //设备变量初始化为0
cdev_init(&my_dev->cdev, &globalvar_fops); //初始化设备中的cdev结构
my_dev->cdev.owner=THIS_MODULE; //初始化cdev中的所有者字段
//my_dev->cdev.ops=&globalvar_fops;
err=cdev_add(&my_dev->cdev, devno, 1); //向内核添加这个cdev结构的信息
if(err<0)
printk("add device failure/n"); //如果添加失败打印错误消息
}
return ret;
}
//打开设备文件系统调用对应的操作
int globalvar_open(struct inode *inode, struct file *filp)
{
struct globalvar_dev *dev;
//根据inode结构的cdev字段,获得整个设备结构的指针
dev=container_of(inode->i_cdev, struct globalvar_dev, cdev);
//将file结构中的private_data字段指向已分配的设备结构
filp->private_data=dev;
return 0;
}
//关闭设备文件系统调用对应的操作
int globalvar_release(struct inode *inode, struct file *filp)
{
return 0;
}
//读设备文件系统调用对应的操作
ssize_t globalvar_read(struct file *filp, char *buf, size_t len, loff_t *off)
{
//获取指向已分配数据的指针
struct globalvar_dev *dev=filp->private_data;
//将设备变量值复制到用户空间
if(copy_to_user(buf, &dev->global_var, sizeof(int)))
{
return -EFAULT;
}
return sizeof(int); //返回读取数据的大小
}
//写设备文件系统调用对应的操作
ssize_t globalvar_write(struct file *filp, const char *buf, size_t len, loff_t *off)
{
//获取指向已分配数据的指针
struct globalvar_dev *dev=filp->private_data;
//从用户空间复制数据到内核中的设备变量
if(copy_from_user(&dev->global_var, buf, sizeof(int)))
{
return -EFAULT;
}
return sizeof(int); //返回写数据的大小
}
module_init(globalvar_init); //模块被装载时调用globalvar_init
module_exit(globalvar_exit); //模块被卸载时调用globalvar_exit
++++++++++++++++++++++++++++++++++++++++++++++++++++
# Makefile
ifneq ((shell uname -r)/build
PWD := (MAKE) -C (PWD) modules
clean:
(KERNELDIR) M=$(PWD) clean
endif
++++++++++++++++++++++++++++++++++++++++++++++++++++
//#test.c
#include
#include
#include
#include
main()
{
int fd, num;
fd=open("/dev/globalvar", O_RDWR, S_IRUSR|S_IWUSR); //可读写方式打开设备文件
if(fd!=-1)
{
read(fd, &num, sizeof(int)); //读取设备变量
printf("The globalvar is %d/n", num);
printf("Please input the num written to globalvar/n");
scanf("%d", &num);
write(fd, &num, sizeof(int)); //写设备变量
read(fd, &num, sizeof(int)); //再次读取刚才写的值
printf("The globalvar is %d/n", num);
close(fd); //关闭设备文件
}
else
{
printf("Device open failure/n");
}
}
++++++++++++++++++++++++++++++++++++++++++++++++++++
# gcc test.c
# mknod /dev/globalvar c 251 0
# rmmod globalvar.ko
# insmod globalvar.ko
# ./a.out
相关热门文章
给主人留下些什么吧!~~
评论热议
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通