文件操作

文件操作 
在OS中,几乎毫不例外地是通过文件系统来组织和管理在计算机中所存储的大量程序和数据的;或者说,文件系统的管理功能,是通过把它所管理的程序和数据组织成一系列文件的方法来实现的。那么在Linux下的文件结构和文件操作是如何进行的?

1.Linux的文件结构

   Linux是一个安全的操作系统,它是以文件为基础而设计的。Linux的文件子系统主要用于管理文件存储空间的分配,文件访问权限的维护,对文件的各种操作用户可以使用命令对文件进行操作,但在功能上受到一定的限制。

    文件主要包括两方面的内容:一是文件本身所包含的数据;另外就是文件的属性,包括文件的访问权限,所有者,文件大小,创建 日期等。

    目录也是一种文件,称为目录文件。目录文件的内容是该目录的目录项,目录项是该目录下的文件和目录的相关信息。当创建一个新目录时,系统将自动创建两个目录项:.和 ..,在shell下输入ls-a可以将其显示在终端上,前者代表当前目录,后者代表当前目录的父目录。对于根目录,两者是相同的。
     在shell下输入cd/切换到根目录,再输入ls可以查看根目录下的目录情况,一般的Linux发行版本都含有如下几个目录。
    /bin用于存放普通用户可执行的命令,系统中的任何用户都可以执行该目录中的命令,如ls,cp,mkdir等命令。
    /boot linux的内核及启动系统是所需要的文件,为保证启动文件更加安全可靠,通常把该目录存放在独立的分区上。
    /dev设备文件的存储目录,如硬盘,光驱等。
    /etc用于存放系统的配置文件。
    /home普通用户的主目录,每个用户在该目录下都有一个与用户同名的目录。
    /lib用于存放各种库文件。
    /proc该目录是一个虚拟文件系统,只有在系统运行时才存在。通过访问该目录下的文件,可以获取系统的状态信息并且修改某些系统的配置信息,可以简单使用cat,strings,命令来查看这些信息,如在shell下输入cat/proc/meminfo可以获取系统内存的使用情况,输入man proc可获得关于proc详细的信息。
    /root超级用户root的主目录。
    /sbin存放的是用于管理系统的命令。
    /tmp临时文件目录。
    /usr用于存放系统应用程序及相关文件,如说明文档,帮助文件等。
    /var用于存放系统中经常变化的文件,如日志文件,用户邮件等。

2.Linux的文件系统模型

    数据或者说文件归根结底是要存储在物理磁盘上的,操作系统通过文件系统可以方便地对磁盘上的文件进行管理。
    对物理磁盘的访问都是通过设备驱动程序来进行的,而对设备驱动访问则有两种途径:一种是通过设备驱动本身提供的接口;另一种是通过虚拟文件系统提供给上层应用程序的接口。第一种方式能够让用户进程绕过文件系统直接读写磁盘上的内容,这使得操作系统带来了很大的不稳定性,因此大部分操作系统包括Linux都是使用虚拟文件系统来访问设备驱动的。

3.文件的分类

Linux中的包含以下几种的文件类型。 
(1)普通文件:这是最常见的文件类型,这种文件包含了某种形式的数据。 
(2)目录文件:目录文件就是目录,目录有访问权限,目录文件的内容就是该目录下的文件和子目录的信息。 
(3)字符特殊文件:用于表示系统中字符类型的设备。 
(4)块特殊文件:用于表示系统的中块类型的设备。 
(5)FIFO:这种类型文件用于进程间通信,即为管道。 
(6)套接字:主要用于网络通信,套接字也可以用于一台主机上的进程之间的通信。 
(7)符号连接:指向另一个文件,是另一个文件的引用。

4.文件的输入输出

    对于用户使用文件无非就是进行这些操作,即:create,open,close,read,write和lseek等。而对于内核而言,所有打开的文件都由文件描述符标识,在对一个文件进行首先是打开的操作,此时需要调用open或者create函数来打开文件。具体来说一下文件的读写及文件读写指针的移动。

4.1文件的读写

<1>read函数

    read函数系统调用用来打开的文件中读取数据,在shell下输入“man 2 read”可获取其函数原型如下:
 
 
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
    函数中各参数的含义是:从文件描述符fd所指向的文件中读取count个字节的数据到buf所指向的缓冲区。若参数count为0,则read()不会读取数据,只返回0。返回值表示实际读取到的字节数。如果返回0,表示已到达文件尾或是无可读取的数据,此外文件读写指针会随读取到的字节移动。

<2>write函数

     write系统调用用来将数据写入已打开的文件中,在shell下输入“man 2 write”可以获取该函数原型:


#include <unistd.h> 
ssize_t write(int fd, const void *buf, size_t count); 

函数中各参数的含义是:将buf所指向缓冲区中的count个字节数据写入到由文件描述符fd所指示的文件中。当然,文件读写指针也会随之移动。如果调试成功,write()会返回写入的字节数。有错误返回-1。

<3>文件读写指针的移动

    lseek系统调用用移动文件读写指针的位置,在shell下输入“ man lseek”可读取其函数原型:
 
 
#include <unistd.h>
#include<sys/types.h>
off_t_lseek(int fildes,off_t offset,int whence);
   每一个已打开的文件都有一个读写位置,当打开文件时通常读写位置是指向文件开头,若是以添加的方式打开文件(调用open函数是使用了O_APPEND),则读写位置会指向文件尾。当调用read()或write()时,读写位置会随之增加,lseek()便用来控制文件的读写位置。参数fildes为已打开的文件描述符,参数offset为根据参数whence来移动读写位置的位移数。
   一下是lseek的几种常用方法。
  将文件读写指针移动到文件开头:
 
 
lseek(int fildes,0,SEEK_SET);
 将文件读写指针移动到文件结尾:
 
 
lseek(int fildes, 0,SEEK_END);
获取文件读写指针当前的位置(相对于文件开头的偏离):
 
 
lseek(int fildes, 0,SEEK_CUR);

以下代码是文件读写和文件读写指针的移动操作过程。

 
 
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<errno.h>
#include<stdlib.h>
#include<string.h>
 
#define bool _Bool
#define false 0
#define true 1
#define _bool_true_false_are_defined 1
void my_err(const char *err_string, int line)
{
fprintf(stderr,"line:%d",line);
perror(err_string);
exit(1);
}
/*自定义的错误处理函数*/
 
/*自定义的读取数据函数*/
int my_read(int fd){
int len;
int ret;
int i;
int _LINE_;
char read_buf[64];
 
/*获取文件长度并保持文件读写指针在文件开始处*/
if(lseek(fd,0,SEEK_END) ==-1){
my_err("lseek",__LINE__);
}
if((len=lseek(fd,0,SEEK_CUR))==-1)/*将文件读写指针移动到文件结尾*/{
my_err("lseek",__LINE__);
}
if((lseek(fd,0,SEEK_SET))==-1)/*获取文件读写指针当前的位置*/{
my_err("lseek",__LINE__);
}
printf("len:%d",len);
/*读数据*/
if((ret = read(fd,read_buf,len)) <0){
my_err("read",__LINE__);
}
/*打印数据*/
for(i=0;i<len;i++){
printf("%c",read_buf[i]);
}
printf("\n");
return ret;
}
int main()
{
int fd;
char write_buf[32]="Hello World!";
 
/*在当前目录下创建文件example_63.c*/
if((fd=creat("example_63.c",S_IRWXU)) == -1){
//if((fd=open("example_63.c", O_RDWR|O_CREAT|O_TRUNC, S_IRWXU)) == -1){
my_err("open",__LINE__);
}
else{
printf("create file success\n");
}/*写数据*/
if (write(fd,write_buf,strlen(write_buf)) != strlen(write_buf)){
my_err("write",__LINE__);
}
my_read(fd);
/*演示文稿的间隔*/
printf("/*-------------------*/\n");
if(lseek(fd,10,SEEK_END) == -1){
my_err("lseek",__LINE__);
}
if(write(fd,write_buf,strlen(write_buf)) != strlen(write_buf)){
my_err("write",__LINE__);
}
my_read(fd);
close(fd);
return 0;
}

程序运行结果:

 
 
0000000 H e l l o W o r l d !
0000014

程序说明: 
程序中首先在当前目录下创建了文件example_63.c,注意open的参数,O_RDWR|O_CREAT|O_TRUNC表示以可读写方式创建一个文件,若该文件名存在,则覆盖,然后使用write系统调用,向新创建的文件写入数据。函数my_read先测试由fd传入的文件描述符对应的文件的长度,然后读出全部数据,最后打印出来。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值