Chinaunix首页 | 论坛 | 博客
  • 博客访问: 6087465
  • 博文数量: 2759
  • 博客积分: 1021
  • 博客等级: 中士
  • 技术积分: 4091
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-11 14:14
文章分类

全部博文(2759)

文章存档

2019年(1)

2017年(84)

2016年(196)

2015年(204)

2014年(636)

2013年(1176)

2012年(463)

分类: 嵌入式

2013-12-06 03:12:58

应用的层的操作最终会调用驱动层的操作
应用层 open read write close





驱动层 open read write release

一、open:
int  (*open)  (struct inode * , struct file*)
作用:1、统计资源,检查错误
           2、申请资源
           3、识别次设备号,如有必要更新f_op 指针 (支持多个设备)

在应用层,例如打开一个设备文件    fd = open ("/dev/hello" , O_RDONLY);
open函数,调用系统下的sys_open,然后继续调用虚拟文件系统下的vfs_open函数,创建两个结构体struct inode 和struct  file ;
结构体struct  inode{
...
i_rdev;    //存放设备号地址
i_cdev;    //存放cdev的地址
...
}
结构体struct  file{
...
f_op;    //保存操作集合的地址struct file_operations
...
}
在驱动层struct cdev里的结构体成员 设备号 和 操作集合 这样就和 应用层的open 函数 联系了起来。
代码实现如下:

点击(此处)折叠或打开

  1. static int hello_open (struct inode *inode, struct file *file)
  2. {
  3.   printk (KERN_INFO "Hey! device opened\n");
  4.   return 0;
  5. }
二、release:
open的逆操作,对应于应用层的close 函数。
用法同open
代码实现如下:

点击(此处)折叠或打开

  1. static int hello_release (struct inode *inode, struct file *file)
  2. {
  3.   printk (KERN_INFO "Hmmm! device closed\n");
  4.   return 0;
  5. }

三、read:

点击(此处)折叠或打开

  1. ssize_t hello_read (struct file *filp, char *buff, size_t count, loff_t *offp)  //filp为定义的结构体指针,buff 为要读的首地址,count为读成功的字节数,第四个参数实现随机访问,一般不用
  2. {
  3.   ssize_t result = 0;
  4.   
  5.   if (count < 0) return -EINVAL;
  6.   if (count > 127) count = 127;  //如果大于缓冲区的大小127,则读127个字节

  7.   if (copy_to_user (buff, data, count))
  8. //返回值为没有copy成功的字节数,此函数有可能引起系统睡眠,不能用于中断。
  9.   {
  10.     result = -EFAULT;    //此错误码返回给应用层下的errno,
  11.   }
  12.   else
  13.   {
  14.     printk (KERN_INFO "wrote %d bytes\n", count);
  15.     result = count;
  16.   }
  17.    
  18.   return result;
  19. }
四、write
write用法同read。 

点击(此处)折叠或打开

  1. ssize_t hello_write (struct file *filp, const char *buf, size_t count, loff_t *f_pos)
  2. {
  3.   ssize_t ret = 0;

  4.   //printk (KERN_INFO "Writing %d bytes\n", count);
  5.   if (count > 127) return -ENOMEM;    //大于127返回给errno,内存不足
  6.   if (copy_from_user (data, buf, count))    //同样copy_fron_user 不能用于中断。 
  7.   {
  8.     ret = -EFAULT;
  9.   }
  10.   else {
  11.     data[count] = '\0';
  12.     printk (KERN_INFO"Received: %s\n", data);
  13.     ret = count;
  14.   }

  15.   return ret;
  16. }
五、mmap
int (*mmap) (struct file *,  struct vm_area_struct *)
把设备内存空间映射到用户空间访问,提高访问效率,减少字符交换 (作用有点类似于共享内存)
用途: video/sound/framebuffer/capture

六、unlocker_ioctl
long hello_ioctl (struct file *filp, unsigned int cmd, unsigned long arg)
用于对设备进行设置


fd 为文件描述符;
命令字cmd 指定对设备进行怎样的操作;命令字必须用宏定义;

例如实现点灯操作:
#define LED_ON  _IO('k' , 1)
#define LED_OFF  _IO('k' , 2)
ioctl (fd , LED_ON)

在驱动函数中,用switch判断命令

点击(此处)折叠或打开

  1. long hello_ioctl (struct file *filp, unsigned int cmd, unsigned long arg)
  2. {
  3.       int ret = 0;

  4.       switch (cmd) {
  5.     
  6.       case HELLO_ONE:
  7.         printk (KERN_INFO "HELLO_ONE called\n");
  8.             break;

  9.       case HELLO_TWO:
  10.         printk (KERN_INFO "HELLO_TWO called\n");
  11.         break;

  12.       default:
int capable (int  capability) 可以用来检查调用进程的权限,例如只能有管理员才能执行此命令 HELLO_TWO:

点击(此处)折叠或打开

  1. long hello_ioctl (struct file *filp, unsigned int cmd, unsigned long arg)
  2. {
  3.       int ret = 0;

  4.       switch (cmd) {
  5.     
  6.       case HELLO_ONE:
  7.         printk (KERN_INFO "HELLO_ONE called\n");
  8.             break;

  9.       case HELLO_TWO:
  10.         if(!capable(CAP_SYS_ADMIN))
  11.         return -EPERM;
  12.         printk (KERN_INFO "HELLO_TWO called\n");
  13.         break;

  14.       default:























阅读(969) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~