linux字符驱动头文件路径,嵌入式Linux字符设备驱动——4注册字符类设备

096daa46391541c56dac3183c15070e5.png

嵌入式Linux字符设备驱动开发流程——以LED为例

前言

留空

头文件

#include     //字符设备描述

#include //内存分配头文件

内存申请kmalloc

文件(路径):未知

static __always_inline void *kmalloc(size_t size, gfp_t flags)

{

if (__builtin_constant_p(size)) {

if (size > KMALLOC_MAX_CACHE_SIZE)

return kmalloc_large(size, flags);

#ifndef CONFIG_SLOB

if (!(flags & GFP_DMA)) {

int index = kmalloc_index(size);

if (!index)

return ZERO_SIZE_PTR;

return kmem_cache_alloc_trace(kmalloc_caches[index],

flags, size);

}

#endif

}

}

字符设备结构体

所属文件名:cdev.h

struct cdev {

struct kobject kobj;

struct module *owner;

const struct file_operations *ops;

struct list_head list;

dev_t dev;

unsigned int count;

};

字符设备初始化

所属文件名:未知

/**

* 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;

}

字符类设备注册

所属文件名:未知

/**

* cdev_add() - add a char device to the system

* @p: the cdev structure for the device

* @dev: the first device number for which this device is responsible

* @count: the number of consecutive minor numbers corresponding to this

*         device

*

* cdev_add() adds the device represented by @p to the system, making it

* live immediately.  A negative error code is returned on failure.

*/

int cdev_add(struct cdev *p, dev_t dev, unsigned count)

{

p->dev = dev;

p->count = count;

return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p);

}

字符设备卸载

所属文件名:未知

/**

* cdev_del() - remove a cdev from the system

* @p: the cdev structure to be removed

*

* cdev_del() removes @p from the system, possibly freeing the structure

* itself.

*/

void cdev_del(struct cdev *p)

{

cdev_unmap(p->dev, p->count);

kobject_put(&p->kobj);

}

内存释放

所属文件名:未知

void kfree(const void *x)

{

struct page *page;

void *object = (void *)x;

trace_kfree(_RET_IP_, x);

if (unlikely(ZERO_OR_NULL_PTR(x)))

return;

page = virt_to_head_page(x);

if (unlikely(!PageSlab(page))) {

BUG_ON(!PageCompound(page));

kmemleak_free(x);

put_page(page);

return;

}

slab_free(page->slab, page, object, _RET_IP_);

}

程序

#include            //模块头文件

#include            //内核头文件

#include              //内核初始化

#include                //字符设备函数

#include              //字符设备描述

#include            //系列设备号处理宏

#include              //内存分配头文件

#define DEVICE_NAME     "leds"      //字符设备名称

#define DEVICE_MINOR_NUM    2       //字符设备数量

#define DEV_MAJOR   0               //主设备号

#define DEV_MINOR   0               //次设备号,0为自动分配

#define REGDEV_SIZE 3000

static int leds_major = DEV_MAJOR;  //主设备号变量

static int leds_minor = DEV_MINOR;  //次设备号变量

static dev_t leds_dev;              //设备号

struct cdev *leds_cdev;             //字符设备结构体变量

struct file_operations leds_fops = {

.owner = THIS_MODULE,

};

static __init int leds_init(void)

{

int ret = 0;

int i;

ret = alloc_chrdev_region(&leds_dev, leds_minor, DEVICE_MINOR_NUM, DEVICE_NAME);

if(ret < 0){

printk(KERN_EMERG "register_chrdev_region req %d is failed!\n", DEV_MAJOR);

return ret;

}

leds_major = MAJOR(leds_dev);   //主设备号

leds_minor = MINOR(leds_dev);   //次设备号

printk(KERN_EMERG "leds chrdev major=%d, minor=%d\n", leds_major, leds_minor);

leds_cdev = kmalloc(DEVICE_MINOR_NUM * sizeof(struct cdev), GFP_KERNEL);

if(leds_cdev == NULL)

{

printk(KERN_EMERG "kmalloc failed");

unregister_chrdev_region(leds_dev, DEVICE_MINOR_NUM);

return -ENOMEM;

}

//memset(leds_cdev, 0, DEVICE_MINOR_NUM * sizeof(struct dev_cdev));

for(i=0; i

cdev_init(&leds_cdev[i], &leds_fops);

leds_cdev[i].owner = THIS_MODULE;

leds_cdev[i].ops = &leds_fops;

ret = cdev_add(&leds_cdev[i], MKDEV(leds_major, leds_minor+1), 1);

if(ret < 0){

printk(KERN_EMERG "cdev_add %d failed!\n", i);

}

else{

printk(KERN_EMERG "cdev_add %d success!\n", i);

}

}

return ret;

}

static __exit void leds_exit(void)

{

int i;

for(i=0; i

cdev_del(&leds_cdev[i]);                            //注销设备

}

kfree(leds_cdev);                                       //释放内存

unregister_chrdev_region(leds_dev, DEVICE_MINOR_NUM);   //注销设备号

printk(KERN_EMERG "leds chrdev exit \n");

}

module_init(leds_init);

module_exit(leds_exit);

MODULE_LICENSE("GPL");

结束语

以上则为嵌入式Linux注册字符类设备的相关内容。

~谢谢支持~

aeff66d04e04331ff01582002fbe34ba.png

如果文章对您有帮助,欢迎移至上方按钮打赏博主;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值