在尝试编写一些驱动模块时,其中就是遇到一些编译错误之类的,一种错误有很多种原因,总结下我遇到的一些问题,供你们参考:
1.编写一个内核程序spinlock.c:
#include
#include
#include
#include
#include
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_toff)
{
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
#include
#include
#include
#include
#include
#include
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:= (shellpwd)CROSSCOMPILE=x8664−linux−gnu−CC=(shell pwd)
CROSS_COMPILE=x86_64-linux-gnu-
CC=(shellpwd)CROSSCOMPILE=x8664−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=(MAKE) ARCH=(MAKE)ARCH=(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C (KERNELDIR)M=(KERNELDIR) M=(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在尝试编写一些驱动模块时,其中就是遇到一些编译错误之类的,一种错误有很多种原因,总结下我遇到的一些问题,供你们参考:
1.编写一个内核程序spinlock.c:
#include
#include
#include
#include
#include
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
#include
#include
#include
#include
#include
#include
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正在运行的架构和交叉编译工具链。所以应当仔细检查。