Linux驱动|cdev_init、cdev_alloc区别

发表于 3年以前  | 总阅读数:299 次

这两个函数是字符设备初始化相关的内核函数。

一、字符设备架构

下面我们以两个设备:LED、MPU6050为例来讲解字符设备的架构

由上图所示:

1、硬件

外设有MPU6050、LED两个设备,他们通过外设电路连接到SOC的对应的引脚上。程序要操作外设,就要通过设置soc中对应的SFR来与外设交互。

2、驱动层

  • 每一个字符设备都必须首先定义一个结构体变量struct cdev,并注册到内核中
  • 所有的该变量在内核中会通过链表进程管理,其中成员list用于将所有链表串接起来
  • 用于操作外设的功能函数全部被封装在struct file_operations中,包括read、write
  • 每一个字符设备都必须要有一个设备号,保存在成员dev中,
  • 主、次设备号只能被分配一次
  • 所有的字符设备号,都由数组chrdevs统一管理
  • chrdevs是一个指针数组,成员类型为**struct char_device_struct ***,下标与字符设备号有一定的对应关系,
  • **struct char_device_struct **中有成员:
unsigned int major;
struct cdev *cdev; 

major : 是主设备号 cdev : 指向该字符设备号对应的cdev结构体

3、应用层、VFS层

  • 用户如果想操作硬件,必须调用内核中的struct file_operations中的操作函数,
  • 那么如何才能找到该结构体呢?必须要依赖文件节点来查找,可以通过以下命令来创建
mknod  /dev/led c 250 0
 mknod 创建设备文件,可以使字符设备,也可以是块设备
 /dev/led 设备文件名
 c  字符设备
 250  主设备号
 0    次设备号

字符设备文件属性中最重要的属性就是字符设备号,该设备号和chedevs的下标有一定对应关系

  • 通过mknod创建的文件,VFS层会分配一个结构体变量来维护该文件,类型为struct inode
  • 每新建1个文件内核都会创建不同的结构体变量与之对应
  • 应用程序要操作某个字符设备,那么必须先通过系统调用open()来打开该字符设备
  • 该函数会返回一个唯一的整型文件描述符,同时内核中会分配结构体变量,类型为struct file,并与文件描述符一一对应,该结构体维护在struct task_struct中
  • 每次打开某个文件,都会分配不同的文件描述符,所以需要用不同的变量来保存文件描述符

二、字符设备创建的流程

了解了架构之后,那么我们来看一下内核中完整的创建字符设备的流程及对应的函数调用关系:

如下图所示,字符设备的创建主要包括以下三个步骤:

  1. 申请设备号
  2. 初始化cdev
  3. 注册cdev 调用的函数见右侧

下面是一个最简单的额字符设备创建的实例

/*  
 *一口Linux
 *2021.6.21
 *version: 1.0.0
*/

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/cdev.h>

static int major = 237;
static int minor = 0;
static dev_t devno;
static struct cdev cdev;
static int hello_open (struct inode *inode, struct file *filep)
{
 printk("hello_open()\n");
 return 0;
}
static struct file_operations hello_ops = 
{
 .open = hello_open,
};
static int hello_init(void)
{
 int result;
 int error; 
 printk("hello_init \n");
 devno = MKDEV(major,minor); 
 result = register_chrdev_region(devno, 1, "test");
 if(result<0)
 {
  printk("register_chrdev_region fail \n");
  return result;
 }
 cdev_init(&cdev,&hello_ops);
 error = cdev_add(&cdev,devno,1);
 if(error < 0)
 {
  printk("cdev_add fail \n");
  unregister_chrdev_region(devno,1);
  return error;
 }
 return 0;
}
static void hello_exit(void)
{
 printk("hello_exit \n");
 cdev_del(cdev);
 unregister_chrdev_region(devno,1);
 return;
}
module_init(hello_init);
module_exit(hello_exit);

该实例代码主要功能:

  1. 申请了字符设备号237
  2. 初始化cdev,并注册了cdev

应用程序如果要想使用,还必须创建字符设备节点

mknod /dev/test c 237 0

这样应用程序就可以通过设备节点/dev/test 调用到对应的内核操作函数.open = hello_open,

/*  
 *一口Linux
 *2021.6.21
 *version: 1.0.0
*/

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
main()
{
 int fd;
 fd = open("/dev/test",O_RDWR);
 if(fd<0)
 {
  perror("open fail \n");
  return;
 }
 printf("open ok \n ");
}

三、函数功能和定义

搞懂上面字符设备创建步骤之后,我们就可以来真正分析cdev_init、cdev_alloc这两个函数了

1. cdev_init()

原型
void cdev_init(struct cdev *cdev, const struct file_operations *fops)

功能
 用于初始化cdev结构体,并填充其成员ops
参数
   cdev:字符设备
   fops :驱动操作函数集合
返回值
  无

该函数实现如下:

/**
 * cdev_init() - initialize a cdev structure
 * @cdev: the structure to initialize
 * @fops: the file_operations for this device
 *
 * Initializes @cdev, remembering @fops, making it ready to add to the
 * system with cdev_add().
 */
void cdev_init(struct cdev *cdev, const struct file_operations *fops)
{
 memset(cdev, 0, sizeof *cdev);
 INIT_LIST_HEAD(&cdev->list);
 kobject_init(&cdev->kobj, &ktype_cdev_default);
 cdev->ops = fops;
}

2. cdev_alloc

原型
struct cdev *cdev_alloc(void)

功能
 用于分配cdev结构体,并添加到内核中
参数
返回值
  成功:返回分配的cdev结构体变量指针
  失败: 返回NULL

该函数实现如下:

/**
 * cdev_alloc() - allocate a cdev structure
 *
 * Allocates and returns a cdev structure, or NULL on failure.
 */
struct cdev *cdev_alloc(void)
{
 struct cdev *p = kzalloc(sizeof(struct cdev), GFP_KERNEL);
 if (p) {
  INIT_LIST_HEAD(&p->list);
  kobject_init(&p->kobj, &ktype_cdev_dynamic);
 }
 return p;
}

注意,该函数分配的cdev需要free掉 该函数没有初始化cdev->ops成员

四、cdev_alloc()的使用

该函数主要用于让用户省去操作cdev的操作,只需要提供**struct file_operations **变量就可以通过以下函数注册字符设备

static inline int register_chrdev(unsigned int major, const char *name,
      const struct file_operations *fops)
{
 return __register_chrdev(major, 0, 256, name, fops);
}

其中函数__register_chrdev()定义如下:


/**
 * __register_chrdev() - create and register a cdev occupying a range of minors
 * @major: major device number or 0 for dynamic allocation
 * @baseminor: first of the requested range of minor numbers
 * @count: the number of minor numbers required
 * @name: name of this range of devices
 * @fops: file operations associated with this devices
 *
 * If @major == 0 this functions will dynamically allocate a major and return
 * its number.
 *
 * If @major > 0 this function will attempt to reserve a device with the given
 * major number and will return zero on success.
 *
 * Returns a -ve errno on failure.
 *
 * The name of this device has nothing to do with the name of the device in
 * /dev. It only helps to keep track of the different owners of devices. If
 * your module name has only one type of devices it's ok to use e.g. the name
 * of the module here.
 */
int __register_chrdev(unsigned int major, unsigned int baseminor,
        unsigned int count, const char *name,
        const struct file_operations *fops)
{
 struct char_device_struct *cd;
 struct cdev *cdev;
 int err = -ENOMEM;

 cd = __register_chrdev_region(major, baseminor, count, name);
 if (IS_ERR(cd))
  return PTR_ERR(cd);

 cdev = cdev_alloc();
 if (!cdev)
  goto out2;

 cdev->owner = fops->owner;
 cdev->ops = fops;
 kobject_set_name(&cdev->kobj, "%s", name);

 err = cdev_add(cdev, MKDEV(cd->major, baseminor), count);
 if (err)
  goto out;

 cd->cdev = cdev;

 return major ? 0 : cd->major;
out:
 kobject_put(&cdev->kobj);
out2:
 kfree(__unregister_chrdev_region(cd->major, baseminor, count));
 return err;
}

可以看到该函数,复用了cdev_alloc()、cdev_add(),我们只需要提供以下3个参数即可:

unsigned int major  主设备号
const char *name    设备号名字
const struct file_operations *fops 驱动操作函数集合

五、结论

cdev_alloc()函数相当于

struct cdev cdev;
cdev_init($cdev,&hello_ops)

本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/wCgPWU9rbDsS9XznZudY7g

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:1年以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:1年以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:1年以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:1年以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:1年以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:1年以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:1年以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:1年以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:1年以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:1年以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:1年以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:1年以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:1年以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:1年以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:1年以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:1年以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:1年以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:1年以前  |  398次阅读  |  详细内容 »
 相关文章
Android插件化方案 5年以前  |  237231次阅读
vscode超好用的代码书签插件Bookmarks 2年以前  |  8065次阅读
 目录