打印

linux虚拟设备驱动程序(阻塞操作)

本帖已经被作者加入个人空间

linux虚拟设备驱动程序(阻塞操作)

学习中... 希望给其他初学者有帮助
这个小程序用到了LKM、设备驱动程序、进程阻塞操作等知识~~
一般在linux下设备分为字符设备和块设备。字符设备是指设备发送和接收数据以字符的形式进行;而块设备则以整个数据缓冲区的形式进行。
我的实验实现的字符设备,实现对设备中全局变量my_ver 的读写操作,字符设备驱动程序的入口点主要包括初始化字符设备、字符设备的I/O调用和中断,字符设备的初始化操作主要通过register_chrdev()函数完成,相对应的卸载时用unregister_chrdev()函数完成~
my_driver_read(struct file *filp, char *buf, size_t len, loff_t *off)
my_driver_write(struct file *filp, const char *buf, size_t len,loff_t *off)
这两个函数分别实现内核空间用户空间的数据交换,呵呵~~其实实现交换的是copy_to_user(buf, &my_ver, sizeof(int))和copy_from_user(&my_ver, buf, sizeof(int)),当然了模块得加载与卸载少不了module_init(my_driver_init)、
module_exit(my_driver_exit)这两个函数。
这里阻塞的意思是,当一个进程写操作执行后 其它进程才能进行读操作
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/wait.h>
#include <asm/semaphore.h>
MODULE_LICENSE("GPL");
#define MAJOR_NUM 254
static ssize_t my_driver_read(struct file *, char *, size_t, loff_t*);
static ssize_t my_driver_write(struct file *, const char *, size_t, loff_t*);
struct file_operations my_driver_fops =
{
 read: my_driver_read, write: my_driver_write,
};
static int my_ver = 0;
static struct semaphore sem;  //定义信号量
static wait_queue_head_t outq; //定义等待队列
static int flag = 0;
static int __init my_driver_init(void)
{
 int ret;
 ret = register_chrdev(MAJOR_NUM, "my_driver", &my_driver_fops);
 if (ret)
 {
  printk("my_driver register failure");
 }
 else
 {
  printk("my_driver register success");
  init_MUTEX(&sem);
  init_waitqueue_head(&outq);
 }
 return ret;
}
static void __exit my_driver_exit(void)
{
 int ret;
 ret = unregister_chrdev(MAJOR_NUM, "my_driver");
 if (ret)
 {
  printk("my_driver unregister failure");
 }
 else
 {
  printk("my_driver unregister success");
 }
}
static ssize_t my_driver_read(struct file *filp, char *buf, size_t len, loff_t *off)
{
 if (wait_event_interruptible(outq, flag != 0))
 {
  return - ERESTARTSYS;
 }
 if (down_interruptible(&sem))
 {
  return - ERESTARTSYS;
 }
 flag = 0;
 if (copy_to_user(buf, &my_ver, sizeof(int)))
 {
  up(&sem);
  return - EFAULT;
 }
 up(&sem);
 return sizeof(int);
}
static ssize_t my_driver_write(struct file *filp, const char *buf, size_t len,loff_t *off)
{
 if (down_interruptible(&sem))
 {
  return - ERESTARTSYS;
 }
 if (copy_from_user(&my_ver, buf, sizeof(int)))
 {
  up(&sem);
  return - EFAULT;
 }
 up(&sem);
 flag = 1;
 //通知数据可获得
 wake_up_interruptible(&outq);
 return sizeof(int);
}
module_init(my_driver_init);
module_exit(my_driver_exit);
我是在2.6的内核下做的实验,所以模块编译必须写Makefile文件
/////////////////////////////////Makefile
obj-m += driver_p.o
my_driver-objs = driver_p.o
CURRENT = $(shell uname -r)
KDIR = /lib/modules/$(CURRENT)/build
PWD = $(shell pwd)
default:
make -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
rm -f *.o *.ko *.mod.c
再来一个insmod drive_p.kp就模块加载就OK啦~~
加载模块后
可以写两个测试程序
一个实现读操作,一个实现写操作~~
///////////////////////////////////////read.c
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
main(){
int fd,num;
fd=open("/dev/my_driver",O_RDWR,S_IRUSR | S_IWUSR);
if(fd!=-1){
  while(1){
   read(fd,&num,sizeof(int));
   printf("the my_driver is %d\n",num);
   if(num==0){
    close(fd);
    break;
   }
  }
}
else{
  printf("device open failure\n");
}
}
//////////////////////////////////////////write.c
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
main(){
int fd,num;
fd=open("/dev/my_driver",O_RDWR,S_IRUSR | S_IWUSR);
if(fd!=-1){
  while(1){
   printf("please input the my_driver!\n");
   scanf("%d",&num);
   write(fd,&num,sizeof(int));
   if(num==0){
    close(fd);
    break;
   }
  }
}
else{
  printf("open my_driver failure\n");
}

}
******************************************                  
****************\\  - -  // *******************              
*************** (  @ @  )  *****************
┏━━━━oOOo-(_)-oOOo━━━━━┓
┃http://blog.ixpub.net/?uid/10509293  ┃
╭~~~~╮╭~~~~╮      o黒o黒 zZ

TOP

very good jiaocai

TOP


感谢一直以来您对我们的支持!
当前时区 GMT+8, 现在时间是 2008-9-5 22:56 京ICP证060528 号

Designed By 17DST