Linux下编程-----文件与IO(一)基本API

来源:互联网 发布:js map参数传递 编辑:程序博客网 时间:2024/06/11 04:01

I/O是什么

输入/输出是内存和外设之间拷贝数据的过程:

   设备->内存: 输入操作

   内存->设备: 输出操作

 高级I/O: ANSI C提供的标准I/O库函数成为高级I/O, 也称为带缓冲的I/O;

 低级I/O: Linux 提供的系统调用通常也称为不带缓冲的I/O;

文件描述符

  在linux系统中打开文件就会获得文件描述符,它是个很小的正整数。每个进程在PCBProcess Control Block)中保存着一份文件描述符表,文件描述符就是这个表的索引,每个表项都有一个指向已打开文件的指针。一个进程启动时,默认打开了3个文件,标准输入、标准输出、标准错误,对应的文件描述符是0(STDIN_FILENO)、1(STDOUT_FILENO)、2(STDERR_FILENO),这些常量定义在unistd.h头文件中。注:括号内的就代表文件指针File*。

文件描述符和文件指针的转换函数

fileno: 将文件指针转换成文件描述符

       int fileno(FILE *stream);

fdopen: 将文件描述符转换成文件指针

       FILE *fdopen(int fd, const char *mode);

int main(){printf("fileno(stdin)= %d\n",fileno(stdin));// res: fileno(stdin)=0} 

基本API

1.open
打开成功返回文件描述符;打开失败返回-1。

int open(const char *pathname, int flags, mode_t mode); 

参数:

   pathname:  文件名, 可以包含[绝对/相对]路径名;

   flags: 文件打开模式;

   mode: 用来指定对文件所有者, 文件用户组以及系统中的其他用户的访问权限;


#include <string.h>#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <errno.h>#include <dirent.h>#define ERR_EXIT(m) \        do \        { \            perror(m); \            exit(EXIT_FAILURE); \        }while(0)int main(){     int fd;   umask(0);   fd=open("test.txt",O_RDONLY,0666);   if(fd==-1)   ERR_EXIT("open failure");   printf("Open OK!\n");   return 0;}

注意两点:

  1.我们使用#define定义出错的函数,这样更加专业

  2.umask是从我们定义的权限中再“拿走”相应的位,注意这里是逻辑减。我们定义权限666,系统一般默认umask是022(使用umask命令查看),所以剩下的是644,我们也可以将umask的值置为0,这样在程序中就不受其影响了。

2.close

  int close(int fd);

  关闭文件描述符, 使得文件描述符得以重新利用,一个进程结束时也会主动关闭所有的文件。

3.read

    ssize_t read(int fd, void *buf, size_t count);

  返回从文件复制到缓冲区的字节数,count:从该文件复制到buf的字节个数。

4.write

    ssize_t write(int fd, const void *buf, size_t count);  

返回值:

   错误: -1

   什么都没做: 0

   成功: 返回成功写入文件的字节数

注意:

   write返回大于0时, 并不代表buf的内容已经写入到磁盘上的文件中了, 其仅仅代表buf中的数据已经copy到相应的内核缓冲区了. 要实现将缓冲区的内容真正”冲洗”到磁盘上的文件, 需要调用fsync函数;

     int fsync(int fd);

   其将内核缓冲区中尚未写入磁盘的内容同步到文件系统中;

   其实在open调用的时候也可以指定同步选项:O_SYNC O_SYNC The file is opened for synchronous I/O.   Any  write(2)s  on  the  resulting  file  descriptor will block the calling process until the data has been physically written to the underlying hardware.

   write会等到将buf的内容真正的写入到磁盘才真正返回;

#define ERR_EXIT(m) \        do \        { \            perror(m); \            exit(EXIT_FAILURE); \        }while(0)int main(){     int fd;   umask(0);   fd=open("test.txt",O_RDONLY,0666);   if(fd==-1)   ERR_EXIT("open failure");   printf("Open OK!\n");    int outfd;   outfd=open("temp.txt",O_RDWR | O_CREAT,0666);   if(outfd==-1)   {       ERR_EXIT("open dest error");   }   char buff[1024];   int nread;   while((nread=read(fd,buff,1024))>0)   write(outfd,buff,nread);   close(fd);   close(outfd);   return 0;}

实现了简单的cp功能。

5.lseek

off_t lseek(int fd, off_t offset, int whence);  

Whence取值:

SEEK_SET

   The offset is set to offset bytes.

SEEK_CUR

   The offset is set to its current location plus offset bytes.

SEEK_END

   The offset is set to the size of the file plus offset bytes.

int ret =lseek(fd,0,SEEK_CUR); printf("current offset =%d\n",ret);

6。目录访问之opendir,readdir

DIR *opendir(const char *name);  //打开一个目录

struct dirent *readdir(DIR *dirp);

int closedir(DIR *dirp);  //关闭目录

int mkdir(const char *pathname, mode_t mode);  //创建目录

int rmdir(const char *pathname);  //删除一个空目录

struct dirent  {      ino_t          d_ino;       /* inode number */      off_t          d_off;       /* not an offset; see NOTES */      unsigned short d_reclen;    /* length of this record */      unsigned char  d_type;      /* type of file; not supported                                          by all filesystem types */      char           d_name[256]; /* filename */  };  

成功: 返回一个指向dirent结构的指针, 它包含指定目录的下一个连接的细节;
失败:NULL


 DIR* dir=opendir(".");   struct direnn *de;   while((de=readdir(dir))!=NULL)   {       if(strncmp(de->d_name,".",1)==0)           continue;       printf("%s\n",de->d_name);      closedir(dir);   exit(EXIT_SUCCESS);

上面代码的功能是实现简单的ls操作,列出目录下的普通文件。





1 0
原创粉丝点击