免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4191 | 回复: 1
打印 上一主题 下一主题

Linux系统调用(一)—文件读写操作 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-08-14 20:11 |只看该作者 |倒序浏览
这段时间正在研究LINUX的系统调用,用于本人喜欢把学过的东西整理起来,然后系统的去记忆。现在拿出来和大家分享。希望对像我这样的初学者有所帮助。本文大部分内容都是<Unix\Linux编程实践教程> 这本书里的,加上一些自己的理解.

1.
名称:        open
目标:         打开一个文件。
头文件:        #include < fcntl.h>
函数原形:        int fd=open(char * name,int how)
参数:         name  文件名
             how   打开模式
返回值:         -1     遇到错误
            int    打开成功,返回文件描述符。

这个系统调用在进程和文件之间建立一条连接 ,这个连接被称为文件描述符,它就像一条由进程通向内核的管道。  
要打开一个文件,必须指定文件名和打开模式,有3种打开模式:只读,只写,可读可写,分别对应于O_RDONLY,O_WRONLY,O_RDWR,这在头文件/usr/include/fcntl.h中有定义。
        打开文件是内核提供的服务,如果在打开过程中内核检测到任何错误,这个系统调用就会返回-1。错误的类型是各种各样的,如:要打开的文件不存在。即使文件存在可能因为权限不够而无法打开,在open的联机帮助中列出了各种可能的错误,大家可以看看。
        UNIX允许一个文件被多个进程访问,也就是说当一个文件被一个进程打开后,这个文件还可以被其它进程打开。
        如果文件被顺利打开内核会返回一个正整数的值,这个数值就叫文件描述符,如果同时打开好几个文件,它们所对应的的文件描述符是不同的,如果一个文件打开多次,对应的文件描述符也不相同。必须通过文件描述符对文件操作。下面的程序可以证明这一点。

  1. #include <stdio.h>
  2. #include <fcntl.h>
  3. #include <unistd.h>

  4. int main(int ac,char *av[])
  5. /*int ac是命令行参数的个数.  char *argv[]是一个存放字符指针的数组, 每个指针指向一个具体的命令行参数(字符串)*/
  6. {
  7.         int fd;
  8.         int size;
  9.         char buf[10000]; /*定义用于存放数据的目的缓冲区*/
  10.        
  11.         if(ac==1)
  12.                 printf(“please input file!\n”);
  13.         else
  14.         {
  15.                 while(--ac)
  16.                 {
  17.                         printf(“file :%s\n”,av[ac]);
  18.                         fd=open(av[1],O_RDONLY);
  19.                         printf(“fd:%d\n”,fd);
  20.                         size=read(fd,buf,sizeof(buf));
  21.                         printf(“size:%d\n”,size);
  22.                         printf(“%s”,buf);
  23.                 }
  24.                 close(fd);
  25.                 return -1;
  26.         }
  27. }
复制代码


我们编译一下
[root@LINUX root]# cc –o show_read show_read.c
运行
[root@LINUX root]# ./show_read show_read.c
下面是运行结果。
file: 3
size:423
#include <stdio.h>
……


我们可以看出此次打开文件的文件描述符是3,如果我们执行下面的语句。
[root@LINUX root]# ./show_read show_read.c show_read.c
下面是运行结果:
file: 3
size: 423
#include <stdio.h>
……

file: 4
size 432
#include <stdio.h>
……

可以看到,我们第一次打开文件的描述符是3,第二次打开文件的文件描述符是4。

2.
名称:        close
目标:         关闭一个文件。
头文件:        #include < unistd.h>
函数原形:        int result=close(int fd)
参数:         fd    文件描述符
返回值:         -1     遇到错误
            int    关闭成功,返回文件描述符。
        Close这个系统调用会关闭进程和文件fd之间的连接,如果关闭过程中出现错误,close返回-1,如:fd所指的文件并不存在。关闭成功则返回文件描述符。

3.
名称:        read
目标:         把数据读到缓冲区。
头文件:        #include < unistd.h>
函数原形:        ssize_t numread=read(int fd, void *buf, size_t qty)
参数:         fd       文件描述符
        buf      用来存放数据的目的缓冲区
        qty      要读取的字节数
返回值:         -1       遇到错误
            unmread  成功关闭,返回所读取的字节数目。
read这个系统调用请求内核从fd所指定的文件中读取qty字节的数据,存放到buf所指定的内存空间中,内核如果成功地读取了数据,就返回所读取的字节数目。否则返回-1。
当文件的字节数没有你想要的那么多时,read就会判断下一个数值是不是’\0’,如果是就停止读取,然后退出。numread返回的是’\0’之前的字节数,也就是是原文件的字节数而不是你想读的字节数。

4.
名称:        creat
目标:         创建/重写一个文件
头文件:        #include < fcntl.h>
函数原形:        int fd=creat(char *filename,node_t mode)
参数:         filename   文件名
        mode      访问模式
返回值:         -1         遇到错误
     fd         创建成功
        Creat告诉内核创建一个名为filename的文件,如果这个文件不存在,就创建它,如果已经存在,就把它的内容清空,把文件的长度设为0。       
        如果内核成功地创建了文件,那么文件的许可位(permission bits)被设置为由第二个参数mode所指定的值.如:
fd=creat(“addressbook”,0644);
        创建一个名为addressbook的文件,如果文件不存在,那么文件的许可位被设为 rw-r-r—.
如果文件已存在它的内容会被清空。任一情况下,fd都会是指向addressbook的文件描述符。

5.
名称:        write
目标:         将内存中的数据写入文件。
头文件:        #include < unistd.h>
函数原形:        ssize_t numread=write(int fd, void *buf, size_t amt)
参数:         fd       文件描述符
        buf      内存数据
        amt      要写的字节数
返回值:         -1       遇到错误
            Num written  成功写入,返回写入的字节数目。
在实际的写入过程中,可能会出现写入的字节数少于所要求的。这可能有两个原因,第一是有的系统对文件的最大尺寸有限制,第二是磁盘空间接近满了。在上述两种情况下内核都会尽力把数据往文件中写,并将实际写入的字节数返回,所以调用write后都必须检查返回值是否与要写入的相同,如果不同就要采取相应的措施。
        学完上面几个系统调用,我们就可以自己编写的cp命令了。它的基本思路是从原文件读取数据写入缓冲,再将缓冲的数据写入目标文件。

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <fcntl.h>

  4. #define BUFFERSIZE 4096
  5. #define COPYMODE 0644  

  6. void oops(char *s1,char *s2);

  7. main(int ac,char *av[])
  8. {
  9.         int in_fd,out_fd,n_chars;
  10.         char buf[BUFFERSIZE];

  11.         if(ac!=3)
  12.         {
  13.                 fprintf(stderr,”usage:%s source destination\n”,*av);
  14.                 exit(1);
  15.         }
  16.         if(in_fd=open(av[1],O_RDONLY))==-1)
  17.                 opps(“Cannot open”,av[1]);
  18.         if(out_fd=creat(av[2], COPYMODE))==-1)
  19.                 oops(“Cannot creat”,av[2]);
  20.         while((n_chars=read(in_fd,buf,BUFFERSIZE))>0)
  21.         {
  22.                 if(write(out_fd,buf,n_chars)!=n_chars)
  23.                         oops(“Write error to”,av[2]);
  24.         }
  25.         if(n_chars==-1)
  26.                 opps(“Read error form”,av[1]);
  27.         if(close(in_fd)==1||close(out_fd)==-1)
  28.                 opps(“Error clising files”,” ”);
  29. }

  30. Void oops(char *s1,char *s2)
  31. {
  32.         fprintf(stderr,”Error:%s”s1);
  33.         perror(s2);
  34.         exit(1);
  35. }
复制代码


6.
名称::        lseek
目标:        使指针指向文件中的指定位置。
头文件:        #include <sys/type.h>
#include <unistd.h>
函数原形:         off_t oldpos = lseek(int fd,off_t dist,int base)
参数:        fd      文件描述符
dist     移动的距离
base    SEEK_SET=>文件的开始
        SEEK_CUR=>当前位子
        SEEK_END=>文件结束
返回值:        -1      遇到错误
Ildpos   指针变化前的位子
        Lseek改变文件描述符所关联的指针的位置,新的位置由dist和base来指定,base是基准位置,dist是从基准位子开始的偏移量。基准位子可以是文件的开始(0)、当前位子(1)或文件的结束(2)。例如:
        lseek(fd,0,SEEK_END);

[ 本帖最后由 湖光倒影 于 2006-8-16 14:43 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2006-08-14 21:45 |只看该作者
>>
>>
>>赞一个!
>>
>>
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP