Linux内核调用设备驱动

来源:互联网 发布:智能电网通信网络 编辑:程序博客网 时间:2024/05/19 07:09

原文地址:http://blog.chinaunix.net/uid-22237530-id-1781802.html

最近做Linux下驱动程序遇到了不少问题。Linux下驱动程序的设计,参考的书籍有《Linux设备驱动》第二版和第三版。但是书籍上说的驱动程序的编写都是怎么供用户态使用,即用于内核和用户态的交互。但是现在做项目遇到了,在静态编译进内核的程序中调用驱动程序,这涉及了怎么在内核中调用驱动程序。查了很多书籍都没有介绍这方面的知识。经过几个星期的努力,不断上网找资料,终于实现了怎么在内核模块中调用驱动程序,下面和大家一起分享一下经验,希望对大家有帮助。同时我还有几个问题没有解决,望大家提点意见,谢了。

   下面是我参考书籍写的一个简单的字符设备驱动程序,如下:
#include
#include
#include
#include
#include
#include
#include
#include"chardev.h"
MODULE_LICENSE("GPL");
#define MAJOR_NUM 250//
ssize_t bao_read (struct file*,char*,size_t,loff_t*);
ssize_t bao_write (struct file*,const char*,size_t,loff_t*);
int bao_ioctl(struct inode *inode,struct file*filp,unsigned int cmd,unsigned long args);
int bao_open(struct inode *inode,struct file *filp);
int bao_release(struct inode *inode,struct file *filp);
//file_operations
struct file_operations bao_fops=
{
 read:bao_read,
 write:bao_write,
 ioctl:bao_ioctl,
 open:bao_open,
 release:bao_release,
 owner:THIS_MODULE,
};
static int bao_var=0;//baovar
static int bao_count=0;
static struct semaphore  sem;
static spinlock_t spin=SPIN_LOCK_UNLOCKED;
int __init bao_init(void)
{
 int ret;
 //
 ret=register_chrdev(MAJOR_NUM,"baovar",&bao_fops);
 if(ret)
 {
  printk("baovar register failure\n");
 }
 else
 {
  printk("baovar register success\n");
  init_MUTEX(&sem);
 }
 return ret;
}
void __exit bao_exit(void)
{
 int ret;
 
 //
 ret=unregister_chrdev(MAJOR_NUM,"baovar");
 if(ret)
 {
  printk("baovar unregister failure\n");
 }
 else
 {
  printk("baovar unregister success\n");
 }
}
int bao_open(struct inode *inode,struct file *filp)
{
 //
 spin_lock(&spin);
 //
 if(bao_count)
 {
  spin_unlock(&spin);
  return -EBUSY;
 }
 printk("baoopen\n");
 bao_count++;
 // spin_unlock(&spin);
 return 0;
}
int bao_release(struct inode *inode,struct file *filp)
{
 bao_count--;
 printk("close->bao\n");
 return 0;
}
ssize_t bao_read(struct file*filp,char *buf,size_t len,loff_t *off)
{
 //
 if(down_interruptible(&sem))
 {
  return -ERESTARTSYS;
 }
 //
 if(__copy_to_user(buf,&bao_var,sizeof(int)))
 {
  up(&sem);
  return -EFAULT;
 }
 up(&sem);
 return sizeof(int);
}
ssize_t bao_write(struct file*filp,const char *buf,size_t len,loff_t *off)
{
 //
 if(down_interruptible(&sem))
 {
  return -ERESTARTSYS;
 }
 //
 if(__copy_from_user(&bao_var,buf,sizeof(int)))
 {
  up(&sem);
  return -EFAULT;
 }
 //
 up(&sem);
 return sizeof(int);
}
int bao_ioctl(struct inode *inode,struct file*filp,unsigned int cmd,unsigned long args)
{
 if(_IOC_TYPE(cmd)!=BAO_IOCTL){return -EINVAL;}
 if(_IOC_NR(cmd)>BAO_IOCTL_MAXNR){return -EINVAL;}
 
 int ret;
 switch(cmd)
 {
  case IOCTL_READ:
   return __put_user(bao_var, (int *) args);
  case IOCTL_WRITE:
   {ret = __get_user(bao_var, (int *) args);
              if (ret)
                 return ret;
              printk("bao_var = %d\n", bao_var);
              break; }
  default:printk("error\n");
   
 }
 return 1;
}
module_init(bao_init);
module_exit(bao_exit);
以上是字符设备驱动模块
chardev.h头文件的内容如下:
#include
#define BAO_IOCTL 't'
#define IOCTL_READ  _IOR(BAO_IOCTL, 0, int)
#define IOCTL_WRITE  _IOW(BAO_IOCTL, 1, int)
#define BAO_IOCTL_MAXNR 1

下面是另一内核模块,在此模块中调用了以上驱动程序,成功的对设备进行操作:
  #include     
  #define   __KERNEL_SYSCALLS__  
  #ifdef   MODVERSIONS  
  #include     
  #endif   
  #include     
  #include     
  #include     
  #include     
  #include     
  #include  
  #include     
  #include     
  #include     
  #include  
  #include   "chardev.h"
  static inline _syscall3(int, ioctl, int ,fd,int, cmd,int*, arg);
  MODULE_LICENSE("GPL");
  static char buf1[20];
  static char buf2[20];
  #define  BEGIN_KMEM { mm_segment_t  old_fs  =  get_fs();  set_fs(get_ds());  
  #define  END_KMEM  set_fs(old_fs);  }  
   
  int   errno;  
  int   init_module(void){  
  int   err;
  int put,get;
  put=113579;
  sprintf(buf1,"%s","baoqunmin"); 
  printk("<1>Hello,world\n");  
  BEGIN_KMEM;  
  err=open("/dev/baovar",O_RDWR,0); 
  if(err>0)  
  printk("open   file   successful\n");
  write(err,buf1,sizeof(buf1));
  read(err,buf2,sizeof(buf2));
  buf2[20]='\n';
  printk("buf2-->%s\n",buf2);
  ioctl(err,IOCTL_WRITE,&put);
  ioctl(err,IOCTL_READ,&get);
  printk("get-->%d\n",get);
  END_KMEM;  
  return   0;  
  }  
  void   cleanup_module(void){  
  printk("<1>Goodbye   cruel   word\n");  
  }
说明:部分转载,详细的去访问原文

0 0
原创粉丝点击