700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > linux3.0字符设备驱动 linux字符设备驱动的 ioctl 幻数

linux3.0字符设备驱动 linux字符设备驱动的 ioctl 幻数

时间:2024-03-17 16:48:10

相关推荐

linux3.0字符设备驱动 linux字符设备驱动的 ioctl 幻数

在Linux字符设备驱动入门(一)中,我们实现了字符设备的简单读写字符功能,接下来我们要在这个基础上加入ioctl功能。首先,我们先来看看3.0内核下../include/linux/fs.h中file_operations结构体的定义:

struct file_operations {

struct module *owner;

loff_t (*llseek) (struct file *, loff_t, int);

ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);

ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);

ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);

ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);

int (*readdir) (struct file *, void *, filldir_t);

unsigned int (*poll) (struct file *, struct poll_table_struct *);

long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);

long (*compat_ioctl) (struct file *, unsigned int, unsigned long);

int (*mmap) (struct file *, struct vm_area_struct *);

int (*open) (struct inode *, struct file *);

int (*flush) (struct file *, fl_owner_t id);

int (*release) (struct inode *, struct file *);

int (*fsync) (struct file *, int datasync);

int (*aio_fsync) (struct kiocb *, int datasync);

int (*fasync) (int, struct file *, int);

int (*lock) (struct file *, int, struct file_lock *);

ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);

unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);

int (*check_flags)(int);

int (*flock) (struct file *, int, struct file_lock *);

ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);

ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);

int (*setlease)(struct file *, long, struct file_lock **);

long (*fallocate)(struct file *file, int mode, loff_t offset,

loff_t len);

};

红色字体已经标出在kernel 3.0中已经完全删除了struct file_operations 中的ioctl 函数指针,剩下unlocked_ioctl和compat_ioctl,取而代之的是unlocked_ioctl,主要改进就是不再需要上大内核锁 (调用之前不再先调用lock_kernel()然后再unlock_kernel())。

所以,在hellow.c中,我们在file_operations中加入成员函数hello_ioctl(红色字体部分):

/* file operations for hello device */

static struct file_operations hello_ops = {

.owner = THIS_MODULE,

.unlocked_ioctl = hello_ioctl,

.open = hello_open,

.read = hello_read,

.write = hello_write,

.release = hello_release,

};

hello_ioctl()的定义如下:

static int hello_ioctl( struct file *file,

unsigned int cmd, unsigned long arg)

{ int temp = 0;

switch(cmd)

{

case HELLO_CMD1:

{

temp = 1;

if(copy_to_user( (int *)arg, &temp, sizeof(int))) return -EFAULT;

break;

}

case HELLO_CMD2:

{

temp = 2;

if(copy_to_user( (int *)arg, &temp, sizeof(int))) return -EFAULT;

break;

}

}

printk( KERN_NOTICE"ioctl CMD%d done!\n",temp);

return 0;

}

这里强调一下cmd的定义:

#define HELLO_MAGIC 'k'

#define HELLO_CMD1 _IO(HELLO_MAGIC,0x1a)

#define HELLO_CMD2 _IO(HELLO_MAGIC,0x1b)

其中'k'为幻数,要按照Linux内核的约定方法为驱动程序选择ioctl编号,应该首先看看include/asm/ioctl.h和Documentation/ioctl-number.txt这两个文件,下面是ioctl.h的部分内容,也是比较重要的:

_IO(type, nr)

用于构造无参数的命令编号;

_IOR(type, nr, datatype)

用于构造从驱动程序中读取数据的命令编号;

_IOW(type, nr, datatype)

用于写入数据的命令;

_IOWR(type, nr, datatype)

用于双向传输。注意千万不能重复定义。

注意对幻数的编号千万不能重复定义,如ioctl-number.txt已经说明‘k'的编号已经被占用的范围为:

'k' 00-0F linux/spi/spidev.h conflict!

'k' 00-05 video/kyro.h conflict!

所以我们在这里分别编号为0x1a和0x1b,到这里,我们已经完成了对ioctl功能的编写,接下来就是在测试程序中利用系统调用来测试它。

=============================================================

ioctl测试程序

=============================================================

#include

#include

#include

#include

#include

#include

#include

#include

#define HELLO_MAGIC 'k' //当然我们也可以定义一个相应的头文件,把ioctl的cmd放进里面,然后再include进 来

#define HELLO_CMD1 _IO(HELLO_MAGIC,0x1a)

#define HELLO_CMD2 _IO(HELLO_MAGIC,0x1b)

int main(void)

{

int ioctl_rdata;

int fd, ret;

fd = open ( "/dev/hellow" , O_RDWR);

if ( fd == -1 )

{

perror("open");

exit(0);

}

ret = ioctl( fd, HELLO_CMD2,&ioctl_rdata);

if ( ret == -1)

{

perror("ioctl");

exit(0);

}

printf("ioctl_rdata= %d \n",ioctl_rdata);

close(fd);

return 0;

}

=============================================================

运行结果

=============================================================

root@Ubuntu:~/share/hellow# insmod hellow.ko

root@Ubuntu:~/share/hellow# mknod /dev/hellow c 251 0

root@Ubuntu:~/share/hellow# ./a.out

ioctl_rdata= 2

root@Ubuntu:~/share/hellow# dmesg | tail

[ 2431.126532] hello init. major:251, minor:0

[ 2453.326022] Hello device open!

[ 2453.326047] ioctl CMD2 done! [ 2453.326487] Hello device close!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。