加载ko模块时报错unknown symbol in module, or unknown parameter

创建两个ko,  A.ko  B.ko

A.ko中的函数要被B.ko所引用;

在A.ko中使用   EXPORT_SYMBOL_GPL(func);

在B.ko中使用 func 编译和加载会报错;

方法如下:

1、将 A.ko编译进内核, 任意目录的makefile中添加 obj -y += A.ko

obj -m += B.ko 如果A,B不在一个目录会报错

方法一:

拷贝A目录中的Module.symvers 到B目录中,之后编译B.ko =========》 测试通过

方法二:

在B的makefile中添加如下语句:

KBUILD_EXTRA_SYMBOLS += /home/chengjian/code/bsp_rru/testOM/BSP_RRU/modules/test_proc/Module.symvers
export KBUILD_EXTRA_SYMBOLS

示例A:

环境: Zynq UltraScale+     zcu102      2018.3


#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/fcntl.h>
#include <linux/init.h>
#include <linux/mutex.h>
#include <linux/pagemap.h>
#include <linux/uaccess.h>


#define MYLOG_BUF_LEN 1024
/* 创建环形缓冲区
	
*/
static char tmp_buf[MYLOG_BUF_LEN];

static char mylogBuf[MYLOG_BUF_LEN];
static int mylog_r = 0;
static int mylog_w = 0;
static int mylog_r_tmp = 0;
DECLARE_WAIT_QUEUE_HEAD(mylog_wait);



/* 读取和写入的位置一致表示 当前缓冲区是空的 */
int isEmpty_mylogbuf(void)
{
	return (mylog_r == mylog_w);
}

/* 假设当前r=0       如果w是1023 */
int isFull(void)
{
	if ((mylog_w == (MYLOG_BUF_LEN - 1)) && (mylog_r == 0))
	{
		return 0; //没有满
	}else if (mylog_w == MYLOG_BUF_LEN  &&  (mylog_r == 0))
	{
		return 1;
	}else
		return (mylog_r == (mylog_w+1)%MYLOG_BUF_LEN);
}

static void mylog_putc(char c)
{
	if (isFull())
	{
		mylog_r = (mylog_r + 1)%MYLOG_BUF_LEN;
		 if((mylog_r_tmp + 1)% MYLOG_BUF_LEN == mylog_r)
            mylog_r_tmp= mylog_r;
	}
	mylogBuf[mylog_w] = c;
	mylog_w = (mylog_w+1)%MYLOG_BUF_LEN;
	wake_up_interruptible(&mylog_wait);
}
/*
*从循环队列中读字符
*输入:*p 单位:1byte
*输出:1表示成功
*/
static int mylog_getc(char *p)
{
	if (isEmpty_mylogbuf())
	{
		return 0;
	}
	*p = mylogBuf[mylog_r_tmp];
	mylog_r_tmp   = (mylog_r_tmp + 1) % MYLOG_BUF_LEN;
	return 1;
}

/*
*调用myprintk,和printf用法相同
*/
int myprintk(const char *fmt, ...)
{
   va_list args;
   int i;
   int j;
    va_start(args, fmt);
    i= vsnprintf(tmp_buf, INT_MAX, fmt, args);
    va_end(args);
   
   for (j = 0; j < i; j++)
        mylog_putc(tmp_buf[j]);
       
   return i;
}

static ssize_t mymsg_read(struct file *file, char __user *buf,
			 size_t count, loff_t *ppos)
{
	int error ;
	char c;
	int i=0;
	printk("mymsg_read \n");
	if ((file->f_flags & O_NONBLOCK) && !isEmpty_mylogbuf())
		return -EAGAIN;
	error = wait_event_interruptible(mylog_wait, !isEmpty_mylogbuf()); //当不是非空的 时候等待;
	for (i=0; i<count; i++)
	{	mylog_getc(&c);
		error = __put_user(c, buf);
		buf++;
	}
	if (!error)
		error = i;
	return error;
}

static const struct file_operations proc_mymsg_operations = {
	.read		= mymsg_read,
	
};

static int mymsg_init(void)
{
	printk("mymsg_init\n");
	proc_create("mymsg", S_IRUSR, NULL, &proc_mymsg_operations);
	return 0;
}

static void mymsg_exit(void)
{
	remove_proc_entry("mymsg", NULL);
}

/*声名到内核空间*/
EXPORT_SYMBOL_GPL(myprintk);
module_init(mymsg_init);
module_exit(mymsg_exit);
MODULE_LICENSE("GPL");




obj-m += mymsg.o

B.ko

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
extern int myprintk(const char *fmt, ...);

int first_drv_open (struct inode * node, struct file * fp)
{
	myprintk("first_drv_open cj \n");
	return 0;
}

ssize_t first_drv_write (struct file *f, const char __user *buf, size_t cnt , loff_t * seek)
{

	myprintk("first_drv_write cj \n");

	return 0;
}

static struct file_operations first_drv_fops = {
    .owner =  THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量*/
    .open  =  first_drv_open,   
    .write =  first_drv_write,     
};
int major;

static int first_drv_init(void)
{
    myprintk("first_drv_init\n");
    major= register_chrdev(0, "first_drv", &first_drv_fops); // 注册, 告诉内核

   return 0;
}

static void first_drv_exit(void)
{
    unregister_chrdev(major,"first_drv"); // 卸载
}

module_init(first_drv_init);
module_exit(first_drv_exit);
MODULE_LICENSE("GPL");

obj-m += testfirst.o
KERN_DIR=/home/.../....../kernel/linux-xlnx-xilinx-v2018.3/
KBUILD_EXTRA_SYMBOLS += /home/.../modules/test_proc/Module.symvers
export KBUILD_EXTRA_SYMBOLS
all:
	make -C $(KERN_DIR) M=`pwd` modules
	
clean:
	rm -f *.o
	rm -f *.symvers
	rm -f *.order
	rm -f *.ko
	rm -f *.mod.*
	rm -f *.cmd
	rm -rf .testfirst
	rm -f .testfirst.ko.cmd
	rm -f .testfirst.mod.o.cmd
	rm -f .testfirst.o.cmd

加载驱动后结果:

dmesg 查看:

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值