您的位置:首页 > 运维架构 > Linux

linux字符设备驱动程序

2015-03-04 20:18 267 查看
        自己正在慢慢学习linux及其相关知识,一直在不断探索者,希望经过自己的努力能够有所收获,最近学到linux设备驱动程序,也参考了网上的很多实例,里面涉及到的几个程序都是参照至网易的一篇博客:“linux字符设备驱动实例”

一、各项源文件

     (1)驱动程序源文件:

   linux各个头文件作用

<span style="font-size:14px;">#include<linux/module.h> //动态的讲模块加载到内核中去
#include<linux/init.h> //包含模块初始化定义,以及一些函数的初始化函数
#include<linux/fs.h> //定义了file struct结构体
#include<linux/cdev.h>
#include<asm/uaccess.h>
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=   //</span><span style="font-family: 'Microsoft YaHei'; line-height: 26px; "><span style="font-size:12px;">ISO C99标准初始化结构体,可以使用.owner=THIS MOUDLE</span></span><span style="font-size:14px;">
{
owner:THIS_MODULE,
open:globalvar_open,
release:globalvar_release,
read:globalvar_read,
write:globalvar_write,
};
struct globalvar_dev
{
int global_var;
struct cdev cdev; //该结构体代表字符设备,定义在linux/cdev 中
};
struct globalvar_dev *my_dev;
static void __exit globalvar_exit(void)
{
printk("<1>exit_JunYao\n");
dev_t devno=MKDEV(dev_major,dev_minor); //dev_t 是 32 位的量, 12 位用作主编号, 20 位用作次编号
cdev_del(&my_dev->cdev);
kfree(my_dev);
unregister_chrdev_region(devno,1);
printk("<1>globalvar unregister success\n");
}
static int __init globalvar_init(void)
{
int ret,err;
printk("<1>init_JunYao\n");
dev_t devno=MKDEV(dev_major,dev_minor);
ret=alloc_chrdev_region(&devno,dev_minor,1,"globalvar");
dev_major=MAJOR(devno);
if(ret<0)
{
printk("<1>globalvar register failure\n");
globalvar_exit();
return ret;
}
else
{
printk("<1>glabalvar register success\n");
}
my_dev=kmalloc(sizeof(struct globalvar_dev),GFP_KERNEL);
if(!my_dev)
{
ret=-ENOMEM;
printk("<1>create device failed\n");
}
else
{
printk("<1>create device success\n");
my_dev->global_var=0;
cdev_init(&my_dev->cdev,&globalvar_fops); //初始化字符设备
my_dev->cdev.owner=THIS_MODULE;
err=cdev_add(&my_dev->cdev,devno,1); //添加字符设备
if(err<0)
printk("<1>add device failure\n");

}
printk("<1>add device success\n");
return ret;
}
int globalvar_open(struct inode *inode,struct file *filp)
{
printk("<1>try to open\n");
struct globalvar_dev *dev;
dev=container_of(inode->i_cdev,struct globalvar_dev,cdev);
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);
module_exit(globalvar_exit);

</span>


 (2)Makefile 

ifneq ($(KERNELRELEASE),)
obj-m :=  globalvar.o
else
KDIR := /home/guagua/linux-2.6.32
all:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -f *.ko *.o *.mod.ko *.mod.c *.symvers
endif


 (3)测试程序test

#include<sys/types.h>
#include<sys/stat.h>
#include<stdio.h>
#include<fcntl.h>
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 number written to globalar\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 %d\n",fd);
}
}


二、(1) 编译内核模块:make Makefile

         (2)安装内核模块:insmod globarval.ko

         (3)编译测试程序:gcc test.c  -o test

         (4)查看设备编号,cat /proc/devices 在globarval前面的就是主设备编号

          (5)创建设备文件 mknod  /dev/globarval c ***  ###    ***为上部查找到的主设备编号,次设备编号自己选择。

          (6)运行测试程序 ./test

三、运行结果

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: