当前位置: 首页 > news >正文

怎么做转载小说网站/seo研究中心qq群

怎么做转载小说网站,seo研究中心qq群,网页生成器手机版,专业的深圳网站建设公司六、字符设备驱动 6.1、基本概念 Linux操作系统思想:一切皆文件 对设备的操作,也是将设备抽象成设备文件,应用层通过文件IO对设备文件进行操作,其最终结 果,是在操作设备。 Linux操作系统,将设备分成三…

六、字符设备驱动

6.1、基本概念

  • Linux操作系统思想:一切皆文件

    • 对设备的操作,也是将设备抽象成设备文件,应用层通过文件IO对设备文件进行操作,其最终结
      果,是在操作设备。

    • Linux操作系统,将设备分成三大类:

      • 字符设备: 除了网络设备和块设备,剩下的全部是字符设备
        • 特点:I/O传输过程中以字符为单位进行传输。用户对字符设备发出读/写请求时,实际的硬件读/写操作一般紧接着发生(同步发生、无缓存机制)
        • 块设备:存储设备
          • 特点:数据传输以(内存缓冲)为单位传输;用户对块设备读/写时,硬件上的读/写操作不会紧接着发生,即用户请求和硬件操作是异步的(异步、有缓存机制)
          • 网络设备: 网卡等
            • 特点:网络设备是一类特殊的设备,它不像字符设备或块设备那样通过对应的设备文件访问,也不能直接通过read或write进行数据请求,而是通过socket接口函数进行访问

6.2、字符设备驱动框架

  • 1、为驱动工程师提供管理驱动设备的统一架构
  • 2、为用户层提供统一的访问控制设备的接口

6.2.1、字符设备框架中的数据类型结构体

  1. 字符设备结构体

    在/include/linux/下的cdev.h中定义

struct cdev{struct kobject kobj;				//kobject对象struct module *owner;				//THIS_MODULEconst struct file_operations *ops;	//操作方法集struct list_head list;dev_t dev;							//设备号(U32 32bit无符号整型)unsigned int count;					//设备引用计数
};
  • dev_t类型的设备号:由主设备号(高12bit)和次设备号(低20bit)组成:

  • MKDEV(major,minor) 宏函数:由主设备号major和次设备号minor生成设备号

  • MAJOR(dev) 宏函数:从设备号中提取主设备号

  • MINOR(dev) 宏函数:从设备号中提取次设备号

    #define MINORBITS 20
    #define MINORMASK ((1U << MINORBITS) - 1)
    #define MKDEV(major,minor) (((major) << MINORBITS) | (minor))
    #define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS))
    #define MINOR(dev) ((unsigned int) ((dev) & MINORMASK))
    

    设备操作结构体

struct file_operations{struct module *owner;loff_t(*llseek)(struct file*,loff_t,int);ssize_t(*read)(struct file*,char __user*,size_t,loff_t*);ssize_t(*write)(struct file*,constchar __user*,size_t,loff_t*);unsignedint(*poll)(struct file*,struct poll_table_struct*);long(*unlocked_ioctl)(struct file*,unsigned int,unsigned long);int(*mmap)(struct file*,struct vm_area_struct*);int(*open)(struct inode*,struct file*);int(*release)(struct inode*,struct file*);int(*fasync)(int,struct file*,int);...
};

6.2.2、为结构体变量分配空间

使用时需要添加返回值判断语句,失败时返回空。

/***cdev_alloc()-allocate a cdev structure**Allocates and returns a cdev structure,or NULL on failure.*/struct cdev *cdev_alloc(void)	

6.2.3、初始化cdev结构体

/*** 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)

6.2.4、添加cdev到系统中,由内核统一管理

使用时需要添加返回值判断语句:错误时返回负值。

/*** 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.Anegative error code is returned on failure.*/int cdev_add(struct cdev *p, dev_t dev, unsigned count)

设备号是系统资源:使用设备号,需要向内核申请,不使用的时候,需要释放
申请设备号和释放设备号的方法由内核提供:

/**alloc_chrdev_region()		-register a rangeofchar device numbers*@dev:		output parameter for first assigned number*@baseminor:first of the requested range of minor numbers*@count:	the number of minor numbers required*@name:	the name of the associated device or driver**Allocates a range of char device numbers.The major number will be*chosen dynamically,and returned(along with the first minor number)*in @dev. Returns zero or a negative error code.*/
//特点:主设备号未定,需由系统分配时使用该函数,次设备号由baseminor和count共同指定
int alloc_chrdev_region(dev_t* dev, unsigned baseminor, unsigned count, const char *name)/***register_chrdev_region()-	register a range of device numbers*@from:	the first in the desired range of device numbers; must include the major number.*@count:the number of consecutive device numbers required*@name:the name of the device or driver.**Return value is zero on success,a negative error code on failure.*///特点:主次设备号已经确定(0~255之间),用来注册多个次设备号时可用此函数
int register_chrdev_region(dev_t from, unsigned count, const char *name)/*
*unregister_chrdev_region()	-return a range of device numbers
*@from:		the first in the range of numbers to unregister
*@count:	the number of device numbers to unregister
*
*This function will unregister a range of @count device numbers,
*starting with @from. The caller should normally be the one who
*allocated those numbers in the first place...
*/
void unregister_chrdev_region(dev_t from, unsigned count)

6.2.5、cdev_del

当不使用的时候,从内核中删除

/*
*cdev_del()	-remove a cdevfromthe 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);
}

6.3、编写字符设备驱动框架

#头文件static int __init demo_init(void)
{//0、申请设备号//1、分配cdev结构体//2、初始化cdev结构体//3、添加到内核中,由内核统一管理return0;
}static void __exit demo_exit(void)
{//1. cdev从内核中删除//2. 设备号资源释放
}module_init(demo_init);
module_exit(demo_exit);
MODULE_LICENSE("GPL");

6.4、设备文件

6.4.1、创建设备文件

通过shell命令——mknod创建设备文件:

mknod - make block or character special files
格式:mknod NAME TYPE [设备号]NAME:设备文件(节点)名TYPE:b:块设备c:字符设备

6.4.2、生成设备文件

  • class_create()
/* This is a #define to keep the compiler from merging different*instances of the __key variable*/
#define class_create(owner,name)\
({\static struct lock_class_key __key;\__class_create(owner,name, &__key);\
})
/** owner:	THIS_MODULE* name:	名字* 返回值	  struct class* 指针*//**__class_create-	create a structclassstructure最终的体现:在/sys/class目录中创建一个以*@owner:	pointer to the module that is to"own"thisstructclass*@name:	pointer to a stringforthe nameofthisclass.*@key:		the lock_class_keyforthisclass;used by mutex lock debugging**This is used to create a struct class pointer that can then be used*in calls to device_create().**Returns & struct class pointer on success,or ERR_PTR() on error.**Note,the pointer created here is to be destroyed when finished by*making a call toclass_destroy().*/
struct class *__class_create(struct module* owner, const char* name, struct lock_class_key*key)/** 为了匹配数据类型*/static inline void* __must_check ERR_PTR(long error)
{return (void*)error;
}static inline long __must_check PTR_ERR(const void *ptr)
{return (long)ptr;
}long __must_check IS_ERR(const void *ptr) //判断是否执行错误void class_destroy(struct class *cls); //销毁2、device_create/**
*device_create-creates a device and registers itwithsysfs
*@class:pointer to the structclassthatthisdevice should be registered to
*@parent:pointer to the parent struct deviceofthisnewdevice,ifany
*@devt:the dev_tforthe char device to be added
*@drvdata:the data to be added to the deviceforcallbacks
*@fmt:stringforthe device's name
*
*Thisfunctioncan be used by char device classes.Astruct device
*will be createdinsysfs,registered to the specifiedclass.
*
*A"dev"file will be created,showing the dev_tforthe device,if
*the dev_t is not0,0.
*If a pointer to a parent struct device is passedin,the newly created
*struct device will be a childofthat deviceinsysfs.
*The pointer to the struct device will be returnedfromthe call.
*Any further sysfs files that might be required can be created usingthis
*pointer.
*
*Returns&struct device pointer on success,orERR_PTR()on error.
*
*Note:the structclasspassed tothisfunctionmust have previously
*been createdwitha call toclass_create().
*/struct device* device_create(struct class *class, struct device *parent,\dev_t devt, \void* drvdata,\constchar *fmt,...)void device_destroy(struct class *class, dev_t devt)

————————–以上是clasee_create和device_create所作的事————————-

  • 完整代码如下:

    /*file name : chardev.c*/
    #include <linux/module.h>
    #include <linux/init.h>
    #include <linux/cdev.h>
    #include <linux/fs.h>
    #include <linux/device.h>#define NAME "chardev"
    #define COUNT 3 
    dev_t dev_no;
    struct cdev *cdevp = NULL;
    struct class *cls = NULL;
    struct device *devp = NULL;static int demo_open(struct inode *inode, struct file *fp)
    {printk(KERN_DEBUG "[%s-%s-%d]char_dev opened.\n", __FILE__, __func__, __LINE__ );return 0;
    }static int demo_release(struct inode *inode, struct file *fp)
    {printk(KERN_DEBUG "[%s-%s-%d]:chrdev exited.\n", __FILE__, __func__, __LINE__ );return 0;
    }struct file_operations fop = {.owner = THIS_MODULE,.open = demo_open,.release = demo_release,
    };static int __init demo_init(void)
    {int ret = 0;int i = 0;ret = alloc_chrdev_region(&dev_no, 0, COUNT, "NAME");if (ret < 0){printk(KERN_ERR "[%s-%s-%d]:alloc_chrdev_region failed.\n", __FILE__, __func__, __LINE__ );goto out0;}printk(KERN_ERR "dev_no:%d-%d",MAJOR(dev_no),MINOR(dev_no));cdevp = cdev_alloc();if (!cdevp){printk(KERN_ERR "[%s-%s-%d]:alloc_chrdev failed.\n", __FILE__, __func__, __LINE__ );ret = -ENOMEM;goto out1;}cdev_init(cdevp, &fop);ret = cdev_add(cdevp, dev_no, COUNT);if (ret < 0){goto out1;}cls = class_create(THIS_MODULE, NAME);if (IS_ERR(cls)){printk(KERN_ERR "[%s-%s-%d]class creat failed\n",__FILE__,__func__,__LINE__);ret = PTR_ERR(cls);goto out2;}for (i = 0; i < COUNT; i++){devp = device_create(cls, NULL, MKDEV(MAJOR(dev_no),i), NULL, "%s%d",NAME,i);if (IS_ERR(devp)){printk(KERN_ERR "[%s-%s-%d]device%d create failed\n",__FILE__,__func__,__LINE__,i);ret = PTR_ERR(devp);goto out3;}}return 0;out3:for (--i; i>0; i--){device_destroy(cls,MKDEV(MAJOR(dev_no),i));}class_destroy(cls);
    out2:cdev_del(cdevp);
    out1:unregister_chrdev_region(dev_no, COUNT);
    out0:return ret;}static void __exit demo_exit(void)
    {int i = 0;for (i = 0; i > COUNT; i++){device_destroy(cls,MKDEV(MAJOR(dev_no),i));}class_destroy(cls);cdev_del(cdevp);unregister_chrdev_region(dev_no, COUNT);
    }module_init(demo_init);
    module_exit(demo_exit);
    MODULE_LICENSE("GPL");
    
    KERN_DIR = /usr/src/linux-headers-4.4.0-040400-genericall:make -C $(KERN_DIR) M=`pwd` modules clean:make -C $(KERN_DIR) M=`pwd` cleanrm -rf modules.orderobj-m   += chardemo.o
    

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FffOGp6D-1648824618616)(https://gitee.com/leon_code/pics_leon/raw/master/202203201902098.png)]

ubuntu 使用 udev 创建设备文件,也就是依赖于图中uevent文件中的内容。
默认创建在/dev目录中

附录:内核错误码

#define EPERM 1			/* Operation not permitted */
#define ENOENT 2		/* No such file or directory */
#define ESRCH 3			/* No such process */
#define EINTR 4			/* Interrupted system call */
#define EIO		5		/* I/O error */
#define ENXIO	6		/* No such device or address */
#define E2BIG	7		/* Argument list too long */
#define ENOEXEC	8		/* Exec format error */
#define EBADF	9		/* Bad file number */
#define ECHILD	10		/* No child processes */
#define EAGAIN	11		/* Try again */
#define ENOMEM	12		/* Out of memory */
#define EACCES	13		/* Permission denied */
#define EFAULT	14		/* Bad address */
#define ENOTBLK	15		/* Block device required */
#define EBUSY	16		/* Device or resource busy */
#define EEXIST	17		/* File exists */
#define EXDEV	18		/* Cross-device link */
#define ENODEV	19		/* No such device */
#define ENOTDIR 20		/* Not a directory */
#define EISDIR	21		/* Is a directory */
#define EINVAL	22		/* Invalid argument */
#define ENFILE	23		/* File table overflow */
#define EMFILE	24		/* Too many open files */
#define ENOTTY	25		/* Not a typewriter */
#define ETXTBSY	26		/* Text file busy */
#define EFBIG	27		/* File too large */
#define ENOSPC	28		/* No space left on device */
#define ESPIPE  29		/* Illegal seek */
#define EROFS 	30		/* Read-only file system */
#define EMLINK	31		/* Too many links */
#define EPIPE   32		/* Broken pipe */
#define EDOM	33		/* Math argument out of domain of func */
#define ERANGE	34		/* Math result not representable */

#define EMFILE 24 /* Too many open files /
#define ENOTTY 25 /
Not a typewriter /
#define ETXTBSY 26 /
Text file busy /
#define EFBIG 27 /
File too large /
#define ENOSPC 28 /
No space left on device /
#define ESPIPE 29 /
Illegal seek /
#define EROFS 30 /
Read-only file system /
#define EMLINK 31 /
Too many links /
#define EPIPE 32 /
Broken pipe /
#define EDOM 33 /
Math argument out of domain of func /
#define ERANGE 34 /
Math result not representable */


http://www.lbrq.cn/news/1331965.html

相关文章:

  • 网站建设优化一体/信息互联网推广
  • 网站加载很慢/怎样注册自己的网站
  • 哪个网站可以做英语语法题/云服务器
  • 视频网站建设的背景简介/外贸推广营销公司
  • 用华为云建立Wordpress网站/长沙网络营销公司排名
  • 电商网站开发的项目描述/百度指数app下载
  • 福田企业网站推广哪个好/济南市最新消息
  • 做校招的网站有哪些/友情手机站
  • 新零售网站建设/如何成为百度广告代理商
  • wordpress淘宝ued/惠州seo关键字优化
  • 怎样可以免费做网站/外包公司是什么意思
  • 后台更新的内容在网站上不显示/青岛seo排名公司
  • 花卉网站建设策划书/优化教程
  • 国务院网站建设标准/友情链接怎么购买
  • 网站后台编辑内容不显示/windows优化工具
  • 桂电做网站的毕设容易过嘛/推广引流方法有哪些推广方法
  • web后端是做什么的/北京网站优化方式
  • 做seo网站优化价格/360竞价推广登录入口
  • 安庆网站建设工作室/网络卖货平台有哪些
  • ui中国网站/优化深圳seo
  • java企业门户网站开发教程/山东16市最新疫情
  • 佛山专业网站设计/网络营销是什么专业类别
  • 北京常用网站/广州seo优化费用
  • 北京门户网站制作费用/百度seo公司哪家好一点
  • 有什么做衣服的网站吗/历下区百度seo
  • 360网站制作潍坊/厦门seo推广优化
  • 装潢公司网站源码php/网站优化排名首页
  • jsp做网站图片怎么存储/百度新闻头条
  • 网站开发项目可行性/nba交易最新消息
  • app开发学习网站/百度网盘app手机版
  • Spring与SpringBoot:从手动挡到自动挡的Java开发进化论
  • Java 排序
  • AI大模型前沿:Muyan-TTS开源零样本语音合成技术解析
  • 电商项目_核心业务_分布式ID服务
  • 【愚公系列】《MIoT.VC》003-构建基本仿真工作站(组件的属性、行为、视频展示)
  • 【AI论文】MiroMind-M1:通过情境感知多阶段策略优化实现数学推理的开源新进展