方法一:
开发环境:VM+Ubuntu
编译环境:linux3.4(全志官方BSP)
交叉编译工具:arm-linux-gcc 4.4.3
1.编写helloworld设备源码
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/fs.h>
#include<linux/io.h>
#include<linux/cdev.h>
#include<linux/miscdevice.h>
#include<linux/init.h>
#include<linux/device.h>
#include<linux/string.h>
#include<linux/types.h>
#include<linux/moduleparam.h>
#include<linux/errno.h>
#define DEVICE_NAME "helloworld"
#define DEVICE_MAJOR 237
int device_open(struct inode *inode,struct file *file)
{
printk("<0>the helloword device open.. \n");
return 0;
}
static ssize_t device_read(struct file *file,char __user *buf,size_t count,loff_t *f_pos)
{
printk("<0>the helloword device reading.. \n");
return 1;
}
static ssize_t device_write(struct file *file,const char __user *buf,size_t count,loff_t *f_pos)
{
printk("<0>the helloword device writing.. \n");
return 1;
}
int device_release(struct inode *inode,struct file *file)
{
printk("<0>the helloword device release \n");
return 0;
}
struct file_operations helloworld_ops=
{
.owner = THIS_MODULE,
.open = device_open,
.read = device_read,
.write = device_write,
.release = device_release,
};
//init
static int __init Helloworld_init(void)
{
int ret;
printk("<0>module init \n");
ret = register_chrdev(DEVICE_MAJOR,DEVICE_NAME,&helloworld_ops);
if(ret<0)
{
printk("<0>%s can't initialized! \n",DEVICE_NAME);
return ret;
}
printk("<0>%s initialized! \n",DEVICE_NAME);
return 0;
}
//exit
static void __exit Helloworld_exit(void)
{
printk("<0>module exit.. \n");
unregister_chrdev(DEVICE_MAJOR,DEVICE_NAME);
printk("<0>exited \n");
}
module_init(Helloworld_init);
module_exit(Helloworld_exit);
MODULE_AUTHOR("xxx");
MODULE_DESCRIPTION("Nanopi NEO Helloworld Driver");
MODULE_LICENSE("GPL");
将hellowrold.c复制到lichee/linux-3.4/drivers/char/文件夹下,并在Makefile末尾添加:
obj-m += helloworld.o
obj-m表示编译成模块,而相对应的obj-y表示编译入内核,$(变量)的值可以是y或m。
然后,退回到/lichee目录,重新编译内核
./build.sh -p sun8iw7p1 -b nanopi-h3 -m kernel
在lichee/linux-3.4/drivers/char/目录下会生成.ko文件
将.ko文件拷贝到Nanopi m1任意目录
2.在nanopi m1端编写应用程序app.c
模拟使用该设备的情况:
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
int main()
{
char buf[2] = {0,1}; //Âú×ã¸ñʽ
size_t n = 1;
int fd;
fd = open("/dev/helloworld",O_RDWR); //É豸Ãû£¬´ò¿ª·½Ê½£¬È¨ÏÞ
if(fd < 0)
{
printf("Can't open the helloworld device.\n");
return -1;
}
else
printf("Open the helloworld device successfully.\n");
write(fd,buf,n);
read(fd,buf,n);
close(fd);
printf("app over\n");
}
3.使用内核模块:
挂载内核模块:
insmod helloworld.ko
查看内核模块列表:
lsmod
查看是否有设备节点:
ls /dev/hello*
创建设备节点:
mknod /dev/helloworld c 237 0
c代表该设备是字符设备,237是设备的主设备号,0是次设备号。成功后,/dev目录下生成helloworld设备文件。
编译应用程序:
gcc -o app app.c
执行应用程序:
./app
显示模块打开成功
卸载内核模块:
rmmod helloworld
删除设备文件:
rm /dev/helloworld
完成内核模块的加载设备,构建设备节点,运行设备,卸载设备,删除设备文件的功能。