Chinaunix

标题: c真的可以直接操作文件吗? [打印本页]

作者: sihan    时间: 2008-01-31 15:45
标题: c真的可以直接操作文件吗?
一直觉得C不能直接对磁盘文件操作, 而是把文件全部读到内存理, 操作完成后,
在全部写回磁盘。 可是下面这个程序确实可以工作, 不知道哪位高手知道
其内部的实现思路大概是怎么的?

个人觉得应该是: 读到内存-改-写回内存

bash-3.1$ cat test.txt
This is a test file
for test04.c.


执行下面程序:
#include <stdio.h>

int main(void)
{
&nbsp;&nbsp;&nbsp;&nbsp;char *fname = "test.txt";
&nbsp;&nbsp;&nbsp;&nbsp;FILE *fp;

&nbsp;&nbsp;&nbsp;&nbsp;fp = fopen(fname, "r+");

&nbsp;&nbsp;&nbsp;&nbsp;fseek(fp, 0, SEEK_END);
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;fprintf(fp, "hello, world!\n");
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;return 0;
}


结果:
bash-3.1$ cat test.txt
This is a test file
for test04.c.

hello, world!

作者: lenovo    时间: 2008-01-31 15:49
原帖由 sihan 于 2008-1-31 15:45 发表
一直觉得C不能直接对磁盘文件操作, 而是把文件全部读到内存理, 操作完成后,
在全部写回磁盘。 可是下面这个程序确实可以工作, 不知道哪位高手知道
其内部的实现思路大概是怎么的?

个人觉得应该是:  ...

我有一个4g的文件,你的内存够大吗?
作者: 熏红猴    时间: 2008-01-31 15:52
文件系统是按块来的吧。
作者: zszyj    时间: 2008-01-31 15:55
原帖由 sihan 于 2008-1-31 15:45 发表
一直觉得C不能直接对磁盘文件操作, 而是把文件全部读到内存理, 操作完成后,
在全部写回磁盘。 可是下面这个程序确实可以工作, 不知道哪位高手知道
其内部的实现思路大概是怎么的?

个人觉得应该是:  ...

你对C的文件操作理解真有意思, 恐怕你以为这世界上所有语言都是仿JAVA的了.
作者: sihan    时间: 2008-01-31 16:02
原帖由 lenovo 于 2008-1-31 15:49 发表

我有一个4g的文件,你的内存够大吗?


原帖由 zszyj 于 2008-1-31 15:55 发表

你对C的文件操作理解真有意思, 恐怕你以为这世界上所有语言都是仿JAVA的了.



那各位的意思是, 直接对磁盘进行操作了?

那如果我想给文件中间插入一段文字, fseek到文件中间, 然后fwrite进入。 这个过程怎么实现的呢?

岂不是要把我的fseek点以后的内容往后移我要fwrite的字节数, 然后在插入? 就好比在数组中间插入?
作者: halve    时间: 2008-01-31 16:05
sihan 说的大致没有错
一般情况下,我们并不能直接对磁盘进行读写操作
事实上,操作系统会维护一个内存区域,这个区域由很多小块内存组成
每一内存小块对应磁盘的一个小单元,比如一个扇区
然后我们对磁盘的所有读写操作,实际上都是对相应的内存镜像的操作
而磁盘与内存镜像之间的同步工作由操作系统完成(即所谓的读磁盘,写磁盘)

当然,这只是大概的一个描述,操作系统对于文件系统的管理
涉及到的磁盘读取,镜像分配,数据定位,文件组织,数据同步有很多复杂的机制跟算法
如果感兴趣,可以找本介绍内核的书,找文件系统相关的章节翻翻

[ 本帖最后由 halve 于 2008-1-31 16:07 编辑 ]
作者: sihan    时间: 2008-01-31 16:16
......

[ 本帖最后由 sihan 于 2008-1-31 16:20 编辑 ]
作者: sihan    时间: 2008-01-31 16:18
原帖由 halve 于 2008-1-31 16:05 发表
sihan 说的大致没有错
一般情况下,我们并不能直接对磁盘进行读写操作
事实上,操作系统会维护一个内存区域,这个区域由很多小块内存组成
每一内存小块对应磁盘的一个小单元,比如一个扇区
然后我们对磁盘的 ...



我刚问的问题的关键是: fopen("r+"), fseek(), fwrite() 这样的操作确实
可以不自己读文件到内存, 改, 然后写磁盘。

按理说:
fopen() ->open()
fseek() -> lseek()
fwrite() -> write()

照这样看, 那就是说, “读文件到内存, 改, 然后写磁盘”
这一系列操作是由 write保证的, 也就是操作系统保证的 ?
不知道我这样的理解对否?

或者说, write操作没有读文件到内存, 而是直接操作磁盘, 如下图这样:

原文件在磁盘上:
-----------------------------
|file_part1 | file_part2 |
-----------------------------

write插入操作后在磁盘上:
-----------------------------
|file_part1 | file_part2 |
-----------------------------
                / \
               /   \
         ----------------
         |file_part1.5|
         ----------------
作者: zx_wing    时间: 2008-01-31 16:23
原帖由 sihan 于 2008-1-31 16:18 发表



我刚问的问题的关键是: fopen("r+"), fseek(), fwrite() 这样的操作确实
可以不自己读文件到内存, 改, 然后写磁盘。

按理说:
fopen() ->open()
fseek() -> lseek()
fwrite() -> write()

照 ...

你最初的理解是对的,都是先在内存里做了修改再写回磁盘的。
没有直接写磁盘的说法。

[ 本帖最后由 zx_wing 于 2008-1-31 16:24 编辑 ]
作者: halve    时间: 2008-01-31 16:29
对磁盘的操作,都是根据一个最小单位来进行的,比如扇区,一次读取一个扇区,一次更改一个扇区
根据你的流程
open() 得到这个文件磁盘布局的索引信息,即每个位置的数据存在磁盘哪个扇区上
lseek() 得到文件指定位置处数据对应的扇区位置
write() 修改扇区内容
这个过程中,所有的操作都是作用于磁盘的内存镜像
有可能你要修改的扇区并没有对应的内存镜像
这个时候系统会负责将这个扇区读入内存(总的镜像数目有限制,若没有多余空闲区域,系统会释放一个已经不再使用的镜像)
然后你修改这一小块内存之后,系统会在一个合适的时间将这块内存的内容写入扇区
作者: sihan    时间: 2008-01-31 16:36
原帖由 zx_wing 于 2008-1-31 16:23 发表

你最初的理解是对的,都是先在内存里做了修改再写回磁盘的。
没有直接写磁盘的说法。


那现在假定: “读文件到内存, 改, 然后写磁盘” 成立。 接下来的问题是:

我要在一个4G的文件中间插入“hello, world!"这句。我进行的操作是:

fopen(file, "r+");
fseek(file_middle);
fwrite("hello, world!");

write是怎么完成这个操作的呢?

write()应该会如下执行:

read_from_device(buf);
inset(buf, position);
write_to_device(buf);

按照”读文件到内存, 改, 然后写磁盘“, 读4G? 内存没那么大呀?
作者: sihan    时间: 2008-01-31 16:40
原帖由 halve 于 2008-1-31 16:29 发表
open() 得到这个文件磁盘布局的索引信息,即每个位置的数据存在磁盘哪个扇区上
lseek() 得到文件指定位置处数据对应的扇区位置
write() 修改扇区内容
这个过程中,所有的操作都是作用于磁盘的内存镜像
有可能你要修改的扇区并没有对应的内存镜像
这个时候系统会负责将这个扇区读入内存(总的镜像数目有限制,若没有多余空闲区域,系统会释放一个已经不再使用的镜像)


明白了, 十分感谢大家!
作者: zx_wing    时间: 2008-01-31 16:49
原帖由 sihan 于 2008-1-31 16:36 发表


那现在假定: “读文件到内存, 改, 然后写磁盘” 成立。 接下来的问题是:

我要在一个4G的文件中间插入“hello, world!"这句。我进行的操作是:

fopen(file, "r+");
fseek(file_middle);
fwrite( ...

唉,不知道CU怎么能快速搜索自己的回复,本来想给你找一篇以前的回复的,找不到了,简单的说一下。
对操作系统来说,它用页来管理内存,磁盘以sector来管理自己的大小。
通常来说一个sector是512 byte。逻辑上,我们讲磁盘分区后,每个区的开始可以看作sector 0处(类似基地址),该区内的其它位置可以看作sector 0 + offset sector。也就是通过类似基地址加偏移这种方式寻址磁盘的。

实际上OS寻址磁盘通过下面这个流程:
修改处相对于文件起始处的偏移  ----->  修改处相对于分区起始处的偏移 -----> 修改处相对于磁盘0磁道的偏移

所以对于1个4G的文件,OS先找到它在哪个分区,然后计算出你要插入“hello world”的位置相对于分区开始是多少偏移,然后将此处一个block(这是OS管理磁盘大小的一个单位,默认大小应该是1024 bytes)读入一个内存页,修改后再写回。
所以并不需要读入整个4G文件,而是用到什么地方读什么地方。
作者: GodPig    时间: 2008-01-31 20:50
还有一种是用内存映射的方法进行操作的,这普通的操作与内存映射再进行操作有什么样的区别吗???
看大家的解释,也是将某一块映射到内存,然后再进行读写之类的操作
作者: zx_wing    时间: 2008-01-31 21:00
原帖由 GodPig 于 2008-1-31 20:50 发表
还有一种是用内存映射的方法进行操作的,这普通的操作与内存映射再进行操作有什么样的区别吗???
看大家的解释,也是将某一块映射到内存,然后再进行读写之类的操作

在linux下,mmap映射文件实质上和read、write方式是一样的。应用程序用像操作内存的方式操作文件,由内核完成read、write操作,对应用程序隐藏细节。
windows上的实现就不一样。windows是直接把映射的文件作为虚拟内存映射到应用程序的地址空间中,当应用程序访问该内存时,依靠内存管理中的swap机制将文件内容读入内存中
作者: SuperZ    时间: 2008-01-31 21:13
在所有语言中,文件操作最终都会转化成系统调用(文件系统的系统调用)。
所以,文件读写策略和c语言没有任何关系;是操作系统,文件系统和设备驱动程序关心的事情。
作者: langue    时间: 2008-01-31 22:16
原帖由 SuperZ 于 2008-1-31 21:13 发表
在所有语言中,文件操作最终都会转化成系统调用(文件系统的系统调用)。
所以,文件读写策略和c语言没有任何关系;是操作系统,文件系统和设备驱动程序关心的事情。


不假,另外文件系统 cache/buffer 的运行机制可以参考 halve #10
作者: langue    时间: 2008-01-31 22:24
另外 read(2)、write(2)、open(2)、lseek(2) 这些都是系统调用,不同的系统可能提供不同的接口(注意,即使接口相同,其语义也可能各有千秋),比如 win32 上使用的是 ReadFile()、WriteFile()、OpenFile() 等一系列 API
如果希望编写跨平台兼容性更强的程序,那么建议尽量使用标准 C 库
作者: wwdwwd    时间: 2008-02-01 01:08
看到大家讨论,受益匪浅,尤其是zx_wing  和langue 两位,继续关注中,^_^
作者: GodPig    时间: 2008-02-01 09:23
恩,谢谢

我发现一个问题,在Win的论坛上很少有人对Unix了解
但是Unix论坛上,好多人对Win了解
作者: cugb_cat    时间: 2008-02-01 09:34
楼主试一下open的O_SYNC标志。
作者: whitehand    时间: 2008-02-01 09:50
启发~~~
作者: maxxfire    时间: 2008-02-01 10:10
有种东西叫做系统调用,即使没有系统调用,BIOS中断调用也可以操作磁盘。。
作者: sihan    时间: 2008-02-01 14:15
原帖由 cugb_cat 于 2008-2-1 09:34 发表
楼主试一下open的O_SYNC标志。


O_SYNC
    打开 文件 实现 I/O 的 同步 . 任何 通过 文件描述符 对 文件 的 write 都会 使 调用 的 进程 中断 , 直到 数据 被 真正 写入 硬件 中 .


但还是会使用内核buffer的。

这和我问的问题没啥关系吧?
作者: SST中国    时间: 2008-02-01 15:23
一个File对应其所在的文件系统的file 结构.其结构中有file operations 结构,对应你那些open,read and so on.
具体定位到磁盘要这样.
先找dentry.再找出inode. 用inode 对应super block.用super block对应磁盘的存储位置.
作者: cugb_cat    时间: 2008-02-01 15:25
原帖由 sihan 于 2008-2-1 14:15 发表


O_SYNC
    打开 文件 实现 I/O 的 同步 . 任何 通过 文件描述符 对 文件 的 write 都会 使 调用 的 进程 中断 , 直到 数据 被 真正 写入 硬件 中 .


但还是会使用内核buffer的。

这和我问的问题没 ...

晕,IO操作都是系统调用,肯定是内核先把数据读到内核缓冲区,然后再拷贝到用户空间啊。
作者: emacsnw    时间: 2008-02-01 15:48
用户程序肯定不能绕过内核直接操作磁盘,不然就谈不上文件系统的保护和安全了。
作者: weigongwan    时间: 2008-02-01 17:11
就是分块读到内存然后操作!并不是把所有的都直接先放到内存
作者: flw2    时间: 2008-02-01 17:27
原帖由 sihan 于 2008-2-1 14:15 发表


O_SYNC
    打开 文件 实现 I/O 的 同步 . 任何 通过 文件描述符 对 文件 的 write 都会 使 调用 的 进程 中断 , 直到 数据 被 真正 写入 硬件 中 .


但还是会使用内核buffer的。

这和我问的问题没 ...


我看了好久也发只有SuperZ说的完全符合你的题目意思

其实D语言也能操作文件,只要你使用linux的系统调用

2楼老版主是想告诉你你的说法明显是错的
3楼说了和没说一样
4也说了和语言没关系
5楼说的没错,可是我看了还是觉得跟没说一样(对你的问题来说)
6...

总的来说,没太看懂
作者: sihan    时间: 2008-02-01 18:12
原帖由 flw2 于 2008-2-1 17:27 发表


我看了好久也发只有SuperZ说的完全符合你的题目意思

其实D语言也能操作文件,只要你使用linux的系统调用

2楼老版主是想告诉你你的说法明显是错的
3楼说了和没说一样
4也说了和语言没关系
5楼说的没 ...


我在12楼已经明确表明 halve 说的符合我的意思。
zx_wing 让我更肯定这种理解,
本来想在那层节贴的, 但牵扯到大家可以互相学习,
就没节。

你说了一堆, 除了激发大家的火药味之外, 感觉没一点用处。
看了你对大家的评论, 你应该是高手了, 解释下吧!
作者: dxcnjupt    时间: 2008-02-01 21:15
补充一点点

读写文件,必须过操作系统的原因,在于CPU不能直接操作硬盘;
对硬盘执行的所有操作必须通过IO端口访问硬盘以及DMA的控制/数据寄存器;
也就是说,你需要一个驱动来访问硬盘;
如果每写一个字节都调用驱动就会效率很低,所以引入了缓冲区(然后还有物理地址和虚拟地址的问题);
操作系统管理上述所有资源,用户就不需要去看一大堆麻烦的东西,只要知道write就可以了。
作者: flw    时间: 2008-02-01 21:17
楼主问的是如何操作文件,但我看很多人讨论的都是如何操作磁盘。
作者: tgbvc    时间: 2008-02-01 21:20
装SOD
作者: agaric    时间: 2008-02-01 23:19
块设备读写大致都是这个样子。
作者: flw2    时间: 2008-02-02 09:13
原帖由 sihan 于 2008-2-1 18:12 发表


我在12楼已经明确表明 halve 说的符合我的意思。
zx_wing 让我更肯定这种理解,
本来想在那层节贴的, 但牵扯到大家可以互相学习,
就没节。

你说了一堆, 除了激发大家的火药味之外, 感觉没一点用 ...


作者: flw2    时间: 2008-02-02 09:28
补充一下
楼主的问题(1楼 + 题目)其实很简单,就是C语言能不能操作文件,然后对那个结果感到意外
大家说了那么多,而且你后来的帖子我真的不明白是什么意思,您别有什么误会,我说话就那样,我就是说实话而已(就是我看不懂大家在讨论什么,虽然我不敢保证我说对了),说的不对您可以指出来,跟什么手没有关系,所以千万别扣高帽子
再说一下我对您的问题的回答:
C语言能操作文件(除了你这是众所周知的吧),C操作文件不是读到内存-改-写回内存(lenovo的回答非常有针对性),D语言也能操作文件的意思是,只要你使用系统调用,最后生成系统可执行的东西就能操作文件,和C语言和java没有关系,它门最后都要转换成系统调用(的指令)
而且别人回答你的问题,你都没怎么注意吧(我是这么觉得,要不我也不那么说,你再看看你5楼的回答,一点不着边,234楼都是针对你的问题(我猜3楼是想说不是内存回写方式),而5楼就跑题跑远了了)
作者: flw2    时间: 2008-02-02 09:33
开始大家都是真对你的问题,可是你5楼就跑题了,所以针对你24楼的回答,我说几本都跑题了,开始几个帖子没跑题你却好像没看见一样

您现在还那么认为吗?(1楼+题目)
作者: cgxu    时间: 2008-02-02 09:42
不知道这个贴为什么这么热火朝天

我不想给你解释什么,因为解释了你也未必能理解

所以你还想了解的话,你可以

Read the fucking source code
作者: foxpro7    时间: 2008-02-03 15:26
原帖由 GodPig 于 2008-2-1 09:23 发表
恩,谢谢

我发现一个问题,在Win的论坛上很少有人对Unix了解
但是Unix论坛上,好多人对Win了解



那你就应该知道win是多么的强大,连搞unix的人都要学习win。
而一部分人可以不靠unix只靠win就足够用了。
作者: zhaokugua    时间: 2008-02-03 15:50
顶了,发现CU的民风淳朴
作者: hoowa    时间: 2008-02-03 16:26
数据进行数据队列处理,由CPU交给桥接芯片,然后由硬盘控制器(DSP处理器),将其存储到内存中(DSP的内存),由DSP驱动,马达控制芯片进行写。

如果是DMA,数据队列处理将直接由硬盘控制器(DSP处理器)跟桥接芯片接触。
作者: Edengundam    时间: 2008-02-03 16:52
原帖由 zx_wing 于 2008-1-31 16:23 发表

你最初的理解是对的,都是先在内存里做了修改再写回磁盘的。
没有直接写磁盘的说法。



你可以调查下Windows系统上提供的: FILE_FLAG_WRITE_THROUGH, FILE_FLAG_NO_BUFFERING.
提供这种操作, 可以阻止OS进行磁盘buffer管理, 为一些特殊应用程序, 譬如: DBMS实现管理buffer提供支持.

Windows的API性能低不少, 其中一个'次要'原因是没有直接使用内核API. 平时的API都是csrss提供的. Windows还有posix的API呢, 不过支持的好像不是很好.
作者: Edengundam    时间: 2008-02-03 16:59
to LZ:
你使用的是C lib的函数, 它们会在用户空间建立buffer, 此buffer是根据OS的磁盘块进行优化的. fwrite等操作, 如果没有触发flush, 那么信息只会保留在用户空间. 其他进程和OS是看不到的.
当触发flush时(行缓冲, 无缓冲, 全缓冲), C lib负责将用户空间信息交给OS. 此时使用OS的系统调用(WIN下就是API), 这个过程, 操作系统会将这些信息存储到buffer中. 硬盘上的一个数据块, 只会对应内存中的一个buffer. buffer上带有引用计数, 可以用来跟踪引用对象的数量. 用户可以显示申请要求OS将数据同步到磁盘上. 不过即使没有写回磁盘, 不同进程还是可以看到OS内核维护的磁盘块的buffer, 因此只要数据交给了内核, 那么不同进程就都能看到此修改了.

进程退出时, 一般显示要求fflush, 这样用户态的信息被交回给内核buffer, 因此你cat时候, 就会看到文件被修改了.
作者: zx_wing    时间: 2008-02-03 17:21
原帖由 Edengundam 于 2008-2-3 16:52 发表



你可以调查下Windows系统上提供的: FILE_FLAG_WRITE_THROUGH, FILE_FLAG_NO_BUFFERING.
提供这种操作, 可以阻止OS进行磁盘buffer管理, 为一些特殊应用程序, 譬如: DBMS实现管理buffer提供支持.

Win ...

兄台误解LZ意思了。FILE_FLAG_WRITE_THROUGH、FILE_FLAG_NO_BUFFERING其实类似于linux下的O_SYNC和DIRECT_IO参数。
前者是写操作直接flush到磁盘不缓存,后者是不使用文件系统的buffer。这和LZ的意思无关。
LZ问的问题实际是:直接操作文件,数据是如何写入磁盘的,中间会不会经过内存?而不是是否使用操作系统提供的一些buffer机制。

如果可以直接操作文件,不经过内存,就变成CPU把自己cache(或连CPU自己的cache都不经过)中的内容不经过内存的途径而直接写入磁盘中。现在计算机体系中没有这种实现。

[ 本帖最后由 zx_wing 于 2008-2-3 17:23 编辑 ]
作者: Edengundam    时间: 2008-02-03 17:27
原帖由 zx_wing 于 2008-2-3 17:21 发表

兄台误解LZ意思了。FILE_FLAG_WRITE_THROUGH、FILE_FLAG_NO_BUFFERING其实类似于linux下的O_SYNC和DIRECT_IO参数。
前者是写操作直接flush到磁盘不缓存,后者是不使用文件系统的buffer。这和LZ的意思无关。
所谓直接操作文件,意思是指数据是如何写入磁盘的,中间会不会经过内存?而不是时候使用操作系统提供的一些buffer机制。
如果可以直接操作文件,不经过内存,就变成CPU把自己cache(或连CPU自己的cache都不经过)中的内容不经过内存的途径而直接写入磁盘中。现在计算机体系中没有这种实现。
...


LZ问题在于根本不理解c lib的缓存, OS的缓存, 进程退出时候, c lib语义(APUE有介绍). 如果可以, 当然不经过内核管理的buffer, 这已经是直接操作了. 而且还有裸设备, 说到这些, 磁盘上还有buffer呢. 非要扯什么硬件缓存有意义么??磁盘上还有buffer呢.

LZ搞清楚c lib和内核buffer足矣, 其他的都没用.
作者: zx_wing    时间: 2008-02-03 17:37
原帖由 Edengundam 于 2008-2-3 17:27 发表


LZ问题在于根本不理解c lib的缓存, OS的缓存, 进程退出时候, c lib语义(APUE有介绍). 如果可以, 当然不经过内核管理的buffer, 这已经是直接操作了. 而且还有裸设备, 说到这些, 磁盘上还有buffer呢. 非要扯什 ...

不是我非要扯什么硬件的cache来显得我高深,小弟虽然不才,也没必要靠这些东西彰显自己。
从LZ的问题和他的回复,我认为大部分朋友误解了LZ的意思,包括flw2兄弟。
LZ是给了个例子,没有分配内存,就把一个字符串写到文件里去了,误以为文件操作可以不经过内存,直接写到磁盘中去。
LZ确实没有看到除他程序之外还有其它buffer。但无论是c lib还是os的kenrel,这些缓存都是存在于内存中的。所以我认为给LZ说清楚文件操作要经过内存这个观点就可以了。
作者: Edengundam    时间: 2008-02-03 17:43
原帖由 zx_wing 于 2008-2-3 17:37 发表

不是我非要扯什么硬件的cache来显得我高深,小弟虽然不才,也没必要靠这些东西彰显自己。
从LZ的问题和他的回复,我认为大部分朋友误解了LZ的意思,包括flw2兄弟。
LZ是给了个例子,没有分配内存,就把一个 ...


字符串就在内存啊...所以我认为他不知道究竟怎么写的, 事实上这个过程很可能没有写磁盘的过程. 所有的信息都只是更新到内核的buffer上了. 根本不涉及到底层东西. 因为没有flush(NULL), 内核不一定立即写磁盘的. 所以这个过程不一定有写磁盘这个动作. 从头到尾, 确定性的是信息提交给了内核(write).

此外, 兄弟底层确实很厉害, 不需要谦虚了. 只是还没到磁盘呢, 上面最多是有一个磁盘的读取. 假设之前这个文件没有被cache到内存上, 如果已经操作过了, 这里也不会有. ^^

OS管理资源, DMA作为被管理的资源, 没办法共享给应用程序, 否则就需要在os和app之间进行DMA的管理, 所以app也没有直接访问DMA的能力. 一般直接, 我看作是不经过OS的磁盘管理.
作者: zx_wing    时间: 2008-02-03 17:49
原帖由 Edengundam 于 2008-2-3 17:43 发表


字符串就在内存啊...所以我认为他不知道究竟怎么写的, 事实上这个过程很可能没有写磁盘的过程. 所有的信息都只是更新到内核的buffer上了. 根本不涉及到底层东西. 因为没有flush(NULL), 内核不一定立即写磁盘 ...

关键就在“字符串就在内存啊...”这点,我估计LZ没把这个想到,想岔了
也可能是我们对LZ问题有不同的理解,所以回复侧重面不同,怎么理解就看LZ。
不好意思,刚才激动了,惭愧惭愧
作者: Edengundam    时间: 2008-02-03 17:53
原帖由 zx_wing 于 2008-2-3 17:49 发表

关键就在“字符串就在内存啊...”这点,我估计LZ没把这个想到,想岔了
也可能是我们对LZ问题有不同的理解,所以回复侧重面不同,怎么理解就看LZ。
不好意思,刚才激动了,惭愧惭愧


:wink: 下班了, 明天半天, 就过春节了....
作者: Sorehead    时间: 2008-02-03 18:19
从不同的角度出发看问题,结果就不大一样了。

明天两位继续呀,要不多没意思。
作者: xi2008wang    时间: 2008-02-03 20:44
原帖由 sihan 于 2008-1-31 15:45 发表
一直觉得C不能直接对磁盘文件操作, 而是把文件全部读到内存理, 操作完成后,
在全部写回磁盘。 可是下面这个程序确实可以工作, 不知道哪位高手知道
其内部的实现思路大概是怎么的?

个人觉得:
1.它可以把文件的部分读到内存中.
2.内核缓冲就是磁盘驱动程序提供的,就像其它设备程序程序一样
作者: chenzengjie    时间: 2008-02-03 20:59
这问题就问的不对.
有啥好解释的?
何为"操作文件?" 和语言有关系么?
作者: wind_lq    时间: 2008-02-03 21:27
看了一半,跑题严重~~~
作者: wqch    时间: 2008-02-03 23:07
mmap
作者: Liu_xp2003    时间: 2008-02-03 23:32
就发现34楼的一针见血,点中要害!大部分回帖跟顶楼的问题都不相干...

看了代码,感觉代码的作者对Linux的device输出运用的很有形.顺便提醒一下楼主,这种方式输出可以在文件末尾追加内容,但是不能在文件中间做插入操作.(而是替换)


难得来CU,看到如此跑题的热贴,发点牢骚!
作者: lmt_2000    时间: 2008-02-04 10:16
原帖由 sihan 于 2008-1-31 16:02 发表






那各位的意思是, 直接对磁盘进行操作了?

那如果我想给文件中间插入一段文字, fseek到文件中间, 然后fwrite进入。 这个过程怎么实现的呢?

岂不是要把我的fseek点以后的内容往后移我要fw ...



老大,你不需要移动吧,只需要修改一些文件的定位序列吧!好好看书去吧
作者: sihan    时间: 2008-02-04 15:17
原帖由 Liu_xp2003 于 2008-2-3 23:32 发表
就发现34楼的一针见血,点中要害!大部分回帖跟顶楼的问题都不相干...

看了代码,感觉代码的作者对Linux的device输出运用的很有形.顺便提醒一下楼主,这种方式输出可以在文件末尾追加内容,但是不能在文件中间做插 ...


何谓"运用的很有形"?
作者: Liu_xp2003    时间: 2008-02-04 19:07
原帖由 sihan 于 2008-2-4 15:17 发表


何谓"运用的很有形"?

Linux中device是用file来表示的. 这段代码写的时候用了逆向思维,把file当device输出了.所以看着很有形.
作者: zx_wing    时间: 2008-02-04 20:35
原帖由 Liu_xp2003 于 2008-2-4 19:07 发表

Linux中device是用file来表示的. 这段代码写的时候用了逆向思维,把file当device输出了.所以看着很有形.

-

[ 本帖最后由 zx_wing 于 2008-2-4 20:46 编辑 ]




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2