想自己做网站推广,做网站必须要服务器吗,seo关键词优化报价价格,app软件开发1 注册字符设备
1.1 结构体介绍
struct cdev
{struct kobject kobj;//表示该类型实体是一种内核对象struct module *owner;//填THIS_MODULE#xff0c;表示该字符设备从属于哪个内核模块const struct file_operations *ops;//指向空间存放着针对该设备的各种操作函数地址str…1 注册字符设备
1.1 结构体介绍
struct cdev
{struct kobject kobj;//表示该类型实体是一种内核对象struct module *owner;//填THIS_MODULE表示该字符设备从属于哪个内核模块const struct file_operations *ops;//指向空间存放着针对该设备的各种操作函数地址struct list_head list;//链表指针域使用hash链表来管理这么多设备dev_t dev;//设备号unsigned int count;//设备数量
};
1.2 定义方式
自己定义的结构体中必须有一个成员为 struct cdev cdev两种方法定义一个设备
直接定义定义结构体全局变量。一般写程序主要使用直接定义动态申请
struct cdev * cdev_alloc() 1.3 初始化
//设备操作函数集合
struct file_operations
{struct module *owner; //填THIS_MODULE表示该结构体对象从属于哪个内核模块int (*open) (struct inode *, struct file *); //打开设备int (*release) (struct inode *, struct file *); //关闭设备ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); //读设备ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); //写设备loff_t (*llseek) (struct file *, loff_t, int); //定位long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);//读写设备参数读设备状态、控制设备unsigned int (*poll) (struct file *, struct poll_table_struct *); //POLL机制实现多路复用的支持int (*mmap) (struct file *, struct vm_area_struct *); //映射内核空间到用户层int (*fasync) (int, struct file *, int); //信号驱动//......
};//使用这套操作函数来操作设备
void cdev_init(struct cdev *cdev,const struct file_operations *fops)
该对象各个函数指针成员都对应相应的系统调用函数应用层通过调用系统函数来间接调用这些函数指针成员指向的设备驱动函数 一般定义一个struct file_operations类型的全局变量并用自己实现各种操作函数名对其进行初始化
int cdev_add(struct cdev *p,dev_t dev,unsigned int count)
功能将指定字符设备添加到内核
参数p指向被添加的设备dev设备号count设备数量一般填1
void cdev_del(struct cdev *p)
功能从内核中移除一个字符设备
参数p指向被移除的字符设备
1.4 小结
字符设备驱动开发步骤 如果设备有自己的一些控制数据则定义一个包含struct cdev cdev成员的结构体struct mydev其它成员根据设备需求设备简单则直接用struct cdev 定义一个struct mydev或struct cdev的全局变量来表示本设备也可以定义一个struct mydev或struct cdev的全局指针记得在init时动态分配 定义三个全局变量分别来表示主设备号、次设备号、设备数 定义一个struct file_operations结构体变量其owner成员置成THIS_MODULE module init函数流程a. 申请设备号 b. 如果是全局设备指针则动态分配代表本设备的结构体元素 c. 初始化struct cdev成员 d. 设置struct cdev的owner成员为THIS_MODULE e. 添加字符设备到内核 module exit函数a. 注销设备号 b. 从内核中移除struct cdev c. 如果如果是全局设备指针则释放其指向空间 编写各个操作函数并将函数名初始化给struct file_operations结构体变量 验证操作步骤 编写驱动代码mychar.c make生成ko文件 insmod内核模块 查阅字符设备用到的设备号主设备号cat /proc/devices | grep 申请设备号时用的名字 创建设备文件设备节点 mknod /dev/??? c 上一步查询到的主设备号 代码中指定初始次设备号 编写app验证驱动testmychar_app.c 编译运行appdmesg命令查看内核打印信息
示例
mychar.c
#include linux/module.h
#include linux/kernel.h
#include linux/fs.h
#include linux/cdev.hint major 11;
int minor 0;
int mychar_num 1;struct cdev mydev;int mychar_open(struct inode *pnode, struct file *pfile)
{printk(mychar_open is called\n);return 0;
}int mychar_close(struct inode *pnode, struct file *pfile)
{printk(mychar_close is called\n);return 0;
}//结构体初始化:部分变量赋值初始化
struct file_operations myops {.owner THIS_MODULE,.open mychar_open,.release mychar_close,
};int mychar_init(void)
{int ret 0;dev_t devno MKDEV(major, minor);/* 申请设备号 */ret register_chrdev_region(devno, mychar_num, mychar);if (ret) {ret alloc_chrdev_region(devno, minor, mychar_num, mychar);if (ret) {printk(get devno failed\n);return -1;}major MAJOR(devno); // 容易遗漏注意}/* 给struct cdev对象指定操作函数集 */cdev_init(mydev, myops);/* 将 struct cdev对象添加到内核对应的数据结构里 */mydev.owner THIS_MODULE;cdev_add(mydev, devno, mychar_num);return 0;
}void __exit mychar_exit(void)
{dev_t devno MKDEV(major, minor);cdev_del(mydev);unregister_chrdev_region(devno, mychar_num);
}//表示支持GPL的开源协议
MODULE_LICENSE(GPL);module_init(mychar_init);
module_exit(mychar_exit);testmychar_app.c
#include sys/types.h
#include sys/stat.h
#include fcntl.h
#include unistd.h
#include sys/ioctl.h#include stdio.hint main(int argc,char *argv[])
{int fd -1;if(argc 2){printf(The argument is too few\n);return 1;}fd open(argv[1],O_RDWR);if(fd 0){printf(open %s failed\n,argv[1]);return 2;}close(fd);fd -1;return 0;
}Makefile
ifeq ($(KERNELRELEASE),)ifeq ($(ARCH),arm)
KERNELDIR ? /home/linux/Linux_4412/kernel/linux-3.14
ROOTFS ? /opt/4412/rootfs
else
KERNELDIR ? /lib/modules/$(shell uname -r)/build
endif
PWD : $(shell pwd)modules:$(MAKE) -C $(KERNELDIR) M$(PWD) modulesmodules_install:$(MAKE) -C $(KERNELDIR) M$(PWD) modules INSTALL_MOD_PATH$(ROOTFS) modules_installclean:rm -rf *.o *.ko .*.cmd *.mod.* modules.order Module.symvers .tmp_versionselse
CONFIG_MODULE_SIGn
obj-m mychar.oendif