- 浏览: 16750630 次
- 性别:
- 来自: 济南
-
最新评论
-
wu1236:
ef0793cd94337324b6fefc4c9474af5 ...
Android ApiDemos示例解析(87):Media->MediaPlayer -
77219634:
0127bf2236bee4dd1f632ce430f1af1 ...
本博客文章都为转载,没有任何版权! -
77219634:
0127bf2236bee4dd1f632ce430f1af1 ...
VPLEX - EMC的RAC -
77219634:
0127bf2236bee4dd1f632ce430f1af1 ...
qTip2 Show -
77219634:
0127bf2236bee4dd1f632ce430f1af1 ...
SecureCRT中文乱码、复制粘贴乱码解决办法(修改版)
Creating those files correctly has always been a bit of a challenge, however. It is not that hard to make a /proc file which returns a string. But life gets trickier if the output is long - anything greater than an application is likely to read in a single operation. Handling multiple reads (and seeks) requires careful attention to the reader's position within the virtual file - that position is, likely as not, in the middle of a line of output. The Linux kernel is full of /proc file implementations that get this wrong.
The 2.6 kernel contains a set of functions (implemented by Alexander Viro) which are designed to make it easy for virtual file creators to get it right. This interface (called "seq_file") is not strictly a 2.6 feature - it was also merged into 2.4.15. But 2.6 is where the feature is starting to see serious use, so it is worth describing here.
The seq_file interface is available via <linux/seq_file.h>. There are three aspects to seq_file:
- An iterator interface which lets a virtual file implementation step through the objects it is presenting.
- Some utility functions for formatting objects for output without needing to worry about things like output buffers.
- A set of canned file_operations which implement most operations on the virtual file.
We'll look at the seq_file interface via an extremely simple example: a loadable module which creates a file called /proc/sequence. The file, when read, simply produces a set of increasing integer values, one per line. The sequence will continue until the user loses patience and finds something better to do. The file is seekable, in that one can do something like the following:
dd if=/proc/sequence of=out1 count=1 dd if=/proc/sequence skip=1 out=out2 count=1
Then concatenate the output files out1 and out2 and get the right result. Yes, it is a thoroughly useless module, but the point is to show how the mechanism works without getting lost in other details. (Those wanting to see the full source for this module can find it here).
The iterator interface
Modules implementing a virtual file with seq_file must implement a simple iterator object that allows stepping through the data of interest. Iterators must be able to move to a specific position - like the file they implement - but the interpretation of that position is up to the iterator itself. A seq_file implementation that is formatting firewall rules, for example, could interpret position N as the Nth rule in the chain. Positioning can thus be done in whatever way makes the most sense for the generator of the data, which need not be aware of how a position translates to an offset in the virtual file. The one obvious exception is that a position of zero should indicate the beginning of the file.The /proc/sequence iterator just uses the count of the next number it will output as its position.
Four functions must be implemented to make the iterator work. The first, called start() takes a position as an argument and returns an iterator which will start reading at that position. For our simple sequence example, the start() function looks like:
static void *ct_seq_start(struct seq_file *s, loff_t *pos) { loff_t *spos = kmalloc(sizeof(loff_t), GFP_KERNEL); if (! spos) return NULL; *spos = *pos; return spos; }
The entire data structure for this iterator is a single loff_t value holding the current position. There is no upper bound for the sequence iterator, but that will not be the case for most other seq_file implementations; in most cases the start() function should check for a "past end of file" condition and return NULL if need be.
For more complicated applications, the private field of the seq_file structure can be used. There is also a special value whch can be returned by the start() function called SEQ_START_TOKEN; it can be used if you wish to instruct your show() function (described below) to print a header at the top of the output. SEQ_START_TOKEN should only be used if the offset is zero, however.
The next function to implement is called, amazingly, next(); its job is to move the iterator forward to the next position in the sequence. The example module can simply increment the position by one; more useful modules will do what is needed to step through some data structure. The next() function returns a new iterator, or NULL if the sequence is complete. Here's the example version:
static void *ct_seq_next(struct seq_file *s, void *v, loff_t *pos) { loff_t *spos = (loff_t *) v; *pos = ++(*spos); return spos; }
The stop() function is called when iteration is complete; its job, of course, is to clean up. If dynamic memory is allocated for the iterator, stop() is the place to return it.
static void ct_seq_stop(struct seq_file *s, void *v) { kfree (v); }
Finally, the show() function should format the object currently pointed to by the iterator for output. It should return zero, or an error code if something goes wrong. The example module's show() function is:
static int ct_seq_show(struct seq_file *s, void *v) { loff_t *spos = (loff_t *) v; seq_printf(s, "%Ld\n", *spos); return 0; }
We will look at seq_printf() in a moment. But first, the definition of the seq_file iterator is finished by creating a seq_operations structure with the four functions we have just defined:
static struct seq_operations ct_seq_ops = { .start = ct_seq_start, .next = ct_seq_next, .stop = ct_seq_stop, .show = ct_seq_show };
This structure will be needed to tie our iterator to the /proc file in a little bit.
It's worth noting that the interator value returned by start() and manipulated by the other functions is considered to be completely opaque by the seq_file code. It can thus be anything that is useful in stepping through the data to be output. Counters can be useful, but it could also be a direct pointer into an array or linked list. Anything goes, as long as the programmer is aware that things can happen between calls to the iterator function. However, the seq_file code (by design) will not sleep between the calls to start() and stop(), so holding a lock during that time is a reasonable thing to do. The seq_file code will also avoid taking any other locks while the iterator is active.
Formatted output
The seq_file code manages positioning within the output created by the iterator and getting it into the user's buffer. But, for that to work, that output must be passed to the seq_file code. Some utility functions have been defined which make this task easy.Most code will simply use seq_printf(), which works pretty much like printk(), but which requires the seq_file pointer as an argument. It is common to ignore the return value from seq_printf(), but a function producing complicated output may want to check that value and quit if something non-zero is returned; an error return means that the seq_file buffer has been filled and further output will be discarded.
For straight character output, the following functions may be used:
int seq_putc(struct seq_file *m, char c); int seq_puts(struct seq_file *m, const char *s); int seq_escape(struct seq_file *m, const char *s, const char *esc);
The first two output a single character and a string, just like one would expect. seq_escape() is like seq_puts(), except that any character in s which is in the string esc will be represented in octal form in the output.
There is also a function for printing filenames:
int seq_path(struct seq_file *m, struct vfsmount *mnt, struct dentry *dentry, char *esc);
Here, mnt and dentry indicate the file of interest, and esc is a set of characters which should be escaped in the output. This function is more suited to filesystem code than device drivers, however.
Making it all work
So far, we have a nice set of functions which can produce output within the seq_file system, but we have not yet turned them into a file that a user can see. Creating a file within the kernel requires, of course, the creation of a set of file_operations which implement the operations on that file. The seq_file interface provides a set of canned operations which do most of the work. The virtual file author still must implement the open() method, however, to hook everything up. The open function is often a single line, as in the example module:static int ct_open(struct inode *inode, struct file *file) { return seq_open(file, &ct_seq_ops); };
Here, the call to seq_open() takes the seq_operations structure we created before, and gets set up to iterate through the virtual file.
On a successful open, seq_open() stores the struct seq_file pointer in file->private_data. If you have an application where the same iterator can be used for more than one file, you can store an arbitrary pointer in the private field of the seq_file structure; that value can then be retrieved by the iterator functions.
The other operations of interest - read(), llseek(), and release() - are all implemented by the seq_file code itself. So a virtual file's file_operations structure will look like:
static struct file_operations ct_file_ops = { .owner = THIS_MODULE, .open = ct_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release };
The final step is the creation of the /proc file itself. In the example code, that is done in the initialization code in the usual way:
static int ct_init(void) { struct proc_dir_entry *entry; entry = create_proc_entry("sequence", 0, NULL); if (entry) entry->proc_fops = &ct_file_ops; return 0; } module_init(ct_init);
And that is pretty much it.
The extra-simple version
For extremely simple virtual files, there is an even easier interface. A module can define only the show() function, which should create all the output that the virtual file will contain. The file's open() method then calls:int single_open(struct file *file, int (*show)(struct seq_file *m, void *p), void *data);
When output time comes, the show() function will be called once. The data value given to single_open() can be found in the private field of the seq_file structure. When using single_open(), the programmer should use single_release() instead of seq_release() in the file_operations structure to avoid a memory leak.
(Log in to post comments)
|
|
|
|
相关推荐
Table of Contents| Index ...Prentice Hall Open Source Software Development Series Foreword Preface ...The Seq File Advantage Updating the NVRAM Driver Looking at the Sources Index
qt 一个基于Qt Creator(qt,C++)实现中国象棋人机对战.
热带雨林自驾游自然奇观探索
冰川湖自驾游冰雪交融景象
C51 单片机数码管使用 Keil项目C语言源码
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
前端分析-2023071100789s12
Laz_制作了一些窗体和对话框样式.7z
1、文件内容:ocaml-docs-4.05.0-6.el7.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/ocaml-docs-4.05.0-6.el7.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、更多资源/技术支持:公众号禅静编程坊
学习笔记-沁恒第六讲-米醋
工业机器人技术讲解【36页】
内容概要:本文档详细介绍了在 CentOS 7 上利用 Docker 容器化环境来部署和配置 Elasticsearch 数据库的过程。首先概述了 Elasticsearch 的特点及其主要应用场景如全文检索、日志和数据分析等,并强调了其分布式架构带来的高性能与可扩展性。之后针对具体的安装流程进行了讲解,涉及创建所需的工作目录,准备docker-compose.yml文件以及通过docker-compose工具自动化完成镜像下载和服务启动的一系列命令;同时对可能出现的问题提供了应对策略并附带解决了分词功能出现的问题。 适合人群:从事IT运维工作的技术人员或对NoSQL数据库感兴趣的开发者。 使用场景及目标:该教程旨在帮助读者掌握如何在一个Linux系统中使用现代化的应用交付方式搭建企业级搜索引擎解决方案,特别适用于希望深入了解Elastic Stack生态体系的个人研究与团队项目实践中。 阅读建议:建议按照文中给出的具体步骤进行实验验证,尤其是要注意调整相关参数配置适配自身环境。对于初次接触此话题的朋友来说,应该提前熟悉一下Linux操作系统的基础命令行知识和Docker的相关基础知识
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
网络小说的类型创新、情节设计与角色塑造
毕业设计_基于springboot+vue开发的学生考勤管理系统【源码+sql+可运行】【50311】.zip 全部代码均可运行,亲测可用,尽我所能,为你服务; 1.代码压缩包内容 代码:springboo后端代码+vue前端页面代码 脚本:数据库SQL脚本 效果图:运行结果请看资源详情效果图 2.环境准备: - JDK1.8+ - maven3.6+ - nodejs14+ - mysql5.6+ - redis 3.技术栈 - 后台:springboot+mybatisPlus+Shiro - 前台:vue+iview+Vuex+Axios - 开发工具: idea、navicate 4.功能列表 - 系统设置:用户管理、角色管理、资源管理、系统日志 - 业务管理:班级信息、学生信息、课程信息、考勤记录、假期信息、公告信息 3.运行步骤: 步骤一:修改数据库连接信息(ip、port修改) 步骤二:找到启动类xxxApplication启动 4.若不会,可私信博主!!!
在智慧城市建设的大潮中,智慧园区作为其中的璀璨明珠,正以其独特的魅力引领着产业园区的新一轮变革。想象一下,一个集绿色、高端、智能、创新于一体的未来园区,它不仅融合了科技研发、商业居住、办公文创等多种功能,更通过深度应用信息技术,实现了从传统到智慧的华丽转身。 智慧园区通过“四化”建设——即园区运营精细化、园区体验智能化、园区服务专业化和园区设施信息化,彻底颠覆了传统园区的管理模式。在这里,基础设施的数据收集与分析让管理变得更加主动和高效,从温湿度监控到烟雾报警,从消防水箱液位监测到消防栓防盗水装置,每一处细节都彰显着智能的力量。而远程抄表、空调和变配电的智能化管控,更是在节能降耗的同时,极大地提升了园区的运维效率。更令人兴奋的是,通过智慧监控、人流统计和自动访客系统等高科技手段,园区的安全防范能力得到了质的飞跃,让每一位入驻企业和个人都能享受到“拎包入住”般的便捷与安心。 更令人瞩目的是,智慧园区还构建了集信息服务、企业服务、物业服务于一体的综合服务体系。无论是通过园区门户进行信息查询、投诉反馈,还是享受便捷的电商服务、法律咨询和融资支持,亦或是利用云ERP和云OA系统提升企业的管理水平和运营效率,智慧园区都以其全面、专业、高效的服务,为企业的发展插上了腾飞的翅膀。而这一切的背后,是大数据、云计算、人工智能等前沿技术的深度融合与应用,它们如同智慧的大脑,让园区的管理和服务变得更加聪明、更加贴心。走进智慧园区,就像踏入了一个充满无限可能的未来世界,这里不仅有科技的魅力,更有生活的温度,让人不禁对未来充满了无限的憧憬与期待。
1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
内容概要:本文介绍了使用 Matlab 实现基于 BO(贝叶斯优化)的 Transformer 结合 GRU 门控循环单元时间序列预测的具体项目案例。文章首先介绍了时间序列预测的重要性及其现有方法存在的限制,随后深入阐述了该项目的目标、挑战与特色。重点描述了项目中采用的技术手段——结合 Transformer 和 GRU 模型的优点,通过贝叶斯优化进行超参数调整。文中给出了模型的具体实现步骤、代码示例以及完整的项目流程。同时强调了数据预处理、特征提取、窗口化分割、超参数搜索等关键技术点,并讨论了系统的设计部署细节、可视化界面制作等内容。 适合人群:具有一定机器学习基础,尤其是熟悉时间序列预测与深度学习的科研工作者或从业者。 使用场景及目标:适用于金融、医疗、能源等多个行业的高精度时间序列预测。该模型可通过捕捉长时间跨度下的复杂模式,提供更为精准的趋势预判,辅助相关机构作出合理的前瞻规划。 其他说明:此项目还涵盖了从数据采集到模型发布的全流程讲解,以及GUI图形用户界面的设计实现,有助于用户友好性提升和技术应用落地。此外,文档包含了详尽的操作指南和丰富的附录资料,包括完整的程序清单、性能评价指标等,便于读者动手实践。
漫画与青少年教育关系
励志图书的成功案例分享、人生智慧提炼与自我提升策略