第一个驱动程序

121 阅读2分钟

小技巧:

查找~/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 image.png

装载驱动程序

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
结果: image.png image.png

如果通过ssh连接ip终端,需要进行一下操作,查看内核打印信息 dmesg dmesg -c 清楚内核打印信息