应用的层的操作最终会调用驱动层的操作
应用层
|
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 函数 联系了起来。
代码实现如下:
-
static int hello_open (struct inode *inode, struct file *file)
-
{
-
printk (KERN_INFO "Hey! device opened\n");
-
return 0;
-
}
二、release:
open的逆操作,对应于应用层的close 函数。
用法同open
代码实现如下:
-
static int hello_release (struct inode *inode, struct file *file)
-
{
-
printk (KERN_INFO "Hmmm! device closed\n");
-
return 0;
-
}
三、read:
-
ssize_t hello_read (struct file *filp, char *buff, size_t count, loff_t *offp) //filp为定义的结构体指针,buff 为要读的首地址,count为读成功的字节数,第四个参数实现随机访问,一般不用
-
{
-
ssize_t result = 0;
-
-
if (count < 0) return -EINVAL;
-
if (count > 127) count = 127; //如果大于缓冲区的大小127,则读127个字节
-
-
if (copy_to_user (buff, data, count))
-
//返回值为没有copy成功的字节数,此函数有可能引起系统睡眠,不能用于中断。
-
{
-
result = -EFAULT; //此错误码返回给应用层下的errno,
-
}
-
else
-
{
-
printk (KERN_INFO "wrote %d bytes\n", count);
-
result = count;
-
}
-
-
return result;
-
}
四、write
write用法同read。
-
ssize_t hello_write (struct file *filp, const char *buf, size_t count, loff_t *f_pos)
-
{
-
ssize_t ret = 0;
-
-
//printk (KERN_INFO "Writing %d bytes\n", count);
-
if (count > 127) return -ENOMEM; //大于127返回给errno,内存不足
-
if (copy_from_user (data, buf, count)) //同样copy_fron_user 不能用于中断。
-
{
-
ret = -EFAULT;
-
}
-
else {
-
data[count] = '\0';
-
printk (KERN_INFO"Received: %s\n", data);
-
ret = count;
-
}
-
-
return ret;
-
}
五、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判断命令
-
long hello_ioctl (struct file *filp, unsigned int cmd, unsigned long arg)
-
{
-
int ret = 0;
-
-
switch (cmd) {
-
-
case HELLO_ONE:
-
printk (KERN_INFO "HELLO_ONE called\n");
-
break;
-
-
case HELLO_TWO:
-
printk (KERN_INFO "HELLO_TWO called\n");
-
break;
-
-
default:
int capable (int capability) 可以用来检查调用进程的权限,例如只能有管理员才能执行此命令 HELLO_TWO:
-
long hello_ioctl (struct file *filp, unsigned int cmd, unsigned long arg)
-
{
-
int ret = 0;
-
-
switch (cmd) {
-
-
case HELLO_ONE:
-
printk (KERN_INFO "HELLO_ONE called\n");
-
break;
-
-
case HELLO_TWO:
-
if(!capable(CAP_SYS_ADMIN))
-
return -EPERM;
-
printk (KERN_INFO "HELLO_TWO called\n");
-
break;
-
-
default:
阅读(1011) | 评论(0) | 转发(0) |