Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1408694
  • 博文数量: 120
  • 博客积分: 182
  • 博客等级: 入伍新兵
  • 技术积分: 2278
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-19 16:31
文章分类

全部博文(120)

文章存档

2015年(12)

2014年(13)

2013年(40)

2012年(55)

分类: 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或者设备文件时,该名字被删除,但已经打开这些文件的进程仍然可以使用这些特殊文件。

阅读(1898) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~