在尝试编写一些驱动模块时,其中就是遇到一些编译错误之类的,一种错误有很多种原因,总结下我遇到的一些问题,供你们参考:
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
这类错误表示ARCH
和CROSS_COMPILE
不一致导致,两者应该都为我们本地Linux正在运行的架构和交叉编译工具链。所以应当仔细检查。