error: passing argument 4 of ‘proc_create’ from incompatible pointer type [-Werror=incompatible-poin

这篇博客讲述了作者在进行实验时遇到的一个Linux内核编程问题,即调用proc_create函数时出现'passing argument 4 of ‘proc_create’ from incompatible pointer type'的警告。作者发现这是由于实验代码过旧,不适用于较新的Linux内核版本。解决方案是更新tasklist.c中相关函数的定义。提供了解决问题的代码片段以及完整的tasklist.c代码和Makefile。文章还附带了参考资料链接。

error: passing argument 4 of ‘proc_create’ from incompatible pointer type [-Werror=incompatible-pointer-types]

今天又在下午做实验(坐牢)期间遇到了折磨人的bug,写完了编译出现一个warning:error: passing argument 4 of ‘proc_create’ from incompatible pointer type [-Werror=incompatible-pointer-types]
在找遍了中文网站都没找到答案后终于受不了了才选择英文网站寻找答案。
error的提示意思是参数指针类型不匹配(pointer incompatible )。本来觉得不匹配也就是一个warning没关系,不过后来还是想找到为什么。。。问题的关键就是老师给出的实验代码太老了,没法在大概linux-2.6.xx后使用了,因此出现了报错。正确答案如下:
把tasklist.c文件第78行左右的函数static struct proc_ops my_proc及其内容替换为如下代码即可:

static struct seq_operations my_seq_fops = {//序列文件记录操作函数集合
        .start  = my_seq_start,
        .next   = my_seq_next,
        .stop   = my_seq_stop,
        .show   = my_seq_show
};

顺便贴一下tasklist.c的完整代码,有需要的自取:

//-------------------------------------------------------------------
//	tasklist.c: 本内核文件创建一个proc伪文件,'/proc/tasklist'
//	通过如下命令可以显示系统中所有进程的部分信息
//	注意:Mkefile文件必须正确放置在当前目录下。
//  编译命令: make 
//  内核模块添加:$sudo insmod tasklist.ko
//  添加内核模块后读取并信息tasklist内核信息: $ cat /proc/tasklist
//  内核模块删除:$sudo rmmod tasklist
//	NOTE: Written and tested with Linux kernel version 3.13.0 and.3.2.0
// 用户也可以自己完成相关的读写程序,就像课后练习1要求的。我们尤其鼓励同学自己写程序代替cat程序。
//  strace函数可用于追踪系统调用,命令格式如下所示:
//  $ strace cat /proc/tasklist
//-------------------------------------------------------------------

#include <linux/module.h>	// for init_module() 
#include <linux/proc_fs.h>	// for create_proc_info_entry() 
#include <linux/sched.h>	// for init_task
#include <linux/seq_file.h>	// for sequence files
#include <linux/slab.h>       // for kzalloc, kfree  

char modname[] = "tasklist";
struct task_struct  *task;
int  taskcounts=0;			// 'global' so value will be retained

static void * my_seq_start(struct seq_file *m, loff_t *pos)
{
   ///printk(KERN_INFO"Invoke start\n");   //可以输出调试信息
   if ( *pos == 0 )  // 表示遍历开始
   {
	   task = &init_task;	//遍历开始的记录地址
	   return &task;   //返回一个非零值表示开始遍历
  }
  else //遍历过程中
  { 
  	if (task == &init_task ) 	//重新回到初始地址,退出
  		return NULL;
  	return (void*)pos	;//否则返回一个非零值
  }  
}
static int my_seq_show(struct seq_file *m, void *v)
{//获取进程的相关信息
  //printk(KERN_INFO"Invoke show\n");					
  seq_printf( m,  "#%-3d ", taskcounts++ );  
  seq_printf( m,  "%5d ", task->pid );
  seq_printf( m,  "%lu ", task->state );
  seq_printf( m,  "%-15s ", task->comm );
  seq_puts( m, "\n" );	  				  
  return 0; 
}

static void * my_seq_next(struct seq_file *m, void *v, loff_t *pos)
{
  //printk(KERN_INFO"Invoke next\n");  
  (*pos)++;    
  task= next_task(task);  //指向下一个进程
  return NULL;

}
static void my_seq_stop(struct seq_file *m, void *v)
{
	//printk(KERN_INFO"Invoke stop\n");		
	// do nothing        
}

static struct seq_operations my_seq_fops = {//序列文件记录操作函数集合
        .start  = my_seq_start,
        .next   = my_seq_next,
        .stop   = my_seq_stop,
        .show   = my_seq_show
};

static int my_open(struct inode *inode, struct file *file)  
{  
    return seq_open(file, &my_seq_fops); //打开序列文件并关联my_seq_fops
}  


static struct proc_ops my_proc={
    .proc_open = my_open,
    .proc_release = single_release,
    .proc_read = seq_read,
    .proc_lseek = seq_lseek,
};

int __init my_init( void )
{
	struct proc_dir_entry* my_proc_entry;
	printk( "<1>\nInstalling \'%s\' module\n", modname );
	my_proc_entry = proc_create(modname, 0x644, NULL, &my_proc);//生成proc文件
	if (NULL == my_proc_entry)
	{
	    return -ENOMEM;
	}
	return	0;  //SUCCESS
}

void __exit my_exit( void )
{
	remove_proc_entry( modname, NULL );//删除proc文件
	printk( "<1>Removing \'%s\' module\n", modname );	
}

module_init(my_init);
module_exit(my_exit);
MODULE_LICENSE("GPL"); 

Makefile代码如下:

obj-m := tasklist.o

KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD:=$(shell pwd)
all:
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules              
clean:
	rm -rf *.o *.ko *.mod.* *.symvers *.order

然后就可以继续快乐的编译啦。

相关参考网站:
点我
还有我

CC [M] /data/wifi8_branch_ui/Iplatform/openwrt/build_dir/target-arm-openwrt-linux-uclibc-bn800v1/kaccess_control/access_control.o /data/wifi8_branch_ui/Iplatform/openwrt/build_dir/target-arm-openwrt-linux-uclibc-bn800v1/kaccess_control/access_control.c: In function 'access_control_procfile_init': /data/wifi8_branch_ui/Iplatform/openwrt/build_dir/target-arm-openwrt-linux-uclibc-bn800v1/kaccess_control/access_control.c:169:87: error: passing argument 4 of 'proc_create' from incompatible pointer type [-Werror=incompatible-pointer-types] 169 | ac_proc_refuse_list = proc_create(AC_PROC_REFUSE_LIST, AC_PROC_PERM, ac_proc_dir, &ac_refuse_list_ops); | ^~~~~~~~~~~~~~~~~~~ | | | struct file_operations * In file included from /data/wifi8_branch_ui/Iplatform/openwrt/build_dir/target-arm-openwrt-linux-uclibc-bn800v1/kaccess_control/access_control.h:17, from /data/wifi8_branch_ui/Iplatform/openwrt/build_dir/target-arm-openwrt-linux-uclibc-bn800v1/kaccess_control/access_control.c:1: ./include/linux/proc_fs.h:110:122: note: expected 'const struct proc_ops *' but argument is of type 'struct file_operations *' 110 | truct proc_dir_entry *proc_create(const char *name, umode_t mode, struct proc_dir_entry *parent, const struct proc_ops *proc_ops); | ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~ /data/wifi8_branch_ui/Iplatform/openwrt/build_dir/target-arm-openwrt-linux-uclibc-bn800v1/kaccess_control/access_control.c:187:91: error: passing argument 4 of 'proc_create' from incompatible pointer type [-Werror=incompatible-pointer-types] 187 | ac_proc_filter_device = proc_create(AC_PROC_FILTER_DEVICE, AC_PROC_PERM, ac_proc_dir, &ac_filter_device_ops); | ^~~~~~~~~~~~~~~~~~~~~ | | | struct file_operations * ./include/linux/proc_fs.h:110:122: note: expected 'const struct proc_ops *' but argument is of type 'struct file_operations *' 110 | truct proc_dir_entry *proc_create(const char *name, umode_t mode, struct proc_dir_entry *parent, const struct proc_ops *proc_ops); | ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~ /data/wifi8_branch_ui/Iplatform/openwrt/build_dir/target-arm-openwrt-linux-uclibc-bn800v1/kaccess_control/access_control.c:205:85: error: passing argument 4 of 'proc_create' from incompatible pointer type [-Werror=incompatible-pointer-types] 205 | ac_proc_white_list = proc_create(AC_PROC_WHITE_LIST, AC_PROC_PERM, ac_proc_dir, &ac_white_list_ops); | ^~~~~~~~~~~~~~~~~~ | | | struct file_operations * ./include/linux/proc_fs.h:110:122: note: expected 'const struct proc_ops *' but argument is of type 'struct file_operations *' 110 | truct proc_dir_entry *proc_create(const char *name, umode_t mode, struct proc_dir_entry *parent, const struct proc_ops *proc_ops); | ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~ /data/wifi8_branch_ui/Iplatform/openwrt/build_dir/target-arm-openwrt-linux-uclibc-bn800v1/kaccess_control/access_control.c: In function 'access_control_hook': /data/wifi8_branch_ui/Iplatform/openwrt/build_dir/target-arm-openwrt-linux-uclibc-bn800v1/kaccess_control/access_control.c:258:32: error: the comparison will always evaluate as 'false' for the address of 'name' will never be NULL [-Werror=address] 258 | if (in == NULL || in->name == NULL || skb == NULL) { | ^~ In file included from ./include/net/sock.h:46, from ./include/linux/tcp.h:20, from /data/wifi8_branch_ui/Iplatform/openwrt/build_dir/target-arm-openwrt-linux-uclibc-bn800v1/kaccess_control/access_control.h:6: ./include/linux/netdevice.h:2321:33: note: 'name' declared here 2321 | char name[IFNAMSIZ]; | ^~~~ cc1: all warnings being treated as errors make[6]: *** [scripts/Makefile.build:287: /data/wifi8_branch_ui/Iplatform/openwrt/build_dir/target-arm-openwrt-linux-uclibc-bn800v1/kaccess_control/access_control.o] Error 1 make[5]: *** [Makefile:1978: /data/wifi8_branch_ui/Iplatform/openwrt/build_dir/target-arm-openwrt-linux-uclibc-bn800v1/kaccess_control] Error 2 make[4]: *** [Makefile:59: /data/wifi8_branch_ui/Iplatform/openwrt/build_dir/linux-model_brcm_bcm490x//.built] Error 2 make[4]: Leaving directory '/data/wifi8_branch_ui/Iplatform/packages/private/kaccess_control' make[3]: *** [package/Makefile:134: package/feeds/iplatform/kaccess_control/compile] Error 2 make[3]: Leaving directory '/data/wifi8_branch_ui/Iplatform/openwrt' make[2]: *** [package/Makefile:129: /data/wifi8_branch_ui/Iplatform/openwrt/staging_dir/target-arm-openwrt-linux-uclibc-bn800v1/stamp/.package_compile] Error 2 make[2]: Leaving directory '/data/wifi8_branch_ui/Iplatform/openwrt' make[1]: *** [/data/wifi8_branch_ui/Iplatform/openwrt/include/toplevel.mk:186: world] Error 2 make[1]: Leaving directory '/data/wifi8_branch_ui/Iplatform/openwrt' make: *** [Makefile:237: iplatform_world] Error 2
最新发布
12-11
### 问题分析 编译错误 `error: passing argument 4 of 'proc_create_data' from incompatible pointer type` 表示在调用函数 `proc_create_data` 时,第四个参数传入了一个与预期类型不兼容的指针。这类问题通常发生在指针类型不匹配、函数原型声明与实际使用不一致或结构体定义不完整的情况下。 Linux 内核开发中常见的 `proc_create_data` 函数原型如下: ```c struct proc_dir_entry *proc_create_data(const char *name, umode_t mode, struct proc_dir_entry *parent, const struct file_operations *proc_fops, void *data); ``` 其中第四个参数应为 `const struct file_operations *proc_fops`,若传递的是其他类型的指针(如 `struct file_operations *` 或者其他无关结构体指针),则会触发此错误[^1]。 --- ### 常见原因及解决方法 #### 1. 指针类型不匹配 确保传入的第四个参数是指向 `const struct file_operations` 的指针。若当前变量不是 `const` 类型,可以通过显式转换或修改变量声明来修正。 **修复方式:** ```c static const struct file_operations my_proc_fops = { .owner = THIS_MODULE, .open = my_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; // 正确调用 entry = proc_create_data("my_entry", 0, NULL, &my_proc_fops, NULL); ``` 若原函数操作结构未加 `const` 修饰,应补充以匹配函数要求: ```c static struct file_operations my_proc_fops = { // ... }; ``` 改为: ```c static const struct file_operations my_proc_fops = { // ... }; ``` #### 2. 结构体定义不完整 如果 `struct file_operations` 在某些文件中未被完全定义(例如缺少头文件包含),也可能导致编译器无法识别其结构,从而引发指针类型不匹配的问题。 **修复方式:** 确保在使用 `struct file_operations` 的所有源文件中都包含了 `<linux/fs.h>` 或相关头文件: ```c #include <linux/fs.h> #include <linux/proc_fs.h> ``` #### 3. 使用了错误的函数版本 在部分内核版本中,`proc_create_data` 和 `proc_create` 的区别在于是否支持 `void *data` 参数。若误用了 `proc_create` 的函数指针而传递了 `data` 参数,也会导致类型不匹配。 **修复方式:** 确认调用的函数名与参数列表一致: - 若需传递私有数据,请使用 `proc_create_data` 并确保前四个参数正确。 - 若无需传递数据,可使用 `proc_create`: ```c entry = proc_create("my_entry", 0, NULL, &my_proc_fops); ``` #### 4. 编译器警告升级为错误 若启用了 `-Werror=incompatible-pointer-types` 编译选项,则原本是警告的类型不匹配会被视为错误。应优先修复根本问题而非禁用警告。 --- ### 示例代码 以下是一个完整的示例,展示如何正确定义并调用 `proc_create_data`: ```c #include <linux/module.h> #include <linux/kernel.h> #include <linux/proc_fs.h> #include <linux/uaccess.h> #include <linux/fs.h> static int my_open(struct inode *inode, struct file *file) { return single_open(file, my_show, PDE_DATA(inode)); } static const struct file_operations my_proc_fops = { .owner = THIS_MODULE, .open = my_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; static int __init my_module_init(void) { struct proc_dir_entry *entry; entry = proc_create_data("my_entry", 0, NULL, &my_proc_fops, NULL); if (!entry) { pr_err("Failed to create /proc/my_entry\n"); return -ENOMEM; } return 0; } static void __exit my_module_exit(void) { remove_proc_entry("my_entry", NULL); } module_init(my_module_init); module_exit(my_module_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("A simple example of proc_create_data usage"); ``` --- ### 相关建议 - 使用 `const` 修饰符可以避免因常量性不一致导致的指针类型冲突。 - 在模块初始化和清理函数中加入错误处理逻辑,有助于快速定位资源分配失败等问题。 - 定期检查头文件依赖关系,确保结构体定义一致性。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值