字符设备注册流程

字符设备注册流程

创建设备节点

使用mknod,格式:
mknod 名称 类型 主设备号 次设备号
eg:
mknod /dev/test c 247 0

编写模块代码(.ko文件)

模块代码可生成.ko代码,优点是insmod方便,临时的模块,适合咱们测试学习

#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
 
MODULE_LICENSE("GPL");
MODULE_AUTHOR("monkey");

static ssize_t monkeyRead(struct file *, char *, size_t, loff_t*);
static ssize_t monkeyWrite(struct file *, const char *, size_t, loff_t*);
 
#define DEV_NAME "monkey_cdev"
 
static int char_major = 0;
static int monkeyData = 0;
 
struct file_operations monkeycdev_fops =
{
  .read = monkeyRead,
  .write = monkeyWrite
};
 
 

static int __init monkeycdev_init(void)
{
  int ret;
 
  ret = register_chrdev(char_major, DEV_NAME, &monkeycdev_fops); 

  if (ret<0) 
  {
    printk(KERN_INFO "Fail!\n");
  } 
  else
  {
    printk(KERN_INFO "Success!\n");
    char_major = ret;
    printk(KERN_INFO "Major = %d\n", char_major);
  }
  return ret;
}
 
/* 模块卸载函数  执行rmmod命令时候执行这个函数 */
static void __exit monkeycdev_exit(void)
{
  unregister_chrdev(char_major, DEV_NAME); 		// 注销设备驱动
  return;
}
 
/* 设备驱动读函数 */
static ssize_t monkeyRead(struct file *filp, char *buf, size_t len, loff_t *off)
{
  printk(KERN_INFO "read ok\n");
  return ;
}
 
/* 设备驱动写函数 */
static ssize_t monkeyWrite(struct file *filp, const char *buf, size_t len, loff_t *off)
{
  printk(KERN_INFO "Write ok");
  return ;
}

module_init(monkeycdev_init);
module_exit(monkeycdev_exit);

编写makefile

make后生成的.ko文件就是咱们的模块代码了.首先需要知道:
obj-m = *.o
obj-y = *.o
上面两者的区别在于,前者才会生成ko文件,后者只是代码编译进内核,并不生成ko文件。

生成KO文件,分两种情况:单个.c文件和多个.c文件
1.单个.c文件
kernel配置文件中定义
CONFIG_RUNYEE_CAMVIB=m
注意上面的m,表示作为一个模块进行编译,最后在MAKEFILE中需要用到的编译开关。
然后再相应的源码目录中的MAKEFILE中添加如下语句:
obj-$(CONFIG_RUNYEE_CAMVIB) := 字符设备注册例程.o
上面的一行的作用就是编译字符设备注册例程.c的源文件,同时会生成相应的字符设备注册例程.ko文件,和编译生成的字符设备注册例程.o在同一目录,最后就是insmod动作了:
insmod /system/lib/modules/字符设备注册例程.ko

2.多个.c文件生成ko文件
kernel配置文件中定义
CONFIG_TOUCHSCREEN_FOCALTECH=m
注意上面的m,表示作为一个模块进行编译,最后在MAKEFILE中需要用到的编译开关。
然后再相应的源码目录中的MAKEFILE中添加如下语句:
obj-$(CONFIG_TOUCHSCREEN_FOCALTECH) += focaltech_ts.o
字符设备注册例程_ts-objs := 字符设备注册例程.o
字符设备注册例程_ts-objs += 字符设备注册例程1.o
字符设备注册例程_ts-objs += 字符设备注册例程2.o
上面的意思就是编译生成ko文件需要三个.c文件【字符设备注册例程.c 字符设备注册例程1.c 字符设备注册例程2.c】,最后
生成名为字符设备注册例程_ts的ko文件,注意ko文件名一定不能为字符设备注册例程。那么在obj-m和lpc-objs中都含有字符设备注册例程.o,
对make来讲会产生循环和混淆,因此也不能这样书写
最后就是insmod动作了:
insmod /system/lib/modules/字符设备注册例程_ts.ko

然后上代码:

obj-m	+= 字符设备注册例程.o
 
#ubuntu的内核源码树,如果要编译在ubuntu中安装的模块就打开这2个
KERN_VER = $(shell uname -r)
KERN_DIR = /lib/modules/$(KERN_VER)/build	
 
all:
	make -C $(KERN_DIR) M=`pwd` modules 
 
 
.PHONY: clean	
clean:
	make -C $(KERN_DIR) M=`pwd` modules clean

现在我们可以透过设备节点的方式去cat,也可以通过例程去查看咱们的驱动是否成功
现在提供个例程:

/* GlobalCharTest.c */
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#define DEV_NAME "/dev/monkey_cdev"
 
int main()
{
  int fd, num;
 
  /* 打开设备文件 */
  fd = open(DEV_NAME, O_RDWR, S_IRUSR | S_IWUSR);
  if (fd<0) {
    printf("Open Deivec Fail!\n");
    return -1;
  }
 
  /* 读取当前设备数值 */
  read(fd, &num, sizeof(int));
  printf("The monkey_cdev is %d\n", num);
 
  printf("Please input a number written to monkey_cdev: ");
  scanf("%d", &num);
 
  /* 写入新的数值 */
  write(fd, &num, sizeof(int));
 
  /* 重新读取设备数值 */
  read(fd, &num, sizeof(int));
  printf("The monkey_cdev is %d\n", num);
 
  close(fd);
  return 0;
}

gcc这个例程,执行生成的可执行文件,就能够查看到相关信息了
是不是恍然大悟了
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值