How to fix error: passing argument 4 of 'proc_create' from incompatible pointer type
How to fix error: passing argument 4 of 'proc_create' from incompatible pointer type
我正在尝试将东西加载到我的内核以了解如何添加东西!
我这里有两个文件!
下面是skynet.c:
#include <linux/module.h> // included for all kernel modules
#include <linux/kernel.h> // included for KERN_INFO
#include <linux/init.h> // included for __init and __exit macros
#include <linux/proc_fs.h> // file operations
#include <linux/seq_file.h> // seq_read, ...
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Dr. Dyson");
MODULE_DESCRIPTION("Global Information Grid");
static int skynet_show(struct seq_file *m, void *v);
static int skynet_open(struct inode *inode, struct file *file);
static const struct file_operations skynet_fops = {
.owner = THIS_MODULE,
.open = skynet_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int skynet_show(struct seq_file *m, void *v) {
here:
seq_printf(m, "Skynet location: 0x%lx\n", (unsigned long)&&here);
return 0;
}
static int skynet_open(struct inode *inode, struct file *file) {
return single_open(file, skynet_show, NULL);
}
static int __init skynet_init(void) {
proc_create("skynet", 0, NULL, &skynet_fops);
printk(KERN_INFO "Skynet in control\n");
return 0;
}
static void __exit skynet_cleanup(void) {
remove_proc_entry("skynet", NULL);
printk(KERN_INFO "I'll be back!\n");
}
module_init(skynet_init);
module_exit(skynet_cleanup);
下面是 Makefile:
obj-m += skynet.o
所有:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) 模块
清洁:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) 干净
但是当我在 make 中写入时,我在下面的终端中得到了这个错误:
make -C /lib/modules/5.8.0-29-generic/build M=/home/jonteyh/ID1200/Device/skynet modules
make[1]: Entering directory '/usr/src/linux-headers-5.8.0-29-generic'
CC [M] /home/jonteyh/ID1200/Device/skynet/skynet.o
/home/jonteyh/ID1200/Device/skynet/skynet.c: In function ‘skynet_init’:
/home/jonteyh/ID1200/Device/skynet/skynet.c:37:34: error: passing argument 4 of ‘proc_create’ from incompatible pointer type [-Werror=incompatible-pointer-types]
37 | proc_create("skynet", 0, NULL, &skynet_fops);
| ^~~~~~~~~~~~
| |
| const struct file_operations *
In file included from /home/jonteyh/ID1200/Device/skynet/skynet.c:5:
./include/linux/proc_fs.h:107:122: note: expected ‘const struct proc_ops *’ but argument is of type ‘const struct file_operations *’
107 | struct proc_dir_entry *proc_create(const char *name, umode_t mode, struct proc_dir_entry *parent, const struct proc_ops *proc_ops);
| ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~
cc1: some warnings being treated as errors
make[2]: *** [scripts/Makefile.build:290: /home/jonteyh/ID1200/Device/skynet/skynet.o] Error 1
make[1]: *** [Makefile:1780: /home/jonteyh/ID1200/Device/skynet] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-5.8.0-29-generic'
make: *** [Makefile:4: all] Error 2
我尝试将 file_operations 更改为 proc_ops 以下内容:
static const struct proc_ops skynet_fops = {
.owner = THIS_MODULE,
.open = skynet_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
但后来我遇到了其他错误,例如版本不存在。
我该如何解决这个不兼容的错误??
有两种解决方法。
第一个解决方案是将struct file_operations
替换为struct proc_ops
,用于内核版本5.6或更高版本:
#include <linux/version.h>
#include <linux/module.h> // included for all kernel modules
#include <linux/kernel.h> // included for KERN_INFO
#include <linux/init.h> // included for __init and __exit macros
#include <linux/proc_fs.h> // file operations
#include <linux/seq_file.h> // seq_read, ...
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Dr. Dyson");
MODULE_DESCRIPTION("Global Information Grid");
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0)
#define HAVE_PROC_OPS
#endif
static int skynet_show(struct seq_file *m, void *v);
static int skynet_open(struct inode *inode, struct file *file);
#ifdef HAVE_PROC_OPS
static const struct proc_ops skynet_ops = {
.proc_open = skynet_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
#else
static const struct file_operations skynet_ops = {
.owner = THIS_MODULE,
.open = skynet_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
#endif
static int skynet_show(struct seq_file *m, void *v) {
here:
seq_printf(m, "Skynet location: 0x%lx\n", (unsigned long)&&here);
return 0;
}
static int skynet_open(struct inode *inode, struct file *file) {
return single_open(file, skynet_show, NULL);
}
static int __init skynet_init(void) {
proc_create("skynet", 0, NULL, &skynet_ops);
printk(KERN_INFO "Skynet in control\n");
return 0;
}
static void __exit skynet_cleanup(void) {
remove_proc_entry("skynet", NULL);
printk(KERN_INFO "I'll be back!\n");
}
module_init(skynet_init);
module_exit(skynet_cleanup);
第二种解决方案是将内核版本 4.18 或更高版本的 proc_create
替换为 proc_create_single
,此时只需要一个基本的只读 proc 文件:
#include <linux/version.h>
#include <linux/module.h> // included for all kernel modules
#include <linux/kernel.h> // included for KERN_INFO
#include <linux/init.h> // included for __init and __exit macros
#include <linux/proc_fs.h> // file operations
#include <linux/seq_file.h> // seq_read, ...
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Dr. Dyson");
MODULE_DESCRIPTION("Global Information Grid");
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
#define HAVE_PROC_CREATE_SINGLE
#endif
static int skynet_show(struct seq_file *m, void *v) {
here:
seq_printf(m, "Skynet location: 0x%lx\n", (unsigned long)&&here);
return 0;
}
#ifndef HAVE_PROC_CREATE_SINGLE
static int skynet_open(struct inode *inode, struct file *file) {
return single_open(file, skynet_show, NULL);
}
static const struct file_operations skynet_fops = {
.owner = THIS_MODULE,
.open = skynet_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
#endif
static int __init skynet_init(void) {
#ifdef HAVE_PROC_CREATE_SINGLE
proc_create_single("skynet", 0, NULL, skynet_show);
#else
proc_create("skynet", 0, NULL, &skynet_fops);
#endif
printk(KERN_INFO "Skynet in control\n");
return 0;
}
static void __exit skynet_cleanup(void) {
remove_proc_entry("skynet", NULL);
printk(KERN_INFO "I'll be back!\n");
}
module_init(skynet_init);
module_exit(skynet_cleanup);
我正在尝试将东西加载到我的内核以了解如何添加东西!
我这里有两个文件!
下面是skynet.c:
#include <linux/module.h> // included for all kernel modules
#include <linux/kernel.h> // included for KERN_INFO
#include <linux/init.h> // included for __init and __exit macros
#include <linux/proc_fs.h> // file operations
#include <linux/seq_file.h> // seq_read, ...
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Dr. Dyson");
MODULE_DESCRIPTION("Global Information Grid");
static int skynet_show(struct seq_file *m, void *v);
static int skynet_open(struct inode *inode, struct file *file);
static const struct file_operations skynet_fops = {
.owner = THIS_MODULE,
.open = skynet_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int skynet_show(struct seq_file *m, void *v) {
here:
seq_printf(m, "Skynet location: 0x%lx\n", (unsigned long)&&here);
return 0;
}
static int skynet_open(struct inode *inode, struct file *file) {
return single_open(file, skynet_show, NULL);
}
static int __init skynet_init(void) {
proc_create("skynet", 0, NULL, &skynet_fops);
printk(KERN_INFO "Skynet in control\n");
return 0;
}
static void __exit skynet_cleanup(void) {
remove_proc_entry("skynet", NULL);
printk(KERN_INFO "I'll be back!\n");
}
module_init(skynet_init);
module_exit(skynet_cleanup);
下面是 Makefile:
obj-m += skynet.o
所有: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) 模块
清洁: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) 干净
但是当我在 make 中写入时,我在下面的终端中得到了这个错误:
make -C /lib/modules/5.8.0-29-generic/build M=/home/jonteyh/ID1200/Device/skynet modules
make[1]: Entering directory '/usr/src/linux-headers-5.8.0-29-generic'
CC [M] /home/jonteyh/ID1200/Device/skynet/skynet.o
/home/jonteyh/ID1200/Device/skynet/skynet.c: In function ‘skynet_init’:
/home/jonteyh/ID1200/Device/skynet/skynet.c:37:34: error: passing argument 4 of ‘proc_create’ from incompatible pointer type [-Werror=incompatible-pointer-types]
37 | proc_create("skynet", 0, NULL, &skynet_fops);
| ^~~~~~~~~~~~
| |
| const struct file_operations *
In file included from /home/jonteyh/ID1200/Device/skynet/skynet.c:5:
./include/linux/proc_fs.h:107:122: note: expected ‘const struct proc_ops *’ but argument is of type ‘const struct file_operations *’
107 | struct proc_dir_entry *proc_create(const char *name, umode_t mode, struct proc_dir_entry *parent, const struct proc_ops *proc_ops);
| ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~
cc1: some warnings being treated as errors
make[2]: *** [scripts/Makefile.build:290: /home/jonteyh/ID1200/Device/skynet/skynet.o] Error 1
make[1]: *** [Makefile:1780: /home/jonteyh/ID1200/Device/skynet] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-5.8.0-29-generic'
make: *** [Makefile:4: all] Error 2
我尝试将 file_operations 更改为 proc_ops 以下内容:
static const struct proc_ops skynet_fops = {
.owner = THIS_MODULE,
.open = skynet_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
但后来我遇到了其他错误,例如版本不存在。 我该如何解决这个不兼容的错误??
有两种解决方法。
第一个解决方案是将struct file_operations
替换为struct proc_ops
,用于内核版本5.6或更高版本:
#include <linux/version.h>
#include <linux/module.h> // included for all kernel modules
#include <linux/kernel.h> // included for KERN_INFO
#include <linux/init.h> // included for __init and __exit macros
#include <linux/proc_fs.h> // file operations
#include <linux/seq_file.h> // seq_read, ...
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Dr. Dyson");
MODULE_DESCRIPTION("Global Information Grid");
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0)
#define HAVE_PROC_OPS
#endif
static int skynet_show(struct seq_file *m, void *v);
static int skynet_open(struct inode *inode, struct file *file);
#ifdef HAVE_PROC_OPS
static const struct proc_ops skynet_ops = {
.proc_open = skynet_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
#else
static const struct file_operations skynet_ops = {
.owner = THIS_MODULE,
.open = skynet_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
#endif
static int skynet_show(struct seq_file *m, void *v) {
here:
seq_printf(m, "Skynet location: 0x%lx\n", (unsigned long)&&here);
return 0;
}
static int skynet_open(struct inode *inode, struct file *file) {
return single_open(file, skynet_show, NULL);
}
static int __init skynet_init(void) {
proc_create("skynet", 0, NULL, &skynet_ops);
printk(KERN_INFO "Skynet in control\n");
return 0;
}
static void __exit skynet_cleanup(void) {
remove_proc_entry("skynet", NULL);
printk(KERN_INFO "I'll be back!\n");
}
module_init(skynet_init);
module_exit(skynet_cleanup);
第二种解决方案是将内核版本 4.18 或更高版本的 proc_create
替换为 proc_create_single
,此时只需要一个基本的只读 proc 文件:
#include <linux/version.h>
#include <linux/module.h> // included for all kernel modules
#include <linux/kernel.h> // included for KERN_INFO
#include <linux/init.h> // included for __init and __exit macros
#include <linux/proc_fs.h> // file operations
#include <linux/seq_file.h> // seq_read, ...
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Dr. Dyson");
MODULE_DESCRIPTION("Global Information Grid");
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
#define HAVE_PROC_CREATE_SINGLE
#endif
static int skynet_show(struct seq_file *m, void *v) {
here:
seq_printf(m, "Skynet location: 0x%lx\n", (unsigned long)&&here);
return 0;
}
#ifndef HAVE_PROC_CREATE_SINGLE
static int skynet_open(struct inode *inode, struct file *file) {
return single_open(file, skynet_show, NULL);
}
static const struct file_operations skynet_fops = {
.owner = THIS_MODULE,
.open = skynet_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
#endif
static int __init skynet_init(void) {
#ifdef HAVE_PROC_CREATE_SINGLE
proc_create_single("skynet", 0, NULL, skynet_show);
#else
proc_create("skynet", 0, NULL, &skynet_fops);
#endif
printk(KERN_INFO "Skynet in control\n");
return 0;
}
static void __exit skynet_cleanup(void) {
remove_proc_entry("skynet", NULL);
printk(KERN_INFO "I'll be back!\n");
}
module_init(skynet_init);
module_exit(skynet_cleanup);