/***************************************************************************************************
设备驱动程序
* globalvar.c
* 功 能:实现全局变量的读写
* 使用用户程序调用驱动模块的函数。
* 特 点:
需要手动加入节点,方法如下:
cat /proc/devices 查找要加入的设备名字(name)及设备号(unm)
mknod /dev/name c num 0 加入
加入了节点,在用户程序user.c才能找到该设备
固定分配设备号。
* 编译环境: SUSELinux 虚拟机
* 实 验 者:张永辉 2012年8月xx日
***************************************************************************************************/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
MODULE_LICENSE("GPL");
#define MAJOR_NUM 1024 //主设备号
static ssize_t globalvar_read (struct file *, char *, size_t, loff_t*);
static ssize_t globalvar_write(struct file *, const char *, size_t, loff_t*);
static int global_var = 0; //设备的全局变量
static ssize_t globalvar_read(struct file *filp, char *buf, size_t len, loff_t *off)
{
//将global_var从内核空间复制到用户空间
if ( copy_to_user(buf, &global_var, sizeof(int)))
{
return - EFAULT;
}
printk("globalvar_read enter ,the data is %d\n",global_var);
return sizeof(int);
}
static ssize_t globalvar_write(struct file *filp, const char *buf, size_t len, loff_t *off)
{
//将用户空间的数据复制到内核空间的global_var
if (copy_from_user(&global_var, buf, sizeof(int)))
{
return - EFAULT;
}
printk("globalvar_write enter ,the data is %d\n",global_var);
return sizeof(int);
}
//初始化字符设备驱动的file_operations结构体 read: globalvar_read, write: globalvar_write,
struct file_operations globalvar_fops =
{
.write = globalvar_write,
.read = globalvar_read,
};
static int __init globalvar_init(void)
{
int ret;
ret = register_chrdev(MAJOR_NUM, "globalvar", &globalvar_fops); //注册设备驱动
if (ret)
{
printk("globalvar register failure");
}else
{
printk("globalvar register success");
}
return ret;
}
//注销设备驱动
static void __exit globalvar_exit(void)
{
unregister_chrdev(MAJOR_NUM, "globalvar");
}
module_init(globalvar_init);
module_exit(globalvar_exit);
/***************************************************************************************************
* Makefile
***************************************************************************************************/
obj-m := globalvar.o #模块编译的目标必须以obj-m 这样的形式指出
KERNELDIR ?= /lib/modules/$(shell uname -r)/build #模块的编译必须指定内核源代码的路径
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules #本行开头必须使用 Tab 键
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
clearn:
rm -rf *.o *.ko *mod.o [mM]odule* .*.cmd .tmp_versions
/***************************************************************************************************
使用方法
共三个文件:globalvar.c 驱动代码
Makefile 用于编译驱动
user.c 用户程序,会使用globalvar驱动。
放到同一目录,做如下操作
#make 编译驱动
#insmod globalvar.ko 安装驱动
#lsmod 查看都有哪些驱动,是否成功安装
#cat /proc/devices 查找globalvar的设备号(此处是1024)
#mknod /dev/globalvar 1024 0 将设备加入节点
#gcc user.c 编译用户程序
#./a.out 执行用户程序,处会执行成功
...
#rmmod globalvar.ko 卸载驱动
#./a.out 执行用户程序,处会执行失败,以为没有globalvar模块了。
...
张永辉 2012年8月28日 suseLinux验证通过。
***************************************************************************************************/
#include <stdio.h>
#include <sys/stat.h> //获得文件的属性,它可以返回一个结构,里面包含文件全部属性
#include <fcntl.h> //设备驱动程序接口是由结构说明,它定义在fcntl.h中
#include <sys/types.h> //类型 clock_t,dev_t,off_t,ptrdiff,size_t,ssize_t,time_t
int main(void)
{
int fd, num;
fd = open("/dev/globalvar", O_RDWR, S_IRUSR | S_IWUSR);
printf("fd = %d \n",fd);
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");
}
return 0;
}