`
hulianwang2014
  • 浏览: 681048 次
文章分类
社区版块
存档分类
最新评论
  • bcworld: 排版成这样,一点看的欲望都没有了
    jfinal

关于EOF和读文件的一些事

 
阅读更多
到底什么是EOF?这是一个问题。一般而言,EOF字面含义就是文件的结尾-end of file,可是如何去检查是否已经到了结尾呢?文件类型各种各样,不可能在文件的结尾处真实的写一个EOF标志,如果真的这么做,操作系统内核的文件系统设计将会非常复杂,于是这个“检测”文件结尾的工作就交给了用户态,通常来讲就是C库来做这件事。内核仅仅按照顺序的方式向前推进对文件的访问即可,因此对于内核态文件数据结构而言,维护一个pos是重要的,正是这个pos不断向前推进,最终到达文件的尾部,每次读取文件是从pos处开始读取,到了最后pos已经到达了文件尾部,那么再读的话就会返回“读到的长度为0”这个结果,而正是这个结果标示了EOF。因此,用户态的程序在读文件时大体都遵循以下逻辑:
open
while true
    read=>length
    if length=0
        EOF
        break
done
也就是说通过检测read到0字节长度的数据来定义EOF。背后的逻辑就是文件的pos在不断向前推进,一直到底,而这是内核维护的,最终内核默默地维护pos,给与用户态的表象就是read到0字节的数据。
如果内核不更新文件的pos,那么理论上这个文件将会一直可以读取,没完没了地被读取,这种机制可以实现一些“其它的文件”。之所以要有其它的文件,是因为Unix文件囊括的东西真是太多了,范围太广大了。有些文件真的不适合有一个结尾,也就是不适合维护一个pos,比如/dev/urandom(这个文件的内核file_operations接口根本不维护pos)这种产生随机数设备文件以及那些根本没有“文件逻辑”然而为了接口方便而必须使用文件接口的设备或者别的。
在Linux中,procfs是一种拥有文件接口的内核信息导出逻辑,该文件系统提供了几乎所有的“文件”访问方式,这里的文件是广义意义上的,也就是说包括维护pos的文件和不维护pos的文件,对于一般的文件,procfs文件系统访问框架自动维护了pos,因此你使用creare-read/write-entry的接口创建的文件,即使在你提供的回调函数中再希望实现“不间断读取”这种不维护pos的逻辑,也是不可能的,因为这种接口的框架层已经帮你维护了一个pos,最终一定会达到文件尾部的。然而有一种方式可以做到不维护pos状态或者说将pos的语义进行了转义或者说误导。以下就是一个代码实例,如果你用cat来读取,将会不间断的输出:
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/proc_fs.h>

#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <linux/seq_file.h>

//定义一个变量,每次自增1,你可以将它定义成你的随机数
int i = 0;

struct proc_dirandom_entry *test;

static void *random_start(struct seq_file *m, loff_t *pos)
{
    return &i;
}
static void *random_next(struct seq_file *m, void *v, loff_t *pos)
{
    //这里产生递增的i
    i++;
    return &i;
}

static void random_stop(struct seq_file *m, void *v)
{
    //例行公事
    return;
}

static int random_show(struct seq_file *m, void *v)
{
    //这里是显示逻辑
    int *a = (int*)v;
    seq_printf(m, "%d\n", *a);
    return 0;
}

static const struct seq_operations random_ops = {
    .start = random_start,
    .next = random_next,
    .stop = random_stop,
    .show = random_show,
};

static int ran_open(struct inode *inode, struct file *file)
{
    int ret = seq_open(file, &random_ops);
    return ret;
}



static const struct file_operations random_file = {
    .open = ran_open,
    .read = seq_read,
    .llseek = seq_lseek,
    .release = seq_release,
    .owner = THIS_MODULE,
};



static int __init
ran_test_init(void)
{
    int ret = 0;
    //初始化,名字随便起的
    test = proc_mkdir("simple", NULL);
    proc_create_data("abcd", 0, test,
             &random_file, NULL);
    return ret;
}

static void __exit
ran_test_exit(void)
{
    remove_proc_entry("driver", test);
    remove_proc_entry("simple", NULL);
}
module_init(ran_test_init);
module_exit(ran_test_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Zhaoya <marywangran@126.com>");
MODULE_DESCRIPTION("Just a testing");

这仅仅是一个使用seqfs实现永久输出的例子,如果你非要使用“一般的文件”来实现之,你就必须在每次读取之后自行lseek,虽然内核自动推进了pos,然而你可以在用户态将pos再退回来:
open
while true
    read
    lseek to 0
done

关键之处就是读到的东西是什么,如是随机数,那么每次的都不一样,赚到了。
分享到:
评论

相关推荐

    谭浩强书中错误eof和feof

    因为文本文件中存储的是ASCII码,而ASCII码中FF代表空值(blank),一般不使用,所以如果读文件返回了FF,说明已经到了文本文件的结尾。但是如果是二进制文件,其中可能会包含FF,因此不能把读到EOF作为文件结束的条件...

    13.第十三章 文件.txt

    对文件的读和写是最常用的文件操作,在C语言标准库中提供了多种文件读写的函数。 字符读写函数:fgetc和fputc 字符串读写函数:fgets和fputs 数据块读写函数:fread和fwrite 格式化读写函数:fscanf和fprintf ...

    C语言-文件-知识要点.pdf

    "C语言文件处理知识要点"是一份关于C语言文件处理的详细知识资源,涵盖了C语言中与文件操作相关的重要概念、技巧和用法。文件处理在编程中是一个基础且关键的部分,能够帮助开发者读取、写入和操作各种类型的文件,...

    c语言文件操作系统

    一个很小的很简洁的文件操作系统!#include #include &lt;malloc.h&gt; ...=EOF) /*从文件读一字符,显示到屏幕*/ { //显示字符 putchar(ch); //继续移动指针读取字符 直到文件结尾 ch=fgetc(fp);

    深入解读C语言中的符号常量EOF

    EOF是指文件的结束符,是一个宏定义  借助于getchar 与putchar 函数,可以在不了解其它输入/输出知识的情况下编写出 数量惊人的有用的代码。最简单的例子就是把输入一次一个字符地复制到输出,其基本思想 如下: ...

    JAVA NIO 按行读取大文件支持 GB级别-修正版

    采用读文件的缓存 fbb 1024*5 行缓存 bb 256 字节 设计思想: 每次通过nio读取字节到 fbb中 然后对fbb自己中的内容进行行判断即 10 回车 13 行号 0 文件结束 这样字节的判断,然后 返回行 如果 到达 fbb的结尾 ...

    使用POI操作Excel文件(读)

    使用POI操作Excel文件,也可参考:http://blog.csdn.net/flyever581549/archive/2008/11/11/3274688.aspx

    如何编写批处理文件批处理文件批处理文件

    在实际应用中我们会把这条命令和重定向符号(也称为管道符号,一般用&gt; &gt;&gt; ^)结合来实现输入一些命令到特定格式的文件中.这将在以后的例子中体现出来。 2.@ 命令 表示不显示@后面的命令,在入侵过程中(例如使用...

    PHP使用feof()函数读文件的方法

    本文实例讲述了PHP使用feof()函数读文件的方法。分享给大家供大家参考。具体用法如下: feof应用于PHP 4, PHP 5 -用来测试文件指针是否到了文件结束的位置。 如果服务器没有关闭由 fsockopen&#40;&#41; 所打开的...

    文件内容复制程序.doc

    //命令行错,结束程序的执行 } //按读方式打开由argv[1]指出的文件 if((in=fopen(argv[1],"r"))==NULL) { printf("The file &lt;%s&gt; can not be opened.\n",argv[1]); return; //打开失败,结束程序的执行 } //成功...

    LabVIEW的读取测量文件

    “读取测量文件”Express Ⅵ位于函数选板“编程→文件I/O→读取测量文件”,图标和接线端如图1所示。  读取测量文件从基于文本的测量文件(.lvm)和二进制... 文件名:指定所读文件的文件名。  EOF?:如果Expres

    Python实现将一个大文件按段落分隔为多个小文件的简单操作方法

    基本思路是,先读原文件内容,并使用正则表达式,依据\n\n进行切片处理,结果为一个列表,其中每一个列表元素都存放一个切片中的内容;然后创建一个写文件的句柄;接下来遍历切片列表,并写入当前切片内容,判断是否...

    golang 读文件

    go语言读文件学习总结 1、使用指针对象读文件 package main import ( fmt io os ) func main() { file, err := os.Open(./main.go) if err != nil { fmt.Println(open file failed) return } defer file...

    C语言程序设计标准教程

    应注意文件指针和文件内部的位置指针不是一回事。文件指针是指向整个文件的,须在程序中定义说明,只要不重新赋值,文件指针的值是不变的。文件内部的位置指针用以指示文件内部的当前读写位置,每读写一次,该指针...

    EDA/PLD中的LabVIEW的读取测量文件

    “读取测量文件”Express Ⅵ位于函数选板“编程→文件I/O→读取测量文件”,图标和接线端如图1所示。  读取测量文件从基于文本的测量文件(.lvm)和二进制... 文件名:指定所读文件的文件名。  EOF?:如果Expres

    文件的读写操作

    1.fgetc/fputc(fgetc结束标记EOF) //从fp指向的文件中一次读取一个字符 fgetc(fp) ...//从fp指向的文件中读文件的读写 文件起始处取信息到数组buf中,最大读取500字节,按行读取 fgets(buf, 500, fp);

    Go语言编程中对文件读写的基本方法整理

    1.func Copy(dst Writer, src Reader) (written int64, err error)这个函数是从一个文件读取拷贝到另外一个文件,一直拷贝到读取文件的EOF,所以不会返回io.EOF错误,参数是写入目标器和读取目标器,返回int64的拷贝...

    Perl 实例精解(第三版).pdf

    9.1.2 打开文件读 9.1.3 打开文件写 9.1.4 Win32文件 9.1.5 打开文件添加 9.1.6 select函数 9.1.7 使用flock锁住文件 9.1.8 seek和tell函数 9.1.9 打开文件读写 9.1.10 管道打开 9.2 ...

    python中rb含义理解

    Python文件读写的几种模式: r,rb,w,wb 那么在读写文件时,...读文件 进行读文件操作时,直到读到文档结束符(EOF)才算读取到文件最后,Python会认为字节\x1A(26)转换成的字符为文档结束符(EOF), 故使用’r’进行读

    对python for 文件指定行读写操作详解

    a:以追加模式打开 (从 EOF 开始, 必要时创建新文件) r+:以读写模式打开 w+:以读写模式打开 (参见 w ) a+:以读写模式打开 (参见 a ) rb:以二进制读模式打开 wb:以二进制写模式打开 (参见 w ) ab:以二进制追加...

Global site tag (gtag.js) - Google Analytics