Linux驱动程序开发的经验总结

3 篇文章 0 订阅
2 篇文章 0 订阅

在尝试编写一些驱动模块时,其中就是遇到一些编译错误之类的,一种错误有很多种原因,总结下我遇到的一些问题,供你们参考:

1.编写一个内核程序spinlock.c:

#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/spinlock.h>

MODULE_LICENSE("GPL");

#define MAJOR_NUM 224

static ssize_t simplespin_read(struct file *, char *, size_t, loff_t*);
static ssize_t simplespin_write(struct file *, const char *, size_t, loff_t*);
static int simplespin_open(struct inode *inode, struct file *filp);
static int simplespin_release(struct inode *inode, struct file *filp);

struct file_operations simplespin_fops =
{
	.read=simplespin_read, 
	.write=simplespin_write, 
	.open=simplespin_open,
	.release=simplespin_release,
};

static int simplespin_var = 0;
static int simplespin_count = 0;
static spinlock_t spin;

static int simplespin_open(struct inode *inode, struct file *filp)
{
	/*获得自选锁*/
	spin_lock(&spin);
	
	/*临界资源访问*/
	if (simplespin_count)
	{
		spin_unlock(&spin);
		return - EBUSY;
	}
	simplespin_count++;
	
	/*释放自选锁*/
	spin_unlock(&spin);
	return 0;
}

static int simplespin_release(struct inode *inode, struct file *filp)
{
	simplespin_count--;
	return 0;
}

static ssize_t simplespin_read(struct file *filp, char *buf, size_t len, loff_t*off)
{
	return 0;
}

static ssize_t simplespin_write(struct file *filp, const char *buf, size_t len,loff_t *off)
{
	return 0;
}

static int __init simplespin_init(void)
{
	int ret;
	spin_lock_init(&spin);
	/*注册设备驱动*/
	ret = register_chrdev(MAJOR_NUM, "chardev", &simplespin_fops);
	if (ret)
	{
		printk("chardev register failure\n");
	}
	else
	{
		printk("chardev register success\n");
	}
	return ret;
}

static void __exit simplespin_exit(void)
{
	/*注销设备驱动*/
	unregister_chrdev(MAJOR_NUM, "chardev");
}

module_init(simplespin_init);
module_exit(simplespin_exit); 

2.写一个test.c进行测试:
#include<sys/types.h>
#include<unistd.h>
#include<fcntl.h>
#include<linux/rtc.h>
#include<linux/ioctl.h>
#include<stdio.h>
#include<stdlib.h>

void main()
{
	int fd;
	fd=open("/dev/jrb",O_RDWR);/*By read and write method open /dev/fgj*/
	if(fd==-1)
	{
		perror("error open\n");
		exit(-1);
	}
	printf("open /dev/jrb successfully\n");
	
	while(1);
	close(fd);
}

3.编写Makefile:
ifeq ($(KERNELRELEASE),)
ARCH=x86
PWD:= $(shell pwd)
CROSS_COMPILE=x86_64-linux-gnu-
CC=$(CROSS_COMPILE)gcc
#CROSS_COMPILE=arm-linux-gnueabi-
KERNELDIR=/usr/src/linux-headers-4.13.0-36-generic


lkm.ko:    spinlock.c
	$(MAKE) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERNELDIR) M=$(PWD) modules

else

obj-m += spinlock.o

endif

test: test.c  
	arm-linux-gnueabi-gcc $< -o $@  -g  
  
clean:
	rm -rf *.o *.ko *.mod.c .*.cmd *.markers *.order *.symvers .tmp_versions test

主要时Makefile里面的一些参数比较重要,直接关系到你是否能够编译成功的关键:

  • KERNELRELEASE:是在内核源码的顶层Makefile中定义的一个变量,在第一次读取执行此Makefile时,KERNELRELEASE没有被定义,所以make将读取执行else之后的内容,
  • ARCH:如果我们用本机内核编译的话,就应配置本机的cpu架构,inter处理器就是x86,如果是开发板那就是arm,如何看是什么archtechture呢?
robin@robin:~$ uname -a
Linux robin 4.13.0-36-generic #40~16.04.1-Ubuntu SMP Fri Feb 16 23:25:58 UTC 2018 x86_64 x86_64
 x86_64 GNU/Linux

uname -a之后就知道我们的处理器时x86/64位处理器,使用的内核版本是4.13.0-36-generic,一般我们的内核版本在/usr/src/下面:

robin@robin:~$ cd /usr/src/linux-
linux-headers-4.13.0-36/         linux-headers-4.15.0-42/         linux-headers-4.8.0-58-
generic/  linux-source-4.8.0/              
linux-headers-4.13.0-36-generic/ linux-headers-4.8.0-58/          linux-source-4.15.0/ 
  • CROSS_COMPILE:就表示我们使用的本机交叉编译工具链,如何看本机工具链是什么?从刚才的uname -a其实我们已经看出来了,使用的是x86。但是具体的编译工具是什么呢?还是进入刚才我们的那个/usr/路径下面,看一下本机有哪些交叉编译工具链?
robin@robin:~$ cd /usr/
arm-linux-androideabi/ arm-linux-gnueabihf/   games/                 lib/                   local/                 
sbin/                  src/                   arm-linux-gnueabi/     bin/                   include/               
lib32/                 locale/                share/                 x86_64-linux-gnu/     
 

从上面可以看出本机用到的交叉编译工具链有x86_64-linux-gnu-gcc,arm-linux-gnueabih-gcc,arm-linux-androideabi-gcc,arm-linux-gnueabi-gcc,我们之前使用的uname -a已经告诉我们本机的cpu型号和内核版本,因此我们就需要配置为x86_64-linux-gnu-,后面记得加一个-,不能跟gcc哦。

  • KERNELDIR:表示本机运行的内核位置,一般在/usr/src/下面先要用uname -r确定一下正在使用的内核的版本,然后在进行选择。

4.常见编译报错:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -C /usr/src/linux-headers-4.13.0-36-generic M=/home/robin/workspace/project/Linux_driver_2nd/samples/3synchronous/3-1spinlock modules
make[1]: Entering directory '/usr/src/linux-headers-4.13.0-36-generic'
  CC [M]  /home/robin/workspace/project/Linux_driver_2nd/samples/3synchronous/3-1spinlock/spinlock.o
In file included from ./include/asm-generic/int-ll64.h:10:0,
                 from ./arch/arm/include/uapi/asm/types.h:4,
                 from ./include/uapi/linux/types.h:4,
                 from ./include/linux/types.h:5,
                 from ./include/linux/list.h:4,
                 from ./include/linux/module.h:9,
                 from /home/robin/workspace/project/Linux_driver_2nd/samples/3synchronous/3-1spinlock/spinlock.c:2:
./include/uapi/asm-generic/int-ll64.h:11:29: fatal error: asm/bitsperlong.h: 没有那个文件或目录
compilation terminated.
scripts/Makefile.build:315: recipe for target '/home/robin/workspace/project/Linux_driver_2nd/samples/3synchronous/3-1spinlock/spinlock.o' failed
make[2]: *** [/home/robin/workspace/project/Linux_driver_2nd/samples/3synchronous/3-1spinlock/spinlock.o] Error 1
Makefile:1550: recipe for target '_module_/home/robin/workspace/project/Linux_driver_2nd/samples/3synchronous/3-1spinlock' failed
make[1]: *** [_module_/home/robin/workspace/project/Linux_driver_2nd/samples/3synchronous/3-1spinlock] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-4.13.0-36-generic'
Makefile:10: recipe for target 'lkm.ko' failed
make: *** [lkm.ko] Error 2

这个错误就是ARCH配置不正确导致的,按照上面的方法重新配置。

make ARCH=x86 CROSS_COMPILE=arm-linux-gnueabi- -C /usr/src/linux-headers-4.13.0-36-generic M=/home/robin/workspace/project/Linux_driver_2nd/samples/3synchronous/3-1spinlock modules
make[1]: Entering directory '/usr/src/linux-headers-4.13.0-36-generic'
arch/x86/Makefile:153: CONFIG_X86_X32 enabled but no binutils support
  CC [M]  /home/robin/workspace/project/Linux_driver_2nd/samples/3synchronous/3-1spinlock/spinlock.o
arm-linux-gnueabi-gcc: error: unrecognized command line option ‘-mno-sse’
arm-linux-gnueabi-gcc: error: unrecognized command line option ‘-mno-mmx’
arm-linux-gnueabi-gcc: error: unrecognized command line option ‘-mno-sse2’
arm-linux-gnueabi-gcc: error: unrecognized command line option ‘-mno-3dnow’
arm-linux-gnueabi-gcc: error: unrecognized command line option ‘-m64’
arm-linux-gnueabi-gcc: error: unrecognized command line option ‘-mno-red-zone’
arm-linux-gnueabi-gcc: error: unrecognized command line option ‘-mcmodel=kernel’
scripts/Makefile.build:315: recipe for target '/home/robin/workspace/project/Linux_driver_2nd/samples/3synchronous/3-1spinlock/spinlock.o' failed
make[2]: *** [/home/robin/workspace/project/Linux_driver_2nd/samples/3synchronous/3-1spinlock/spinlock.o] Error 1
Makefile:1550: recipe for target '_module_/home/robin/workspace/project/Linux_driver_2nd/samples/3synchronous/3-1spinlock' failed
make[1]: *** [_module_/home/robin/workspace/project/Linux_driver_2nd/samples/3synchronous/3-1spinlock] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-4.13.0-36-generic'
Makefile:11: recipe for target 'lkm.ko' failed
make: *** [lkm.ko] Error 2

这类错误表示ARCHCROSS_COMPILE不一致导致,两者应该都为我们本地Linux正在运行的架构和交叉编译工具链。所以应当仔细检查。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值