分类: LINUX
2013-01-22 16:24:01
最近在复习文件操作以及文件系统的基础知识,将其整理成笔记,以后看的时候更方便些。
首先,说说文件,什么是文件?在linux中,文件是一种线性的字节流。这些字节对于操作系统来说并不重要,但是对用户而言却是至关重要的。这么说其实还是有点泛泛的,但是目前只要知,道就可以了,先不去深究。文件主要内容包括两方面:文件本身所包含的数据和文件的属性;其中文件的属性也称作元数据,包括文件的大小、所有者、访问权限、创建日期等等。
在linux中,一切皆为文件。因此,目录也是一种文件,称为目录文件。文件被组织成多级目录系统。目录包含文件,用来维护文件系统的结构。目录文件的内容是该目录的目录项,而目录项则是该目录下的文件和目录的相关信息。一般的linux发行版中都包含如下目录:
1 /bin 用于存放普通用户可执行的命令,如ls,cp,mkdir等等;
2 /boot 存放linux内核以及系统启动时所需的文件(为了保证文件的启动更加安全可靠,常常吧该目录存放在独立的分区);
3 /dev 该目录下存放设备文件的相关信息;
4 /etc 用于存放系统的配置文件,比如说用户账号以及密码信息存放于配置文件/etc/password和/etc/shadow中;
5 /home 是普通用户的主目录;
6 /lib 该目录下存放各种库文件;
7 /proc 这是个虚拟文件系统,只有当系统运行时才存在;,它里面包含了一些目录和虚拟文件,通过访问该目录下的文件,可以获取系统的状态信息并修改某些系统的配置信息。在shell下输入man proc可以获得关于proc的详细信息;
8 /root 这是超级用户root的主目录;
9 /sbin 存放用于管理系统的命令;
10 /tmp 这是个临时文件目录,用于存放系统或程序产生的临时文件;
11 /usr 该目录下存放系统的应用程序及相关文件;
12 /var 用于存放系统中经常变化的文件,比如日志文件、用户邮件等等。
接下来将常用的文件操作相关的函数一一道来:
(1)open函数
open系统调用用来打开一个或者创建一个文件,在shell下输入“man 2 open”可以获得还函数的原型:
#include
#include
#include
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
其中第一个参数pathname是要打开的文件或者要创建的含路径的文件名,第二个参数flags表示打开文件的方式。flags的取值:
O_RDONLY 以只读方式打开文件;
O_WRONLY 以只写方式打开文件;
0_RDWR 以可读可写方式打开文件。
O_CREAT 若文件不存在则自动建立该文件,只有此时,才需要用到第三个参数mode,以说明新文件的存取权限;
O_EXCL 若O_CREAT已经被设置,此指令会去检查文件是否存在。若文件不存在则创建该文件,若文件存在则导致打开文件出错;
O_TRUNC 若文件存在并且以可写的方式打开,此时标志会将文件长度清零,即原文件中保存的数据将丢失,但文件的属性保持不会变;
O_APPEND 所写入的数据会以追加的方式加入到文件后面;
O_SYNC 以同步的方式打开文件,任何文件的修改都会阻塞直到物理磁盘上的数据同步以后才返回;
O_NOFOLLOW 若参数pathname所指的文件为一个符号链接,则会令文件打开失败;
O_NONBLOCK或O_NDELAY 以非阻塞的方式打开文件,对于oen以及随后的对该文件的操作,都会立即返回。
注:当且仅当第二个参数使用了O_CREAT时,需要使用第三个参数mode来说明文件的存取权限。值得一提的是新文件的实际存取权限是moode与umask按照(mode&~umask)运算以后的结果。
成功调用open会返回一个文件描述符,若有错误发生返回-1,并把错误代码赋给errno。
(2)creat函数
可以通过creat系统调用开创建一个新文件,在shell下输入“man 2 creat”获取该函数原型:
#include
#include
#include
int creat(const char *pathname, mode_t mode);
其中第一个参数pathname是要打开或者要创建的文件名,若pathname指向的文件不存在,则创建一个新文件;若pathname创建的文件存在,则创建的新文件覆盖原来的文件。mode与open函数中的相同。
成功调用creat会返回一个文件描述符,若有错误发生返回-1,并把错误代码赋给errno。
注:creat只能以只写的方式打开创建的文件,它无法创建设备文件,设备文件的创建要使用mknod.
(3)close函数
close系统调用用来关闭一个已经打开的文件,在shell下输入“man 2 close”获取其原型:
#include
int close(int fd);
close函数只有一个参数,此参数表示需要关闭的文件的文件描述符,该文件描述符是由open或creat函数得到的。调用creat成功时返回0,发生错误时返回-1并设置错误代码。
注:close函数调用成功时并不保证数据能全部协会硬盘。
(4)read函数
read系统调用用来从打开的文件中读取数据,在shell下输入“man 2 read”获得其原型:
#include
ssize_t read(int fd, void *buf, size_t count);
含义:从文件描述符fd所指的文件中读取count个字节的数据到buf所指向的缓存中。若参数count为0,则read()不会读取数据,只返回0。返回值表示实际读取到的字节数,若返回0,表示已到达文件末尾或者无数据可读。文件读写指针会随着读取到的字节移动。若read()顺利返回实际读取到的字节数最好能将返回值与参数count做比较。当有错误发生时返回-1,错误代码存放在errno中。
(5)write函数
write系统调用用来将数据写入到已经打开的文件中,在shell下输入“man 2 write”获取到其函数原型:
#include
ssize_t write(int fd, const void *buf, size_t count);
含义:将buf所指向的缓冲区中的count个字节数据写入到由文件描述符fd所指向的文件中。若调用成功,write()会返回写入的字节数,当有错误发生时则返回-1,错误代码存入errno中。
(6)lseek函数
lseek系统调用用来移动文件读写指针的位置,在shell下输入“man 2 lseek”获取其函数原型:
#incldue
#include
off_t lseek(int fildes,off_t offset, int whence);
每个已经打开的文件都有一个读写位置,当打开文件时通常读写位置是指向文件开头的,若是以添加的方式打开一个文件(调用open时使用了O_APPEND),则读写位置会指向文件末尾。当调用read()或者write()时,读写位置会随之增加,lseek()便用来控制该文件的读写位置。参数fildes为已经打开的文件描述符,参数offset为根据参数whence来移动读写位置的位移数。参数whence有如下三种取值:
① SEEK_SET 从文件开始处计算偏移量,文件指针到文件开始处的距离为offset;
② SEEK_CUR 从文件指针的当前位置开始计算偏移量,文件指针值等于当前指针值加上offset的值。offset允许取负值;
③ SEEK_END 从文件结尾处开始计算偏移量,文件指针的值等于当前指针的值加上offset的值。offset允许取负值。
lseek的雨中常用方法:
① lseek(int fildes, 0, SEEK_END);/*将文件读写指针移到文件开头*/
② lseek(int fildes, 0, SEEK_CUR);/*将文件读写指针移到当前位置*/
③ lseek(int fildes, 0, SEEK_END);/*将文件读写指针移到文件末尾*/
注:linux不允许lseek()对tty设备进行操作。对于普通文件,其偏移量必须是非负值,lseek仅仅将当前的文件偏移量记录在内核中,并不引起任何的I/O操作。
(7)rename函数
rename系统调用用来修改文件名或者文件的位置,在shell下输入“man 2 rename”获取其函数原型:
#include
int rename(const char *oldpath, const char *newpath);
含义:rename会将参数oldpath所指定的文件名改为参数newpth所指定的文件名称。若newpah所指定的文件已经存在,则原文件会被删除。执行成功返回0,有错误发生时返回-1,错误代码存入errno中。
(8)文件的删除函数
其实文件的删除可以用unlink系统调用,目录文件的删除则需要使用rmdir系统调用。而一个普通的既能删除文件又能删除目录的系统调用是remove,remove系统调用实际上是在其内部封装了unlink和rmdir,当需要删除的是文件时,调用unlink;当需要删除的是目录时,调用rmdir,在shell下输入“man 2 unlink”和“man 2 remove”获取它们的函数原型:
#include
int unlink(cont char *pathname);
int remove(const char *pathname);
remve实际上封装了unlink,unlink系统调用实现从文件系统上删除一个文件。若文件的链接数为0,且没有进程打开这个文件,则文件被删除并且其占用的磁盘空间被释放。若文件的链接数为0,但是有进程打开了这个文件,则文件暂时不能被删除,直到所有打开该文件的进程都结束才能删除该文件,利用这点可以确保即使程序崩溃,它所创建的临时文件也不会遗留下来。若参数pathname指向一个链接文件,则该链接文件被删除。若参数pathname指向一个符号链接,则该链接被删除。若参数pathname指向一个socket文件、FIFO或者设备文件时,该名字被删除,但已经打开这些文件的进程仍然可以使用这些特殊文件。