Chinaunix首页 | 论坛 | 博客
  • 博客访问: 261623
  • 博文数量: 78
  • 博客积分: 1810
  • 博客等级: 上尉
  • 技术积分: 1039
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-20 11:11
文章存档

2012年(78)

我的朋友

分类: LINUX

2012-03-20 20:01:02

文件编程
 
在进行文件编程前,我想介绍下linux上的文件的一些概述,具体如下所示:

我们知道操作系统的五大供能之一就是对文件的管理.

那么为什么要引入文件管理的功能呢,它的主要任务是什么呢?

在现代操作系统中,要利用大量的程序和数据,由于内存容量有限,且不能长期保存,于是人们想出了把这些数据以文件的形式放在外存中,需要的时候再将它们调入内存-----从此就有了文件系统。它负责管理在外存上的文件,并把对存取,共享和保护等手段提供给用户。这样就方便了用户,保证了文件的安全性,还提高了系统资源的利用率。

1.从系统角度来看,文件系统是对文件存储器空间进行组织和分配,负责文件的存储并对存入的文件进行保护和检索的系统。从用户的角度看,文件系统的主要目的是实现了对文件的按名存取。

2.由于要存储大量的文件,所以如何对这些文件实施有效的管理呢------>所以人们又引入了目录,通过目录来对文件进行管理。

---------------------------------------------------

现在我们来看看Linux中如何实现文件系统的。

二.Linux中的文件系统

文件系统指文件存在的物理空间,Linux 系统中每个分区都是一个文件系统,都有自己的目录层次结构。Linux 会将这些分属不同分区的、单独的文件系统按一定的方式形成一个系统的总的目录层次结构。

在原理课中,我们知道系统是靠FCB来管理文件的,而具体到了Linux操作系统下时,它是靠index node来管理文件的。

1.Linux中的文件系统

1>Linux是一个安全的操作系统,它是以文件为基础设计的。从此处就可以看出“Linux下皆文件”。Linux中的文件子系统主要用于管理文件存储空间的分配,文件访问权限的维护,对文件的各种操作。

a.用户可以使用shell 命令对文件进行操作,但在功能上受到一定的限制。

b.程序员可以通过系统调用或C语言的库函数对文件进行操作。

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

3>目录也是一种文件,称为目录文件。目录文件的内容时该目录的目录项,目录项时该目录下的文件和目录的相关信息。当创建一个新目录时,系统将自动创建两个目录项:. 和..

我们可以用命令来体验一下它的实 现 :

think@ubuntu:~$ mkdir tiger
think@ubuntu:~$ ls -al tiger
drwxr-xr-x  2 think think 4096 2010-11-16 13:11 .
drwxr-xr-x 51 think think 4096 2010-11-16 13:11 .. 
mkdir tiger 是创建一个tiger的目录 ,然后再用命令ls -al tiger来看一下tiger目录的详细信息。可以看见系统将 自动创建两个目录项:. 和   ..     

(如果对ls 命令不熟悉的话可以看我的小白学Linxu之常见命令有具体解释 )

4>Linux 采用的是标准目录结构---树型结构无论操作系统管理几个磁盘分区,这样的目录树只
有一个(这样设计的原因是为了:有助于对系统文件和不同的用户文件进行统一管理)

说明:

我们大加熟知的windows操作系统它是有几个分区就有几个树目录。

例如:我们有C,D,E,3个盘,那么就有3个树目录。

5>在Linux安装的时候,安装程序就已经为用户创建了文件系统和完整而固定的目录组成形式,并指定了每个目录的作用和其中的文件类型。

a.我们还是从用命令体验以下把:

首先输入 cd /(切换到根目录下)

然后 在输入  ls (就可以看到Linux下一些主要的目录)

think@ubuntu:~$ cd /
think@ubuntu:/$ ls
bin    etc         initrd.img.old  lost+found  proc     srv    usr
boot   home        lib             media       root     sys    var
cdrom  host        lib32           mnt         sbin     think  vmlinuz
dev    initrd.img  lib64           opt         selinux  tmp    vmlinuz.old

b.现在看一下这些目录的功能吧

/bin 二进制可执行命令 
/dev 
设备特殊文件
 
/etc 
系统管理和配置文件
 
/home 
用户主目录的基点,比如用户user 的主目录就是/home/user 。
 
/lib 
标准程序设计库,又叫动态链接共享库。
 
/sbin 
系统管理命令,这里存放的是系统管理员使用的管理程序
 
/tmp 
公用的临时文件存储点
 
/root 
系统管理员的主目录

/mnt 
用户临时安装其他文件系统的目录。 
/proc 
虚拟的目录,是系统内存的映射。可直接访问这个目录来获取系统信息。
 
/var 
某些大文件的溢出区,例如各种服务的日志文件
 
/usr 
最庞大的目录,要用到的应用程序和文件几乎都在这个目录下,相当于DOS操作系统C盘目录下的windows。

说明:

etc针对的是系统管理员。

home是针对的是我们用户。

dev存放是设备信息。

proc存放的是内核信息

usr存放的是系统调用 

 

2.Linux中的文件分类

1>普通文件 

计算机用户和操作系统用于存放数据、程序等信息的文件。一般都长期地存放在外存储器(磁盘、磁带等)中。常规文件一般又分为文本文件和二进制文件。

2>目录文件

Linux 文件系统将文件索引节点号和文件名同时保存在目录中。所以,目录文件就是将文件的名称和它的索引节点号结合在一起的一张表。目录文件只允许系统进行修改。用户进程可以读取目录文件,但不能对它们进行修改。

3> 设备文件

Linux 把所有的外设都当作文件来看待。每一种I/O 设备对应一个设备文件,存放在/dev 目录中,如行式打印机对应/dev/lp 文件,第一个软盘驱动器对应/dev/fd0 文件。

4> 管道文件

主要用于在进程间传递数据。管道是进程间传递数据的“媒介”。某进程数据写入管道的一端,另一个进程从管道另一端读取数据。Linux 对管道的操作与文件操作相同,它把管道做为文件进行处理。管道文件又称先进先出(FIFO) 文件。

5> 链接文件

又称符号链接文件,它提供了共享文件的一种方法。在链接文件中不是通过文件名实现文件共享,而是通过链接文件中包含的指向文件的指针来实现对文件的访问。使用链接文件可以访问常规文件,目录文件和其它文件。

那么具体在Linux中一个文件的类型都底是怎么表示的呢

来实践以下看看:

在终端输入命令: ls -l 可以看一下

--------------------------------------------------------------------------------------------

think@ubuntu:~$ ls -l
drwx------ 19 think think     4096 2010-10-30 11:28 code

-rwxr-xr-x  1 think think     1152 2010-11-01 10:22 deadlock.c

lrwxrwxrwx   1 root  root     33 2010-09-17 02:23 initrd.img.old -> boot/initrd.

crw-rw-rw-   1 root root      1,   5 2010-11-16 08:59 zero

brw-rw----   1 root disk      8,   0 2010-11-16 08:59 sda

-----------------------------------------------------------------------------------

说明:

第一字母就表示了这个文件的类型:

d: 表示目录

- :表示文件

l:表示链接文件

b:表示块设备文件

c: 表示字符设备文件

p: 表示管道文件

 
现在我们就开始具体的文件编程吧!!
linux中文件编程可以使用两种方法:1.Linux系统调用     2.C语言库函数。系统调用是基于linux系统的,它不能跨系统使用。c语言库函数在各个系统都能使用。
A.下面先介绍基于系统调用的文件编程

1.文件的创建.

int creat(const char *filename,mode_t mode)
filename:要创建的文件名(包含路径,缺省为当前路径)
mode:创建模式

常见创建模式:
S_IRUSR 可读
S_IWUSR 可写
S_IXUSR 可执行
S_IRWXU可读、写、执行

这几个模式怎么记忆呢?可以按照它的英文全称记忆。如S_IRUSR: Set ID Read ,这是设置用户的操作模式,后面再加一个USR。l

除了可以使用上述宏以外,还可以直接使用数字来表示文件的访问权限:
可执行 -> 1
可写 -> 2
可读 -> 4

上述值的和,如可写可读 -> 6
无任何权限 -> 0

各自权限分别对应了二进制的不同位数。由左到右(高位到低位)对应的顺序为  读--写--执行,我们可以把它理解为修改一个程序代码的过程记忆,即先阅读代码(读),改代码(写),运行代码(执行)。

实例代码:

  1. "font-family:'Microsoft YaHei';font-size:18px;">#include    
  2. #include    
  3.   
  4. #include    
  5. #include    
  6. #include    
  7.   
  8. void  create_file(char *filename){   
  9.       
  10.     if(creat(filename,0755)<0){   
  11.         printf("create file %s failure!\n",filename);   
  12.         exit(EXIT_FAILURE);   
  13.     }else{   
  14.         printf("create file %s success!\n",filename);   
  15.     }   
  16. }   
  17.   
  18. int main(int argc,char *argv[]){   
  19.     int i;   
  20.     if(argc<2){   
  21.         perror("you haven't input the filename,please try again!\n");   
  22.         exit(EXIT_FAILURE);   
  23.     }   
  24.   
  25.     for(i=1;i
  26.         create_file(argv[i]);      
  27.     }   
  28.   
  29.     exit(EXIT_SUCCESS);   
  30. }  

在Linux系统中,所有打开的文件都对应一个文件描述符。文件描述符的本质是一个非负整数。当打开一个文件时,该整数由系统来分配。文件描述符的范围是0 ~OPEN_MAX 。早期的UNIX版本OPEN_MAX =19,即允许每个进程同时打开20个文件,现在很多系统则将其增加至1024。

2.文件打开

int open(const char *pathname, int flags)
int open(const char *pathname, int flags,mode_t mode)
pathname:要打开的文件名(包含路径,缺省为当前路径)
flags:打开标志

常见的打开标志:
O_RDONLY 只读方式打开
O_WRONLY 只写方式打开
O_RDWR 读写方式打开
O_APPEND 追加方式打开
O_CREAT 创建一个文件
O_NOBLOCK 非阻塞方式打开

如果使用了O_CREATE标志,则使用的函数是:
int open(const char *pathname,int flags,mode_t mode);
这时需要指定mode来表示文件的访问权限。

当我们操作完文件以后,需要关闭文
件:
int close(int fd)

fd为文件描述符,来自与creat或者open函数的返回值。

3.系统调用-读
int read(int fd, const void *buf, size_t length)
功能:
从文件描述符fd所指定的文件中读取length个字节到buf所指向的缓冲区中,返回值为实际读取的字节数。

4.系统调用-写
int write(int fd, const void *buf, size_t length)
功能:
把length个字节从buf指向的缓冲区中写到文件描述符fd所指向的文件中,返回值为实际写入的字节数。

5.系统调用-定位
int lseek(int fd, offset_t offset, int whence)
功能:
将文件读写指针相对whence移动offset个字节。操作成功时,返回文件指针相对于文件头的位置。

whence可使用下述值:
SEEK_SET:相对文件开头
SEEK_CUR:相对文件读写指针的当前位置
SEEK_END:相对文件末尾
offset可取负值,表示向前移动。例如下述调用
可将文件指针相对当前位置向前移动5个字节:
lseek(fd, -5, SEEK_CUR)

由于lseek函数的返回值为文件指针相对于文件头的位置,因此下面调用的返回值就是文件的长度:
lseek(fd, 0, SEEK_END)

6.有时我们需要判断文件是否可以进行某种操作(读,写等),这时可以使用access函数:
int access(const char*pathname,int mode)
pathname:文件名称
mode:要判断的访问权限。可以取以下值或者是他们的组合。

R_OK:文件可读,W_OK:文件可写,
X_OK:文件可执行,F_OK文件存在。
返回值:当我们测试成功时,函数返回0,否则如果一个条件不符时,返回-1。

B.下面先介绍基于C库调用的文件编程

1.     FILE * fopen(const char *filename,const char *mode)

       mode:

                r,rb   //只读方式打开

                w,wb  //只写方式打开,如果文件不存在,则创建该文件

                a,ab  //追加方式打开,如果文件不存在,则创建该文件

               

                r+,r+b,rb+  //读写方式打开

                w+,w+b,wh+  //读写方式打开,如果文件不存在,则创建该文件

                a+,a+b,ab+  //读和追加方式打开,如果文件不存在,则创建该文件

         注:b用于区分二进制文件和文本文件,这一点在DOS,Windows系统中是有区分的,

                但linux不区分二进制文件和文本文件。

2.库函数-读

  size_t fread(void *ptr,size_t size,size_t n,FILE * stream)

       //从stream指向的文件中读取n个字段,每个字段为size字节,并将读取的数据放入ptr

          所指的字符数组中,返回实际已读取的字节数。

3.库函数-写

  size_t fwrite(void *ptr,size_t size,size_t n,FILE * stream)

       //从缓冲区ptr所指的数组中把n个字段写到stream指向的文件中,每个字段长为size

        个字节,返回实际写入的字段数。

4.库函数--读字符

       int fgetc(FILE *stream)

例:

  #include

  main()

  {

     FILE *fp;

     char ch;

     if((fp=fopen("c1.txt","rt"))==NULL)

     {

         printf("\nCannot open file strike any key exit!")

          getch();

          exit(1);

     }

    ch=fgetc(fp);

    while(ch!=EOF)

    {

         putchar(ch);

         ch=fgetc(fp);

     }

    fclose(fp);

  } 

 

5.库函数--写字符

     int fputc(int c,FILE *stream)

       //向指定的文件中写入一个字符

例:

     #include

     main()

     {

          FILE *fp;

          char ch;

          if((fp=fopen("string",wt+)==NULL)

          {

                printf("Cannot open file,strike any key exit!\n");

                getch();

                exit(1);

          }

          printf("input a string:\n");

          ch=getchar();

          while(ch!='\n')

          {

             fputc(ch,fp);

             ch=getchar();

          }

         printf("\n");

         fclose(fp);

     }

  

6.库函数--格式化读

     fscanf(FILE *stream,char *format[,argument...])

             //从一个流中进行格式化输入

例:

   #include

   #include

   int main()

   {

          int i;

          printf("input an integer:\n")

          if(fscanf(stdin,"%d",&i))

              printf("the integer read was: %i\n",i);

          return 0;

   } 

7.库函数--格式化写

  int fprintf(FILE *stream,chr* format[,argument,...])

      //格式化输出到一个流中

8.库函数--定位

    int fseek(FILE *stream,long offset,int whence)

             //和系统调用一样的

9.路径获取

         char *getcwd(char *buffer,size_t size)

             //提供一个size大小的buffer,getcwd会把当前的路径名copy到buffer中,如果

               buffer太小,函数会返回-1。

例:

     #include

    main()

   {

      char buf[80];

      getcwd(buf,sizeof(buf));

      printf("current working directory:%s\n",buf);

    }

另还有fputs fgets,feof等函数,参考相关书籍

 

 创建目录:

   #include

   int mkdir(char *dir,int mode)

    //创建一个新目录。

     返回值0表示成功,-1表示出错。


 

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