小技巧:
查找~/100ask_imx6ull-sdk/Linux-4.9.88/drivers/char内容
grep "name" -nrw
驱动程序包括:
1、构造结构体
2、注册|销毁 chrdev
3、入口函数
4、出口函数
/**
* 第一个驱动程序
*/
#include <linux/mm.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/mman.h>
#include <linux/random.h>
#include <linux/init.h>
#include <linux/raw.h>
#include <linux/tty.h>
#include <linux/capability.h>
#include <linux/ptrace.h>
#include <linux/device.h>
#include <linux/highmem.h>
#include <linux/backing-dev.h>
#include <linux/shmem_fs.h>
#include <linux/splice.h>
#include <linux/pfn.h>
#include <linux/export.h>
#include <linux/io.h>
#include <linux/uio.h>
#include <linux/module.h>
#include <linux/uaccess.h>
static int major;
static int hello_open(struct inode * node, struct file * file)
{
printk("%s %s %d", __FILE__, __FUNCTION__, __LINE__);
return 0;
}
static ssize_t hello_read(struct file * file, char __user *buf, size_t size, loff_t *offset)
{
printk("%s %s %d", __FILE__, __FUNCTION__, __LINE__);
return size;
}
static ssize_t hello_write(struct file * file, const char __user *buf, size_t size, loff_t *offset)
{
printk("%s %s %d", __FILE__, __FUNCTION__, __LINE__);
return size;
}
static int hello_release(struct inode * node, struct file * file)
{
printk("%s %s %d", __FILE__, __FUNCTION__, __LINE__);
return 0;
}
// 1.构造结构体
static const struct file_operations hello_drv = {
.owner = THIS_MODULE,
.read = hello_read,
.write = hello_write,
.open = hello_open,
.release = hello_release
};
// 2.注册chrdev 3.入口函数
static int hello_init(void)
{
major = register_chrdev(0, "100ask.net", &hello_drv);
return 0;
}
// 3.出口函数
static void hello_exit(void)
{
unregister_chrdev(major, "100ask.net");
};
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
首先要make,在执行baer make生成索引,就可以进行点击跳转
编写测试程序
/**
测试程序
写:./hello_drv_test /dev/xxx 100ask
读:./hello_drv_test /dev/xxx
<> 表示可以省略
[] 表示不可以省略
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{
int fd;
int len;
char buf[100];
if (argc < 2)
{
printf("Usage: \n");
printf("%s <dev> [string]", argv[0]);
return -1;
}
fd = open(argv[1], O_RDWR);
if (fd < 0)
{
printf("打开文件失败\n");
return -1;
}
if (argc == 3)
{
len = write(fd, argv[2], strlen(argv[2]) + 1);
}
else {
{
len = read(fd, buf, len);
buf[99] = '\0';
printf("read str: %s\n", buf);
}
}
close(fd);
return 0;
}
驱动程序和测试程序都进行交叉编译,驱动程序->.ko 测试程序生成可执行程序,移植到开发板
打开内核的打印信息,有些板子默认打开了
echo "7 4 1 7" > /proc/sys/kernel/printk
查看内核打印消息权限
cat /proc/sys/kernel/printk
装载驱动程序
insmod hello_drv.ko
查看驱动设备 lsmod
卸载驱动程序 rmmod hello_drv
查看主设备号
cat /proc/devices
创建设备节点
/dev/xyz: 名称 c: 字符设备 245: 主设备号 0: 从设备号
mknod /dev/xyz c 245 0
删除设备
rm -rf /dev/xyz
执行命名查看挂载nod节点
ls /dev/xyz
执行测试程序
写操作:./hello_drv_test /dev/xyz 100ask.net
读操作:./hello_drv_test /dev/xyz
结果:
如果通过ssh连接ip终端,需要进行一下操作,查看内核打印信息 dmesg dmesg -c 清楚内核打印信息