struct file_operations

ssize_t (*read) (struct file *file, char __user *   buf, size_t  count, loff_t   *pos);
        功能:从内核空间读取数据到用户空间
        参数:
                    file:    存放open打开文件时生成的file指针
                    buf:    从用户空间的read传来,所以buf是用户空间的地址,buf指向的地址用来存放读取的数据
                    count:从用户空间的read传来,表示要读取的字节数
                    pos:    文件的偏移位置
        返回值:返回值已读取的字节数,出错返回一个负值

long (*unlocked_ioctl) (struct file *, unsigned int  cmd, unsigned long  arg);
        功能:驱动程序一般需要支持通过ioctl实现各种控制与参数设置
        参数:
                    file:         存放open打开文件时生成的file指针    
                     cmd:   存放用户空间传送过来的命令
                     arg:     存放用户空间传送过来的参数,如为整数,可直接使用。如为指针,驱动首先要检查指针的合法性
                                    使用 access_ok函数检查,检查通过后才可以使用
         返回值:与ioctl系统调用一样,成功返回0,失败返回错误码
        可通过 capable函数来确定调用进程是否有权执行操作

注:为了创建唯一的 ioctl命令号,每一个命令号被分为了4个字段,下面介绍的新符号都定义在 <linux/ioctl.h>中。

type:
        幻数。选择一个号码,并在整个驱动程序中使用这个号码。(记住先阅读ioctl-number.txt)
number:
        序列号。
direction :
        数据传送的方向,如果这个特殊的命令涉及数据传送。可能的值是  _IOC_NONE(没有数据传输)_IOC_READ_IOC_WRITE, 和 IOC_READ|_IOC_WRITE (双向传输数据)。 数据传送是从应用程序的角度来看的;也就是说,_IOC_READ 意思是从设备中读取设备, 因此设备必须写到用户空间. 注意这个成员是一个位掩码, 因此 _IOC_READ 和 _IOC_WRITE 可使用一个逻辑 AND 操作来抽取. 

size :
        所涉及的用户数据的大小。 这个成员的宽度是依赖体系的, 但是常常是 13 或者 14 位.。具体可通过宏 _IOC_SIZEBITS 找到针对特定体系结构的具体数值。系统不强制使用这个字段,内核不检查它 。  正确使用这个成员可帮助检测用户空间程序的错误,如果我们不改变相关数据项的大小,这个字段可以帮助我们实现实现向后兼容。如果你需要很大的数据传输,可以忽略这个字段。 

<linux/ioctl.h>头文件中包含的<asm/ioctl.h>中定义了一些构造命令编号的宏:
_IO(type,nr)                                构造没有参数的命令
 _IOR(type, nr, datatype)       用于构造从驱动程序中读取数据的命令
_IOW(type,nr,datatype)           用于构造向驱动程序写入数据的命令
_IOWR(type,nr,datatype)        用于双向传输
type:幻数 
nr:    序列号
datatype:数据类型 

unsigned int (*poll) (struct file *filp, poll_table *wait); 
    功能:是poll,epoll,select的后端实现。
    参数:
                fp:    存放open打开文件时生成的file指针
                wait:它由vfs层的 do_select函数传递给 poll。然后向其中加入等待队列,使用 poll_waitpoll_table结构体中添加一个等待队列 。
                     void poll_wait (struct file *, wait_queue_head_t  *, poll_table *); 
    返回值:返回一个用来描述操作是否可以立即无阻塞执行的位掩码

这几个标志在 <linux/poll.h>中定义:
POLLIN 
        如果设备可被不阻塞地读, 这个位必须设置. 
POLLRDNORM 
       如果“通常”的数据已经就绪,可以读取,就设置该位。一个可读设备需返回 ( POLLIN | POLLRDNORM ).
POLLRDBAND 
        这个位指示可以从设备中读取带外( out-of-band)数据, 当前只可以在 Linux 内核的DECnet 代码中使用,并且通常不用于设备驱动
POLLPRI 
        可以不阻塞地读取高优先级数据,设置该位会使 select 报告文件发生一个异常,因为 selct 把带外据作为一个异常情况. 
POLLHUP 
        当读这个设备的进程到达文件尾时, 驱动必须设置 POLLUP(挂起)位。依照select的功能描述,调用select的进程会被告知设备时可读的。
POLLERR 
        一个错误情况已在设备上发生. 当调用 poll, 就会报告设备可读可写, 因为读写都会无阻塞地返回一个错误码 
POLLOUT 
        如果设备可以无阻塞地写入,就在返回值中设置该位 
POLLWRNORM 
        这个位和 POLLOUT 有相同的含义,有时其实就是同一个数字。一个可写的设备需返回 ( POLLOUT | POLLWRNORM). 
POLLWRBAND 
        如同 POLLRDBAND , 这个位意思是带有零优先级的数据可写入设备. 只有 poll 的数据报实现使用这个位, 因为一个数据报看传送带外数据. 
         POLLRDBAND 和 POLLWRBAND 只在与套接字相关的文件描述符中才有意义。设备驱动通常用不到这两个标志

poll的一般模板:
 static unsigned int hello_poll(struct file *filp, poll_table *wait)
{
unsigned  int  mask = 0;
struct hello_device   *dev = filp->private_data;

poll_wait(filp, &dev->rq, wait);
poll_wait(filp, &dev->wq, wait);  

down(&dev->sem);
if (dev->len > 0)
{
mask |= POLLIN | POLLRDNORM; 
}
if (dev->len != 128)
{
mask |= POLLOUT | POLLWRNORM;
}
up(&dev->sem);

return mask;
}

注:对poll机制需要做的一些说明:
  •     首先需要明确poll_wait所做的操作就是把等待队列添加到poll_table 中,然后在vfs层的do_select中执行等待队列的操作。此时所有的描述符处在等待队列的状态中,直到其中一个描述符被唤醒。
  •     而唤醒等待队列的操作时机是在对select中所包含的任一描述符进行相应地读写操作或其他操作时,在相应操作的驱动中实现调用唤醒队列的内核函数,此时do_select才会被唤醒。如果在驱动函数中没有调用唤醒操作,则do_select不会被唤醒。
  •     do_select被唤醒后,对所有的文件描述符(注意,这里是对系统调用select中包含的所有文件描述符)执行其相应的驱动函数poll,然后在驱动函数中来判断其对应的设备是否已经就绪。
  •     驱动函数判断完后,返回一个用来描述操作是否可以立即无阻塞执行的位掩码,do_select根据各个驱动函数poll返回的掩码,来判断相应的设备是否可被无阻塞操作。如果可以则置位系统调用slect中参数相应的位。

int (*fasync) (int fd, struct file *fp, int mode);










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值