您的位置:首页 > 运维架构 > Linux

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

2015-09-03 22:19 489 查看


I/O是什么

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

设备->内存: 输入操作

内存->设备: 输出操作

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

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

文件描述符

在linux系统中打开文件就会获得文件描述符,它是个很小的正整数。每个进程在PCB(Process
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操作,列出目录下的普通文件。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: