分类: C/C++
2013-08-23 20:10:20
1.标志分为:文件状态标志GETFL 文件描述符标志GETFD
这三种值互斥 — 一个文件只能有这三种值之一。 )因此首先必须用屏蔽字 O_ACCMODE取得存取方式位,然后将结果与这三种值相比较。
2.linux下管道的执行顺序不同。比如 a | b 大多数貌似是shell → fork → exec b → fork exec a. a 标准输入为b标准输出。(这里不同的继承顺序决定于不同的实现,见APUE9.9)
3.打开文件/dev/fd/n等效于复制描述符 n (假定描述符n是打开的)。
4.read和write没有缓冲功能指的是在用户空间,实际上在进行该系统调用的时候在系统内是有缓冲区的。(不然一个个往磁盘上写啊)
fread和fopen的优势在于,函数自动在用户空间提供缓冲区,减少了系统调用的次数,也就减少了管态和模态的切换时间。
第一个问题:二进制文件和文本文件。
第一,以二进制和文本方式打开在linux下并无区别,在dos和win下有区别,因为\r\n和\n的切换。
在linux内核看来,文本文件和二进制文件是一样的。
只不过文本方式通常存的都是ascii之类的文字,所有他们的字节长度有一定规范,比如A是65,转为二进制01000001。那么就保存为01000001。01000001 01000001就是A A。但是二进制,都入的字节不一定按照这样解析。比如,我自己的程序把这个二进制看作是用户的权限。
从这个角度看,带有BOM和UTF-8的都不属于文本文件。
什么是BOM,通过在文件的最开始,保存几个无法打印的字符,来识别该文件的编码格式,就是BOM(这些字符通常在各个编码都无法打印,比如空字符)。那么这些字符就起到了其他的作用,而且,UTF-8还属于变长型编码,不能简单的按照ASCII解码。
还有个问题,使用C编程的时候,printf输出文字,默认的是ASCII,如果想输出utf-8怎么办?
第二个问题:
linux下如何识别不同文件的编码格式?
在windows下生成的文件会有BOM进行辅助识别。但是linux下却没有。那linux如何识别呢?一般的识别算法都是针对普遍情况,对于特定的构造的文件可能无法识别。
比如发现一篇文章的字符编码,抽查了n次,满足UTF-8,UNICODE,GBK编码格式,
就继续,知道发现两个不满足。
UNICODE
UTF-8
00000000 - 0000007F 0xxxxxxx
00000080 - 000007FF
110xxxxx 10xxxxxx
00000800 - 0000FFFF 1110xxxx 10xxxxxx 10xxxxxx
00010000 - 001FFFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
00200000
- 03FFFFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
04000000
- 7FFFFFFF 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
比如UTF-8,第一个字节如果前三位是110,第二个前两位一定是10。不满足就不是UTF-8。可以在系统可识别的编码中使用排除法。
在linux下默认的编码格式是UTF-8,win下GB2312。在命令行输入文字,就是UTF-8的。而且,剪切版里也是UTF-8。在页面复制的时候,将文字转码为UTF-8,如果输出到gbk的文件中需要再转码一次。
在这个过程中,为了察看win下和linux下utf-8的文件区别,使用了od命令,这个命令可以用来查看文件的16进制的形式。
od -x 文件 查看16进制
file命令查看编码格式
补充:
GB2312:
ASCII 128个字符,首位为0
一个小于127的字符的意义与原来相同,但两个大于127的字符连在一起时,就表示一个汉字,前面的一个字节(他称之为高字节)从0xA1用到 0xF7,后面一个字节(低字节)从0xA1到0xFE,这样我们就可以组合出大约7000多个简体汉字了
GBK:后来还是不够用,于是干脆不再要求低字节一定是127号之后的内码,只要第一个字节是大于127就固定表示这是一个汉字的开始,不管后面跟的是不是扩展字 符集里的内容。结果扩展之后的编码方案被称为 GBK 标准
第三个问题:
空洞文件的存储问题,是像普通文件+0一样存储么?
使用o_append标志无法形成空洞。
因为这个标志意味着追加到尾端,所以偏移量总是指向文件末尾。
而且lseek也不返回错误。
U N I X 提供了一种方法使这种操作成为原子操作,其方法就是在打开文件时设置
O _ A P P E N D标志。正如前一节中所述,这就使内核每次对这种文件进行写之前,都将进程的当前位移量设置到该文件的尾端处,于是在每次写之前就不再需要调用 lseek。可以读,但是写前会原子调用lseek空洞文件
100006字节 包括100000字节的空洞 ,占用了12个存储块 ,一块是4K(df命令)
可见空洞有一份没有保存,
如果使用cat test1,会把空洞填充的0当作实际的0数据复制,不再是空洞。
而cp则不会。因为cat把数据当作0输出
注:
可能是由于ubuntu win安装的原因,
sudo tune2fs -l /dev/sda1 失败
后来df发现使用的是/dev/loop0,sudo tune2fs -l /dev/loop0
第四个问题:O_SYNC、fsync,fdatasync的区别。
O_SYNC标志是文件描述符标志在 UNIX中,通常write只是
将数据排入队列,而实际的I/O操作则可能在以后的某个时刻进行。数据库系统很可能需要使用
O_SYNC,这样一来,在系统崩溃情况下,它从write返回时就知道数据已确实写到了磁盘上。
普通的write加入队列直接返回。
比较O_SYNC,fsync,fdatasync等的区别和效率
http://blog.csdn.net/cindy9902/article/details/5827183
http://blog.csdn.net/wangfeng2500/article/details/8288775
数据库总能用到上面的函数。
第五个问题:
多个进程写同一个文件如何管理
http://blog.chinaunix.net/uid-24585858-id-2856540.html
第六个问题:如何实现fread的缓冲功能: