Linux 文件描述符(open,read,write,lseek,close)
http://blog.csdn.net/linuxmichael/article/details/5156790# Linux系统可以看成是一个由文件组成的系统,在linux系统中,基本上所有的设备,硬件,资源都被看成一个文件,比如,在/dev下面我们可以看到我们的硬盘sda1(我的机器是安装的SCIS硬盘的虚拟机),终端设备ttyn,在/proc目录下面我们可以看到当前的内存信息,ca
http://blog.csdn.net/linuxmichael/article/details/5156790#
Linux系统可以看成是一个由文件组成的系统,在linux系统中,基本上所有的设备,硬件,资源都被看成一个文件,比如,在/dev下面我们可以看到我们的硬盘sda1(我的机器是安装的SCIS硬盘的虚拟机),终端设备ttyn,在/proc目录下面我们可以看到当前的内存信息,cat/proc/meminfo,可以查看CPU的信息: cat /proc/cpuinfo,
上一节已经讲过这个例子,它就是向STDOUT_FILENO这个文件里面写入helloworld
grep –R ’STDOU_FILENO’ /usr/include/
上面的命令就是在/usr/include/这个目录及其子目录里的文件里查找含有STDOUT_FILENO这个字符串的行,找到就打印出来,我们来看结果
只有在条,通过后面的注释可以看出,这个宏定义表示的是标准输出,也就是屏幕,那它为什么是1呢。我们引出了下面的术语,文件描述符(Filedescriotor)
对于内核而言,所有打开文件都由文件描述符引用。文件描述符是一个非负整数。当打开一个现存文件或创建一个新文件时,内核向进程返回一个文件描述符。当读、写一个文件时,用open或creat返回的文件描述符标识该文件,将其作为参数传送给read或write。
有三个特殊的文件描述符,每个进程在创建时,都默认打开三个文件描述符。
standard input(0), standard output(1), standarderror(2)
上面的STDOUT_FILENO就是标准输出文件描述符,它和我们标准C库里的文件指针很相似,只是相似,完全不一样(后面我们有例子来分析两个的不相同之处)。
#include <stdio.h>
#include <fcntl.h>
int main(void)
{
}
下面是执行的结果:
因此我们的猜测是正确的。看下图左边的用户文件描述符表,其实就是当前程序打开的文件的一个数组,其文件描述符就是其下标。
注意下标准输入,标准输出,标准错误输出这三个描述符的定义在<unistd.h>
头文件中,我们可以通过grep来找出来,具体用法见前面。
文件描述符的范围是0 ~ OPEN_MAX
open函数
前面一直有提到这个函数,看其字面意思就是打开一文件的意思。下面看它的具体用法。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int oflag);
int open(const char *pathname, int oflag, mode_t mode) ;
功能:打开文件
返回值:若成功为文件描述符,若出错为- 1 (与fopen区别开NULL,因为他返回的是FILE指针)
pathname是要打开或创建的文件的名字。
oflag参数可用来说明此函数的多个选择项。
对于open函数而言,仅当创建新文件时才使用第三个参数。
用下列一个或多个常数进行或运算构成oflag参数(这些常数定义在<fcntl.h>头文件中):
O_RDONLY
O_RDWR
O_APPEND
O_CREAT
O_EXCL
O_TRUNC
O_NOCTTY
O_NONBLOCK
O_SYNC
上面三个头文件是用open这个系统调用时用到的从这儿也能区分出标准C和系统调用的区别,头文件不一样。
S _ IS U ID
S _ IS G ID
S _ IS V TX
S _IRWXU
S _ IRSR
S _IWUSR
S _IXUSR
S _IRWXG
S _IRGRP
S _IWGRP
S _IXGRP
S _IRWXO
S _IROTH
S _ IWOTH
S _ IXOTH
Open不仅可以打开一个文件,也可以去创建一个文件,这一点要注意下,其实在系统调用函数里面,还有一个真正的创建文件调用函数,creat函数。
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int creat(const char * pathname, mode_t mode) ;
功能:创建一个新的文件。
返回值:若成功为只写打开的文件描述符,若出错为- 1。
注意,此函数等效于:
open (pathname, O_WRONLY | O_CREAT | O_TRUNC, mode) ;
creat的一个不足之处是它以只写方式打开所创建的文件不能读。
read函数
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
功能:
返回:读到的字节数,读不到字节返回0,若count
有多种情况可使实际读到的字节数少于要求读字节数:
—
—
—
—
wirte函数
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
功能;向打开文件写数据。
返回:若成功为已写的字节数,若出错为- 1。
其返回值通常与参数count的值不同,否则表示出错。write出错的一个常见原因是:磁盘已写满,或者超过了对一个给定进程的文件长度限制。
对于普通文件,写操作从文件的当前位移量处开始。如果在打开该文件时,指定了O_APPEND选择项,则在每次写操作之前,将文件位移量设置在文件的当前结尾处。在一次成功写之后,该文件位移量增加实际写的字节数。
lseek函数
每个打开文件都有一个与其相关联的“当前文件偏移量”。它是一个非负整数,用以度量从文件开始处计算的字节数。通常,读、写操作都从当前文件偏移量处开始,并使偏移量增加所读或写的字节数。按系统默认,当打开一个文件时,除非指定O_APPEND选择项,否则该位移量被设置为0。
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int filesdes, off_t offset, int whence) ;
功能:设置文件内容读写位置
返回:若成功为新的文件位移,若出错为- 1。
对参数offset
—
—
—
注意:
可以调用lseek显式地定位一个打开文件。
lseek仅记录当前文件的偏移量,而不会对文件进行I/O操作。
lseek的偏移量可以超过当前文件的字节总数,从而在文件中产生一个hole
看下面的例子:
我们通过ls–hl
close函数
#include <unistd.h>
int close (int
功能:关闭一个打开文件
返回:若成功为0,若出错为- 1
当一个进程终止时,它所有的打开文件都由内核自动关闭。很多程序都使用这一功能而不显式地用close关闭打开的文件。
上面几个系统调用的函数在我们的标准C里基本上都有对应的函数实现,比如fope对应open, fclose对应close,fread对应read, fwrite对应wirte。
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
int main(void)
{
}
分别用标准C的库fopen和系统调用的open打开两个相同的文件,这个文件在我这儿是不存在的,分别打印出它们的出错信息和出错号,和它们的文件描述符和文件指针。下面是结果;
系统调用open打开出错返回-1,而fopen返回类型是指针,因此返回是NULL,其类型是(void*)0,也就是0,
更多推荐
所有评论(0)