编译字符设备驱动程序时,遇到如下错误:
[lgw@localhost 4-4]$ make
make -C /lib/modules/3.5.0-2.fc17.i686.PAE/build M=/home/lgw/shareArm/4-4 modules
make[1]: Entering directory `/usr/src/kernels/3.5.0-2.fc17.i686.PAE'
CC [M] /home/lgw/shareArm/4-4/Dev_frame0.o
/home/lgw/shareArm/4-4/Dev_frame0.c:40:3: error: unknown field ‘ioctl’ specified in initializer
/home/lgw/shareArm/4-4/Dev_frame0.c:40:3: warning: initialization from incompatible pointer type [enabled by default]
/home/lgw/shareArm/4-4/Dev_frame0.c:40:3: warning: (near initialization for ‘device_fops.write’) [enabled by default]
make[2]: *** [/home/lgw/shareArm/4-4/Dev_frame0.o] Error 1
make[1]: *** [_module_/home/lgw/shareArm/4-4] Error 2
make[1]: Leaving directory `/usr/src/kernels/3.5.0-2.fc17.i686.PAE'
make: *** [all] Error 2
源程序Dev_frame0.c:
#include <linux/module.h> //模块所需的大量符号和函数定义
#include <linux/fs.h> //文件系统相关的函数和头文件
#include <linux/cdev.h> //cdev结构的头文件
#define DEVICE_NAME "Dev_frame0" //可供”cat /proc/devices”命令查看,可与模块名同名也可以异名
int DEVICE_MAJOR = 50; //指定主设备号
/*-----------------------------------------------*/
int device_open(struct inode *inode, struct file *filp)
{
printk("user open device.\n");
return 0;
}
/*-----------------------------------------------*/
ssize_t device_write(struct file *filp,const char *buffer, size_t count, loff_t *f_pos)
{
printk("user write data to driver.\n");
return count;
}
/*-----------------------------------------------*/
ssize_t device_read(struct file *filp, char *buffer, size_t count, loff_t *f_pos)
{
printk("user read data from driver.\n");
return count; }
/*-----------------------------------------------*/
int device_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
printk("user ioctl runing.\n");
return cmd;
}
/*-----------------------------------------------*/
int device_release(struct inode *inode, struct file *filp)
{
printk("device release.\n");
return 0;
}
/*---- device_fops 结构定义文件操作函数体之后----- ----*/
struct file_operations device_fops = {
.owner= THIS_MODULE,
.read= device_read,
.ioctl= device_ioctl,
.open= device_open,
.write= device_write,
.release= device_release, //可写成device_colse
}; /*-----------------------------------------------*/
int device_init(void) {
int ret;
ret=register_chrdev( DEVICE_MAJOR,DEVICE_NAME,&device_fops );//字符驱动程序申请注册
if(ret<0){
printk("register chrdev failure!\n");//字符驱动程序注册失败
return ret;
}
else{
printk("register chrdev ok!\n");
}
return 0;
}
void device_exit(void) {
unregister_chrdev(DEVICE_MAJOR,DEVICE_NAME);//字符驱动程序申请注销
printk("unregister chrdev ok!\n");
}
module_init(device_init);
module_exit(device_exit);
我的ARM板上的linux系统是2.6.32.2,我的PC linux 是3.5.0-2.fc17.i686.PAE
在网上查到:
从2.6.36开始,file_operations结构发生了重大变化。(但基本的思想还是不变的)
取消了 原先的
int (*ioctl)(struct inode*, struct file*, unsigned int, unsigned long);
添加来新的成员long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);原来的ioctl 但是返回值变为long
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);内核空间64位,用户空间32位
于是我去查看了一下linux/fs.h 文件:(红色是上面说到的ioctl,绿色为我的驱动程序中用到的成员)
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 *, loff_t, loff_t, 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);
};
相应的地方更改为:
long device_ioctl(struct file *file, unsigned int cmd, unsigned long arg) //减少了inode的参数
{
…………
}
struct file_operations device_fops = {
…………
.unlocked_ioctl=device_ioctl,
…………
};