/*demo_chr_dev.c*/
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/fs.h>
#include<linux/cdev.h>
//</span>
static struct cdev chr_dev;//定义一个字符设备对象
static dev_t ndev;//字符设备节点的设备号
static int chr_open(struct inode *nd,struct file *filp) //打开设备
{
int major=MAJOR(nd->i_rdev);
int minor=MINOR(nd->i_rdev);
printk("chr_open,major=%d,minor=%d\n",major,minor);
return 0;
}
static ssize_t chr_read(struct file *f,char __user *u,size_t sz,loff_t *off) //读取设备文件内容
{
printk("In the chr_read() function!\n");
return 0;
}
//关键数据结构
struct file_operations chr_ops=
{
.owner=THIS_MODULE,
.open=chr_open,
.read=chr_read,
};
static int demo_init(void) //模块初始化函数
{
int ret;
cdev_init(&chr_dev,&chr_ops);//初始化字符设备对象,chr_ops定义在上面
ret=alloc_chrdev_region(&ndev,0,1,"char_dev");//分配设备号
if(ret<0)
return ret;
printk("demo_init():major=%d,minor=%d\n",MAJOR(ndev),MINOR(ndev));
ret=cdev_add(&chr_dev,ndev,1);//将字符设备对象chr_dev注册到系统中
if(ret<0)
return ret;
return 0;
}
static void demo_exit(void)
{
printk("Removing chr_dev module...\n");
cdev_del(&chr_dev);//将字符设备对象chr_dev从系统中注销
unregister_chrdev_region(ndev,1);//释放分配的设备号
}
module_init(demo_init);
module_exit(demo_exit);
MODULE_LICENSE("GPL");
//main.c
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#define CHR_DEV_NAME "/dev/chr_dev"
int main()
{
int ret;
char buf[32];
int fd = open(CHR_DEV_NAME, O_RDONLY | O_NDELAY);
if(fd < 0)
{
printf("open failed!\n");
return -1;
}
read(fd, buf, 32);
close(fd);
return 0;
}
//Makefile
ifneq ($(KERNELRELEASE),)
obj-m:=world.o
else
KERNELDIR:=/lib/modules/$(shell uname -r)/build
PWD:=$(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.o *.mod.c *.mod.o *.ko
endif
操作步骤
1:dmesg
//生成设备文件节点
2:mknod /dev/chr_dev c 240 0
3:ls /dev/chr_dev
4:./main
5:dmesg -c