精华内容
下载资源
问答
  • Linux文件操作API涉及到创建、打开、读写和关闭文件。 1.linux API  创建 int creat(const char *filename, mode_t mode);  参数mode指定新建文件的存取权限,它同umask一起决定...
    

    Linux的文件操作API涉及到创建、打开、读写和关闭文件。

    1.linux API


      创建

    int creat(const char *filename, mode_t mode);



      参数mode指定新建文件的存取权限,它同umask一起决定文件的最终权限(mode&umask),其中umask代表了文件在创建时需要去掉的一些存取权限。umask可通过系统调用umask()来改变:

    int umask(int newmask);


    打开

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



      open函数有两个形式,其中pathname是我们要打开的文件名(包含路径名称,缺省是认为在当前路径下面),flags可以去下面的一个值或者是几个值的组合:

    标志含义
    O_RDONLY以只读的方式打开文件
    O_WRONLY以只写的方式打开文件
    O_RDWR以读写的方式打开文件
    O_APPEND以追加的方式打开文件
    O_CREAT创建一个文件
    O_EXEC如果使用了O_CREAT而且文件已经存在,就会发生一个错误
    O_NOBLOCK以非阻塞的方式打开一个文件
    O_TRUNC如果文件已经存在,则删除文件的内容
      



      O_RDONLY、O_WRONLY、O_RDWR三个标志只能使用任意的一个。

         mode可以是以下情况的组合:

    标志含义
    S_IRUSR用户可以读
    S_IWUSR用户可以写
    S_IXUSR用户可以执行
    S_IRWXU用户可以读、写、执行
    S_IRGRP组可以读
    S_IWGRP组可以写
    S_IXGRP组可以执行
    S_IRWXG组可以读写执行
    S_IROTH其他人可以读
    S_IWOTH其他人可以写
    S_IXOTH其他人可以执行
    S_IRWXO其他人可以读、写、执行
    S_ISUID设置用户执行ID
    S_ISGID设置组的执行ID



      除了可以通过上述宏进行“或”逻辑产生标志以外,我们也可以自己用数字来表示,Linux总共用5个数字来表示文件的各种权限:第一位表示设置用户ID;第二位表示设置组ID;第三位表示用户自己的权限位;第四位表示组的权限;最后一位表示其他人的权限。每个数字可以取1(执行权限)、2(写权限)、4(读权限)、0(无)或者是这些值的和。例如,要创建一个用户可读、可写、可执行,但是组没有权限,其他人可以读、可以执行的文件,并设置用户ID位。那么,我们应该使用的模式是1(设置用户ID)、0(不设置组ID)、7(1+2+4,读、写、执行)、0(没有权限)、5(1+4,读、执行)即10705:

    open("test", O_CREAT, 10705);



      上述语句等价于:

    open("test", O_CREAT, S_IRWXU | S_IROTH | S_IXOTH | S_ISUID );



      如果文件打开成功,open函数会返回一个文件描述符,以后对该文件的所有操作就可以通过对这个文件描述符进行操作来实现。

      读写

      在文件打开以后,我们才可对文件进行读写了,Linux中提供文件读写的系统调用是read、write函数:

    int read(int fd, const void *buf, size_t length);
    int write(int fd, const void *buf, size_t length);



      其中参数buf为指向缓冲区的指针,length为缓冲区的大小(以字节为单位)。函数read()实现从文件描述符fd所指定的文件中读取length个字节到buf所指向的缓冲区中,返回值为实际读取的字节数。函数write实现将把length个字节从buf指向的缓冲区中写到文件描述符fd所指向的文件中,返回值为实际写入的字节数。

      以O_CREAT为标志的open实际上实现了文件创建的功能,因此,下面的函数等同creat()函数:

    int open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);



      定位

      对于随机文件,我们可以随机的指定位置读写,使用如下函数进行定位:

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



      lseek()将文件读写指针相对whence移动offset个字节。操作成功时,返回文件指针相对于文件头的位置。参数whence可使用下述值:

      SEEK_SET:相对文件开头
      SEEK_CUR:相对文件读写指针的当前位置
      SEEK_END:相对文件末尾

      offset可取负值,例如下述调用可将文件指针相对当前位置向前移动5个字节:

    lseek(fd, -5, SEEK_CUR);



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

    lseek(fd, 0, SEEK_END);



      关闭

      当我们操作完成以后,我们要关闭文件了,只要调用close就可以了,其中fd是我们要关闭的文件描述符:

    int close(int fd);



      例程:编写一个程序,在当前目录下创建用户可读写文件“hello.txt”,在其中写入“Hello, software weekly”,关闭该文件。再次打开该文件,读取其中的内容并输出在屏幕上。


    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <stdio.h>
    #define LENGTH 100
    main()
    {
     int fd, len;
     char str[LENGTH];
     fd = open("hello.txt", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); /* 创建并打开文件 */
     if (fd)
     {
      write(fd, "Hello, Software Weekly", strlen("Hello, software weekly")); /* 写入 Hello, software weekly字符串 */
      close(fd);
     }

     fd = open("hello.txt", O_RDWR);
     len = read(fd, str, LENGTH); /* 读取文件内容 */
     str[len] = '/0';
     printf("%s/n", str);
     close(fd);
    }
    编译并运行,执行结果如下图:


             #gcc -g -o hello ./hello.c

             #./hello

             #Hello, software weekly


    2.C语言库函数

      C库函数的文件操作实际上是独立于具体的操作系统平台的,不管是在DOS、Windows、Linux还是在VxWorks中都是这些函数:

      创建和打开

    FILE *fopen(const char *path, const char *mode);


      fopen()实现打开指定文件filename,其中的mode为打开模式,C语言中支持的打开模式如下表:

    标志含义
    r, rb以只读方式打开
    w, wb以只写方式打开。如果文件不存在,则创建该文件,否则文件被截断
    a, ab以追加方式打开。如果文件不存在,则创建该文件
    r+, r+b, rb+以读写方式打开
    w+, w+b, wh+以读写方式打开。如果文件不存在时,创建新文件,否则文件被截断
    a+, a+b, ab+以读和追加方式打开。如果文件不存在,创建新文件


      其中b用于区分二进制文件和文本文件,这一点在DOS、Windows系统中是有区分的,但Linux不区分二进制文件和文本文件。

      读写

      C库函数支持以字符、字符串等为单位,支持按照某中格式进行文件的读写,这一组函数为:

    int fgetc(FILE *stream);
    int fputc(int c, FILE *stream);
    char *fgets(char *s, int n, FILE *stream);
    int fputs(const char *s, FILE *stream);
    int fprintf(FILE *stream, const char *format, ...);
    int fscanf (FILE *stream, const char *format, ...);
    size_t fread(void *ptr, size_t size, size_t n, FILE *stream);
    size_t fwrite (const void *ptr, size_t size, size_t n, FILE *stream);


      fread()实现从流stream中读取加n个字段,每个字段为size字节,并将读取的字段放入ptr所指的字符数组中,返回实际已读取的字段数。在读取的字段数小于num时,可能是在函数调用时出现错误,也可能是读到文件的结尾。所以要通过调用feof()和ferror()来判断。

      write()实现从缓冲区ptr所指的数组中把n个字段写到流stream中,每个字段长为size个字节,返回实际写入的字段数。

      另外,C库函数还提供了读写过程中的定位能力,这些函数包括

    int fgetpos(FILE *stream, fpos_t *pos);
    int fsetpos(FILE *stream, const fpos_t *pos);
    int fseek(FILE *stream, long offset, int whence);
    等。


      关闭

      利用C库函数关闭文件依然是很简单的操作:

    int fclose (FILE *stream);


      例程:将第2节中的例程用C库函数来实现。

    #include <stdio.h>
    #define LENGTH 100
    main()
    {
     FILE *fd;
     char str[LENGTH];

     fd = fopen("hello.txt", "w+"); /* 创建并打开文件 */
     if (fd)
     {
      fputs("Hello, Software Weekly", fd); /* 写入Hello, software weekly字符串 */
      fclose(fd);
     }

     fd = fopen("hello.txt", "r");
     fgets(str, LENGTH, fd); /* 读取文件内容 */
     printf("%s/n", str);
     fclose(fd);
    }


    3.小结

      Linux提供的虚拟文件系统为多种文件系统提供了统一的接口,Linux的文件编程有两种途径:基于Linux系统调用;基于C库函数。这两种编程所涉及到文件操作有新建、打开、读写和关闭,对随机文件还可以定位。本章对这两种编程方法都给出了具体的实例

    展开全文
  • Linux文件IO操作

    2020-04-21 21:29:37
    文件操作1、系统调用概述2、系统调用 和 库函数的区别(重要!!!)3、文件描述符(重要!!!)案例:读取文件数据4、文件的打开读写关闭4.1、打开文件open4.1.1、flags宏的介绍(打开方式)4.1.2、mode的介绍...

    1、系统调用概述

    系统调用,顾名思义,说的是操作系统提供给用户程序调用的一组“特殊”接口。(重要!!!)
    一个进程(用户态、内核态)(了解)
    在这里插入图片描述

    2、系统调用 和 库函数的区别(重要!!!)

    在这里插入图片描述
    在这里插入图片描述
    系统调用是需要时间的,程序中频繁的使用系统调用会降低程序的运行效率。当运行内核代码时,CPU工作在内核态,在系统调用发生前需要保存用户态的栈和内存环境,然后转入内核态工作。系统调用结束后,又要切换回用户态。这种环境的切换会消耗掉许多时间 。

    3、文件描述符(重要!!!)

    用一个非负整数 来标识一个文件 这个非负的整数 就是文件描述符。
    打开一个文件 系统就会为我们非配一个文件描述符 操作文件描述符 就等价于 操作文件.

    文件描述符表:进程运行的时候 系统创建文件描述符表 来管理系统中文件描述符。
    每一个进程 默认打开了3个文件描述符(0标准输入设备/键盘 1标准输出设备/屏幕 2标准错误输出/屏幕)

    案例:读取文件数据

    在这里插入图片描述
    在这里插入图片描述
    运行结果:
    在这里插入图片描述
    在这里插入图片描述
    当用户打开一个文件的时候 系统 会给我们分配一个最小可用的文件描述符(重要!!!)
    在这里插入图片描述
    文件描述符表的管理(位图)
    在这里插入图片描述

    4、文件的打开读写关闭

    4.1、打开文件open

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    int open(const char *pathname, int flags);//打开已存在的文件
    int open(const char *pathname, int flags, mode_t mode);//打开不存在的文件
    //flags:read write操作文件的权限
    //mode:该文件在磁盘中 相对于 用户的权限
    
    功能:
        打开文件,如果文件不存在则可以选择创建。
    参数:
        pathname:文件的路径及文件名
        flags:打开文件的行为标志,必选项 O_RDONLY, O_WRONLY, O_RDWR
        mode:这个参数,只有在文件不存在时有效,指新建文件时指定文件的权限
    返回值:
        成功:成功返回打开的文件描述符
        失败:-1
    

    4.1.1、flags宏的介绍(打开方式)

    比如:以读写的方式打开 不存在则创建 存在清空 flags=O_RDWR | O_CREAT | O_TRUNC
    在这里插入图片描述

    4.1.2、mode的介绍(权限)

    mode的权限分3组:所拥有者、同组用户、其他用户
    每组都必须有独立的权限。
    在这里插入图片描述
    4表示读r 2表示写w 1表示可执行x
    在这里插入图片描述
    在这里插入图片描述
    文件的最终权限 = 默认权限 - 文件掩码
    文件掩码:屏蔽其他用户的权限
    在这里插入图片描述
    在这里插入图片描述

    chmod 777 xxx将xxx的最终权限设置为777

    4.2、关闭文件close

    #include <unistd.h>
    int close(int fd);
    功能:
        关闭已打开的文件
    参数:
        fd : 文件描述符,open()的返回值
    返回值:
        成功:0
        失败: -1, 并设置errno
    

    案例:

    在这里插入图片描述
    运行结果:
    在这里插入图片描述

    4.3、文件的写操作write

    #include <unistd.h>
    ssize_t write(int fd, const void *buf, size_t count);
    
    功能:
        把指定数目的数据写到文件(fd)
    参数:
        fd :  文件描述符
        buf : 数据首地址
        count : 写入数据的长度(字节)
    返回值:
        成功:实际写入数据的字节个数
        失败: - 1
    

    在这里插入图片描述

    4.4、read读取文件数据

    #include <unistd.h>
    ssize_t read(int fd, void *buf, size_t count);
    
    功能:
        把指定数目的数据读到内存(缓冲区)
    参数:
        fd : 文件描述符
        buf : 内存首地址
        count : 读取的字节个数
    返回值:
        成功:实际读取到的字节个数
        失败: - 1 文件末尾返回0
    

    案例:读文件数据

    在这里插入图片描述

    案例:实现cp命令: cp src_file dst_dir

    在这里插入图片描述

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <string.h>
    int main(int argc, char *argv[])
    {
    	//./main test.txt  test
    	if(argc != 3)
    	{
    		printf("please intput:./main src dst_dir\n");
    	}
    	char src_file[128]="";
    	char dst_file[128]="";
    	strcpy(src_file, argv[1]);//test.txt
    	sprintf(dst_file,"%s/%s",argv[2], argv[1]);//"test/test.txt"
    	
    	int fd1 = open(src_file, O_RDONLY);
    	if(fd1 < 0)
    	{
    		perror("open");
    		return 0;
    	}
    	int fd2 = open(dst_file, O_WRONLY|O_CREAT,0777);
    	if(fd2 <0)
    	{
    		perror("open");
    		return 0;
    	}
    
    	while(1)
    	{
    		char buf[128]="";
    		//从s源文件中读取数据
    		int ret = read(fd1,buf,sizeof(buf));
    		if(ret <= 0)
    			break;
    		//将读到的w数据写到目的文件中
    		write(fd2,buf,ret);
    	}
    
    	close(fd1);
    	close(fd2);
    	return 0;
    }
    

    运行结果:
    在这里插入图片描述

    5、文件的阻塞特性

    【注意】阻塞与非阻塞是对于文件而言的,而不是指read、write等的属性

    案例:默认终端是读是阻塞的

    #include<stdio.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<fcntl.h>
    int main(int argc,char *argv[])
    {
    	// /dev/tty --> 当前终端设备
    	int fd = open("/dev/tty", O_RDONLY);//默认是阻塞的
    	if(fd<0)
    	{
    		perror("open");
    		return 0;
    	}
    	
    	printf("fd = %d\n",fd);
    	
    	char buf[128]="";
    	printf("准备读!!!\n");
    	read(fd,buf,sizeof(buf));
    	printf("buf=%s\n",buf);
    	
    	close(fd);
    	return 0;
    }
    

    运行结果:
    在这里插入图片描述

    案例:非阻塞()

    #include<stdio.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<fcntl.h>
    int main(int argc,char *argv[])
    {
    	// /dev/tty --> 当前终端设备
    	//int fd = open("/dev/tty", O_RDONLY);//默认是阻塞的
    	int fd = open("/dev/tty", O_RDONLY|O_NONBLOCK);//不阻塞的
    	
    	if(fd<0)
    	{
    		perror("open");
    		return 0;
    	}
    	
    	printf("fd = %d\n",fd);
    	
    	char buf[128]="";
    	printf("准备读!!!\n");
    	read(fd,buf,sizeof(buf));
    	printf("buf=%s\n",buf);
    	
    	close(fd);
    	return 0;
    }
    

    运行结果:
    在这里插入图片描述

    5.1、通过fcntl函数设置文件的阻塞特性(了解)

    我们还可以通过fcntl函数来设置文件描述符的阻塞特性
    #include <unistd.h>
    #include <fcntl.h>
    int fcntl(int fd, int cmd, ... /* arg */);
    功能:改变已打开的文件性质,fcntl针对描述符提供控制。
    参数:
        fd:操作的文件描述符
        cmd:操作方式
        arg:针对cmd的值,fcntl能够接受第三个参数int arg。
    返回值:
        成功:返回某个其他值
        失败:-1
    fcntl函数有5种功能:
    1) 复制一个现有的描述符(cmd=F_DUPFD)
    2) 获得/设置文件描述符标记(cmd=FGETFD或FSETFD)
    3) 获得/设置文件状态标记(cmd=FGETFL或FSETFL)
    4) 获得/设置异步I/O所有权(cmd=FGETOWN或FSETOWN)
    5) 获得/设置记录锁(cmd=FGETLK, FSETLK或F_SETLKW)
    

    案例:默认阻塞

    在这里插入图片描述
    fcntl函数设置非阻塞

    #include<stdio.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<fcntl.h>
    int main(int argc,char *argv[])
    {
    	char buf[128]="";
    	//fcntl设置文件标记的3步曲
    	//获得文件的标记
    	int flag = fcntl(0, F_GETFL);
    	//修改文件的标记(非阻塞标记)
    	flag |= O_NONBLOCK;
    	//设置文件的标记
    	fcntl(0,F_SETFL, flag);
    	
    	printf("准备读!!!\n");
    	read(0,buf,sizeof(buf));
    	printf("buf=%s\n",buf);	
    	
    	return 0;
    }
    

    运行结果:
    在这里插入图片描述

    6、通过文件名 直接获取文件的状态(了解)

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    int stat(const char *path, struct stat *buf);
    int lstat(const char *pathname, struct stat *buf);
    功能:
        获取文件状态信息
        stat和lstat的区别:
            当文件是一个符号链接时,lstat返回的是该符号链接本身的信息;
            而stat返回的是该链接指向的文件的信息。
    参数:
        path:文件名
        buf:保存文件信息的结构体
    返回值:
        成功: 0
        失败: -1
    

    struct stat的结构信息:

    struct stat {
        dev_t           st_dev;     //文件的设备编号
        ino_t           st_ino;     //节点
        mode_t          st_mode;            //文件的类型和存取的权限
        nlink_t         st_nlink;       //连到该文件的硬连接数目,刚建立的文件值为1
        uid_t           st_uid;     //用户ID
        gid_t           st_gid;     //组ID
        dev_t           st_rdev;        //(设备类型)若此文件为设备文件,则为其设备编号
        off_t           st_size;        //文件字节数(文件大小)
        blksize_t       st_blksize;     //块大小(文件系统的I/O 缓冲区大小)
        blkcnt_t        st_blocks;      //块数
        time_t          st_atime;       //最后一次访问时间
        time_t          st_mtime;       //最后一次修改时间
        time_t          st_ctime;       //最后一次改变时间(指属性)
    };
    

    st_mode(16位整数)参数说明:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    案例:

    #include<stdio.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<fcntl.h>
    int main(int argc,char *argv[])
    {
    	struct stat my_stat;
    	stat("test.txt", &my_stat);
    	
    	printf("文件的大小:%u\n", my_stat.st_size);
    	if(S_ISREG(my_stat.st_mode))
    	{
    		printf("它是一个普通文件\n");
    	}
    	else if(S_ISDIR(my_stat.st_mode))
    	{
    		printf("它是一个目录文件\n");
    	}
    	
    	if((my_stat.st_mode& S_IRUSR)== S_IRUSR)
    	{
    		printf("所有者具备读的权限\n");
    	}
    	return 0;
    }
    

    运行结果:
    在这里插入图片描述

    7、文件的目录操作(了解)

    我们经常需要读取一个目录下的所有文件名,所以一下介绍如何读取一个文件下的目录
    步骤:

    1、打开文件目录opendir

    #include <sys/types.h>
    #include <dirent.h>
    DIR *opendir(const char *name);
    功能:打开一个目录
    参数:
        name:目录名
    返回值:
        成功:返回指向该目录结构体指针
        失败:NULL
    

    2、读取目录readdir 调用一次 只能读取一个文件

    #include <dirent.h>
    struct dirent *readdir(DIR *dirp);
    功能:读取目录
    参数:
        dirp:opendir的返回值
    返回值:
        成功:目录结构体指针
        失败:NULL
    

    struct dirent:

    struct dirent
    {
        ino_t d_ino;                  // 此目录进入点的inode
        off_t d_off;                    // 目录文件开头至此目录进入点的位移
        signed short int d_reclen;      // d_name 的长度, 不包含NULL 字符
        unsigned char d_type;           // d_type 所指的文件类型
        char d_name[256];               // 文件名
    };
    

    d_type取值:
    在这里插入图片描述

    3、关闭closedir

    #include <sys/types.h>
    #include <dirent.h>
    int closedir(DIR *dirp);
    功能:关闭目录
      参数:
          dirp:opendir返回的指针
      返回值:
          成功:0
          失败:-1
    

    案例:

    #include <stdio.h>
    #include <dirent.h>
    int main(int argc,char *argv[])
    {
    	//打开目录
    	DIR *dir = opendir("test");
    	if(dir == NULL)
    	{
    		perror("opendir");
    		return 0;
    	}
    	//读取目录
    	while(1)
    	{
    		struct dirent *p = readdir(dir);
    		if(p == NULL)
    			break;
    		printf("文件名:%s  ", p->d_name);
    		if(p->d_type == DT_DIR)
    		{
    			 printf("目录\n");
    		}
    		else if(p->d_type == DT_REG)
    		{
    			printf("普通文件\n");
    		}
    	}
    	
    	//关闭
    	closedir(dir);
    }
    

    运行结果:
    在这里插入图片描述

    展开全文
  • Linux 文件操作的系统调用接口

    千次阅读 2016-08-15 14:19:06
    文件操作的相关调用也是Linux内核提供的最重要的编程接口。    本节将重点叙述如下几个常用的文件操作系统调用。  open:打开文件。  read:从已打开的文件中读取数据。  write:向已打开的文件中写入...

    文件操作的系统调用接口:
     文件是Linux系统中的重要概念。它不仅仅是对普通文件的操作接口,也是设备通信、进程间通信、网络通信的重要编程接口。因

    此文件操作的相关调用也是Linux内核提供的最重要的编程接口。
     
     本节将重点叙述如下几个常用的文件操作系统调用。
     open:打开文件。
     read:从已打开的文件中读取数据。
     write:向已打开的文件中写入数据。
     close:关闭已打开的文件。
     ioctl:向文件传递控制信息或发出控制命令。
     
     对文件的操作工程一般是这样的:先打开文件,内核对打开的文件进行管理,打开成功后应用程序将获得文件描述符;然后应用程

    序使用文件描述符对文件进行读写操作;当全部操作完毕后,应用程序需要将文件关闭以释放用于管理打开文件的内存。
     文件描述符是一个取值从0开始的整数。内核默认一个进程同时打开的文件数有一个上限,也就是文件描述符取值的上限,一般是

    1024。
     每个进程在启动后就默认有三个打开的文件描述符0,1,2,如果启动程序时没有进行重定向,则文件描述符0关联到标准输入,1关

    联到标准输出,2关联到标准错误输出。在C库函数中可以使用以下几个宏来表示这几个文件描述符:
     #define STDIN_FILENO   0
     #define STDOUT_FILENO  1
     #define STDERR_FILENO  2


    打开文件:
     在访问文件之前,首先应打开文件。可以使用open或creat函数来打开文件,它们的接口头文件及函数原型如下:
     #include <sys/types.h>
     #include <sys/stat.h>
     #include <fcntl.h>
     int open(const char *pathname, int flags);
     int open(const char *pathname, int flags, mode_t mode);
     int creat(const char *pathname, mode_t mode);

     其各个参数及返回值的含义解释如下.
     ◆ pathname:要打开的文件名称。
     ◆ flags:标志位,指定打开文件的操作方式及打开时的一些行为。
     ◆ mode: 用于指定新文件的权限标志位。
     ◆ 返回值:操作成功则返回文件描述符,否则返回-1并设置标量errno的值。

     flags参数有以下几个基本的取值。
     ◆ O_RDONLY:以只读方式打开文件。
     ◆ O_WRONLY:以只写方式打开文件。
     ◆ O_RDWR:以读写方式打开文件。

     这几个标志位指定打开文件的操作方式,它们是互斥的,不能同时使用,但可以与下述标志用按位或的方式组合起来使用。
     ◆ O_CREAT:如果被打开的文件不存在,则自动创建这个文件。
     ◆ O_EXCL:如果O_CREAT标志已经使用,那么当由pathname参数指定的文件已经存在时open函数返回失败。如果pathname给出的是 

      一个符号链接,无论它指向的文件是否存在,对open函数的调用都会返回失败。
     ◆ O_NOCITY:如果被打开的文件是一个终端设备文件(如/dev/tty),它不会成为这个进程的控制终端。
     ◆ O_TRUNC:如果被打开的文件存在并且是以可写的方式打开的,则清空文件原有内容。
     ◆ O_APPEND:新写入的内容将被附加在文件原来的内容之后,即打开后文件的读写位置被置于文件尾。
     ◆ O_NONBLOCK:被打开的文件将以非阻塞的方式进行操作。
     ◆ O_NDELAY:同O_NONBLOCK。
     ◆ O_SYNC:被打开的文件将以同步I/O的方式进行操作,即任何写操作都会先被同步到硬件设备上。同步完成后,对写函数的调用 

      才返回。
     ◆ O_NOFOLLOW:如果pathname是一个符号链接,则对open函数的调用将返回失败。
     ◆ O_DIRECTORY:如果pathname不是目录,则对open函数的调用将返回失败。

     需要注意的是,open函数有两个原型,其中一个多出了个参数mode,它用于指定创建的新文件的访问权限。如果打开时使用了

    O_CREAT标志创建新文件,则一般都要给出mode参数,它的一些常用取值如表所示,这些值可以用按位或的方式组合使用。新文件的所属用

    户和所属组则是创建它的进程的所属用户和所属组。
     权限标志定义  对应的八进制形式  含义
     S_IRWXU   00700    文件所属用户有读写和执行权限
     S_IRUSR(S_IREAD) 00400    文件所属用户有读权限
     S_IWUSR(S_IWRITE) 00200    文件所属用户有写权限
     S_IXUSR(S_IEXEC) 00100    文件所属用户有执行权限
     S_IRWXG   00070    组内用户有读写和执行权限
     S_IRGRP   00040    组内用户有读权限
     S_IWGRP   00020    组内用户有写权限
     S_IXGRP   00010    组内用户有执行权限
     S_IRWXO   00007    其他用户有读写和执行权限
     S_IROTH   00004    其他用户有读权限
     S_IWOTH   00002    其他用户有写权限
     S_IXOTH   00001    其他用户有执行权限

     鉴于在调用open函数时,O_WRONLY,O_CREAT,O_TRUNC三个标志位经常组合使用,因此由一个专门的函数creat来实现。如下:
     creat(pathname, mode); 
     实际上等价于:
     open(pathname,O_WRONLY|O_CREAT|O_TRUNC,mode);
     
     这两个函数在打开文件成功时将返回一个文件描述符,可用于随后的read/write或其他对文件的操作使用。两个不同的进程打开同

    一个文件是允许的,但它们得到的文件描述符一般是不同的。如果它们都对文件进行写操作,就会出现数据不一致的情况,也就是最后写入

    的可能覆盖先前其他进程写入的内容,这就涉及到进程间数据共享和同步的概念了。
     如果打开操作失败,这两个函数会返回-1,并将errno变量设置为一个合适的错误值。

    从文件读取数据:
     文件打开后就可以进行读写操作了。读操作的接口头文件及函数原型如下:
     #include <unistd.h>
     ssize_t read(int fd, void *buf, size_t count);

     其各个参数及返回值的含义解释如下:
     ◆ fd:要读取的文件描述符。
     ◆ buf:指向读取到的数据要放入的缓冲区。(buf指向的内存空间必须事先分配好)
     ◆ count:要读取的字节数(缓冲区大小)。
     ◆ 返回值:读取到的字节数,失败返回-1,并设置标量errno的值。

     这里的size_t型实际上就是无符号整型,而ssize_t型就是有符号整型。
     这个函数将从fd代表的文件的当前读写位置读取不超过count个字节到buf指向的内存中,并返回读到的字节数。

     对于普通文件来说,读操作完成后,文件的读写位置会向后移动,移动的长度就是读取的字节数,下一次读操作将从新的读写位置

    开始。
     read函数的返回值小于指定的count是可能的,并不是错误。出现这种情况有各种原因,比如,文件本身可供读取的字节数比count

    小或者read系统调用被信号打断等。read系统调用看似简单,但实际上对于各种可能情况的处理是比较复杂的,因为I/O操作有很多异常情

    况要考虑到。下面列出了read系统调用中可能遇到的情况及其处理方法。
     ◆ 调用返回值等于count,读取的数据存放在buf指向的内存中,结果与预期一致。
     ◆ 调用返回一个大于0小于count的值,读取的字节数存放在buf指向的内存中。出现这种情况可能是一个信号打断了读取过程,或 

      在读取中发生了一个错误,或读取的有效字节数大于0但不足count个,或在读入count个字节前文件已经结束。如果读取 

      的过程被信号打断则可以再次进行读取。
     ◆ 调用返回0,说明文件已结束,没有可以读入的数据。
     ◆ 调用阻塞,说明没有可读的数据,这种情况下如果以非阻塞方式操作文件,那么会立即返回错误。
     ◆ 调用返回-1,并且errno变量被设置为EINTR,表示在读入有效字节前收到一个信号,这种情况可以重新进行读操作。
     ◆ 调用返回-1,并且errno变量被设置为EAGAIN,这说明是在非阻塞方式下读文件,并且没有可读的数据。
     ◆ 调用返回-1,并且errno变量被设置为非EINTR或EAGAIN的值,表示有其他类型的错误发生,必须根据具体情况进行处理。

     由于有各种异常情况的存在,为了从文件中可靠的读取指定的字节数,就必须对这些情况进行处理,必要时需重新进行读操作。这

    对于设备文件、管道或socket来说尤其有意义。例如,用下面的代码能够可靠的从文件中读取指定的字节数(假设文件是以阻塞的方式进行

    操作的):
     ssize_t ret;
     while(len != 0 && (ret = read(fd,buf,len)) != 0)
     {
      if(ret == -1)
      {
       if(errno == EINTR) continue;
       perror("read");
       break; 
      }
      len -= ret;
      buf += ret; 
     }
     这里把操作放在循环中,当一次读操作没有得到len个字节时,将调整len和buf的值继续进行操作。如果读操作返回-1,说明有错

    误发生,这时如果错误码是EINTR,说明只是被信号打断,可以继续读,其他情况则被认为是严重的错误,不能再继续读。
     以上是以阻塞方式读文件的例子,这时,如果文件是一个设备文件并且设备没有可读的数据,进程将进入睡眠状态不再继续执行,

    或者说阻塞在read系统调用处,直到设备有了可读的数据才会被唤醒继续执行。很多时候我们需要进程能够立刻返回以处理其他的事物,那

    么就需要采用非阻塞的方式来操作文件,举例如下:
     ssize_t nr;
     start:
     nr = read(fd, buf, len);
     if(nr == -1)
     {
      if(errno == EINTR)  goto start;
      if(errno == EAGAIN)  
      {
       /*处理其他事物,在恰当时再调用read*/
      }
      else
      {
       /*有错误发生,处理错误*/
      }
     } 
     可以看到,在采用非阻塞的方式读文件时,如果读操作返回-1,我们必须检查错误码是否为EINTR或EAGAIN,如果是EINTR,可以再

    次进行读操作,而如果是EAGAIN,表示要读取的(设备)文件现在没有可供读取的数据,因此进程可以继续处理其他事物,而后在恰当的时

    机再来读取这个文件。
      
    写数据到文件:
     向打开文件中写入数据的接口头文件及函数原型如下:
     #include <unistd.h>
     ssize_t write(int fd, const void *buf, size_t count);

     其各个参数及返回值的含义解释如下。
     ◆ fd:要写入的文件的描述符。
     ◆ buf:指向要写入的数据所存放的缓冲区。
     ◆ count:要写入的字节数。
     ◆ 返回值:实际写入的字节数,失败则返回-1,并设置变量errno的值。

     这个函数会从fd所代表的文件当前读写位置开始,把buf指向的内存中最多count个字节写入文件。写入成功则返回写入的字节数,

    并更新文件的读写位置。
     write系统调用返回大于0而小于count的值是合法的,并不表示有错误发生。
     ◆ 调用返回值等于count,说明数据全部写入成功。
     ◆ 调用返回一个大于0小于count的值,说明部分数据没有写入。这可能是因为写入过程被信号打断,或者底层的设备暂时没有足 

      够的空间存放写入的数据。
     ◆ 调用阻塞,说明暂时不能写入数据,这种情况下如果以非阻塞方式操作文件,那么会立即返回错误。
     ◆ 调用返回-1,并且errno变量被设置为EINTR,表示在写入一个有效字节前,收到一个信号,应用程序可以再次进行写操作。
     ◆ 调用返回-1,并且errno变量被设置为EAGAIN,说明是在非阻塞方式下写文件但文件暂时不能写入数据。
     ◆ 调用返回-1,并且errno变量被设置为EBADF,表示给定的文件描述符非法,或者文件不是以写方式打开。
     ◆ 调用返回-1,并且errno变量被设置为EFAULT,表示buf是无效的指针。
     ◆ 调用返回-1,并且errno变量被设置为EFBIG,表示写入的数据超过了最大的文件尺寸,或者超过了允许的文件读写位置。
     ◆ 调用返回-1,并且errno变量被设置为EPIPE,说明写入时发生了数据通道断层的错误,这种情况只在文件是管道或者是socket 

      的情况下发生。在这种情况下,进程还将收到一个SIGPIPE信号,信号的默认处理程序是使进程退出。
     ◆ 调用返回-1,并且errno变量被设置为ENOSPC,说明底层设备没有足够的空间。
     
     写文件举例如下:
     ssize_t ret;
     while(len != 0 && (ret = write(fd, buf, len)) != 0)
     {
      if(ret == -1)
      {
       if(errno == EINTR) continue;
       perror("write"); 
       break;
      } 
      len -= ret;
      buf += ret;
     }
     这里假定写操作是以阻塞的方式进行的。如果以非阻塞方式进行写操作,则当函数返回-1时,必须检测errno变量的值是否为

    EAGAIN,以决定能否再进行写操作。
     

    发送控制命令:
     在Linux系统上,那些不能被抽象为读和写的文件操作统一由ioctl操作代表。ioctl操作用于向文件发送控制命令,这些命令不能

    被视为是输入输出流的一部分,而只是影响文件的操作方式。对于设备文件来说,ioctl操作常用于修改设备的参数。
     ioctl系统调用的接口头文件及函数原型如下:
     #include <sys/ioctl.h>
     int ioctl(int fd, int request, ...);
     
     ◆ fd:要操作的文件描述符。
     ◆ request:代表要进行的操作,不同的(设备)文件有不同的定义。
     ◆ 可变参数:取决于request参数,通常是一个指向变量或结构体的指针。
     ◆ 返回值:成功返回0,有效ioctl操作返回其他非负值,错误返回-1。

     ioctl能够进行的操作根据fd所代表的文件的具体类型而变化,非常繁多。下面举一个例子,使用TIOCGWINSZ命令获得终端的窗口

    大小,如下:
     

    复制代码
    /*文件名:console_size.c*/
     /*说明:使用ioctl获得控制台窗口的大小*/
     #include <stdio.h>
     #include <stdlib.h>
     #include <unistd.h>
     #include <sys/ioctl.h>
     
     int main(void)
     {
                 struct winsize size;
                 /*判断标准输出是否为tty设备,防止输出被重定向的情况*/
                 if(!isatty(STDOUT_FILENO) < 0) return -1;
                 /*获得窗口大小*/
                if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &size) < 0)
               {
                        perror("ioctl TIOCGWINSZ error");
                        return -1; 
               }
               /*输出结果*/
               printf("rows is %d, columns is %d\n", size.ws_row, size.ws_col);
    
              return 0;
     }
    复制代码

     

     
    关闭文件:
     程序完成对文件的操作后,要使用close系统调用将文件关闭,其接口头文件与函数原型如下:
     #include <unistd.h>
     int close(int fd);
     
     fd是要关闭的文件的描述符,返回值在操作成功的情况下是0,否则是-1.

    展开全文
  • linux文件IO操作

    2016-12-13 15:51:29
    说起linux编程来,甚至包括其他系统的编程,很大一部分都是处理IO操作了。特别是在linux系统上,由于一起都是文件(fd)的思想,更是扩大了文件IO的范畴。比如磁盘上文件的IO,网络IO,终端IO,管道IO等等。这些IO...

            说起linux编程来,甚至包括其他系统的编程,很大一部分都是处理IO操作了(另一个重要的部分是进程process)。特别是在linux系统上,由于一切都是文件(fd)的思想,更是扩大了文件IO的范畴。比如磁盘上文件的IO,网络IO,终端IO,管道IO等等。这些IO操作的共同点在于都是对文件描述符的操作,而且在最底层都可能是系统调用。当然如果我们考虑最多的两类IO,即文件IO和网络IO,它们的区别也很大。

           文件IO虽然也是系统调用,执行时会进入内核操作,但是往往速度是很快的,我们可以当成是一个普通函数的调用。对文件IO的操作其实我们很容易理解,全部就涉及到打开,读,写,关闭,定位到指定偏移量。对应的函数是open,read,write,close,lseek。值得注意的是这些操作都是系统调用,所以它们都是原子操作的,比如说write一段内容到某个文件,我们不必担心在此过程备中断而另一个任务去覆盖write。但是这些操作的组合确不是原子的,比如先lseek到某个位置然后write一段内容,这两个函数之间是有时间窗的,是有可能被中断的。

            文件IO在linux上是很底层的,所以linux又在上面做了一层封装,提出了标准IO的概念。标准IO引入了流(FILE对象),这些读写文件不再直接使用文件描述符(fd)了,而用一个FILE指针来操作文件,这有个好处是FILE对象是自带缓存区的,可以不必多次的进行系统调用。在c语言里,基本对文件的操纵都是通过FILE对象在操作的,在C++里更有文件IO的更高层封装,比如说fstream。思想上都是使用了流的概念。


            上图可以理解内核对文件IO准备的数据结构,此图摘自《UNIX环境高级编程》。每个进程表里有一个矢量(数组),数组的下标就是fd(所以fd其实是个短整数),每一项包含一个打开的文件fd的标志位(比如close_on_exec)以及一个指针(该指针指向文件表项);内核还为每个fd维持了一个文件表项,主要包括如图所示文件状态标志(读,写,append,同步,非阻塞等等),当前文件偏移量,v节点指针(注意,Linux系统没有v节点,直接指向的inode),另外注意,多个文件表项可能指向的同一个v节点,也就是实际打开的是同一个文件,但是他们的打开状态不同,偏移量也可能不同;最后内核为每个实际的文件准备了v节点和inode,inode真实的反映了该文件的长度,作者,在磁盘中的位置,block等等。

            总体上说来,文件IO的复杂度是不高的,基本认为读写都可以成功,而且是同步的阻塞式的读写,远远没有网络IO的复杂度高。网络IO我们这里只讨论TCP的操作,和文件IO类似,在应用层,对网络IO也是通过一个文件描述符来操作的,函数也很类似,比如也有open,read,write,close,但没有lseek,同时也多了一些操作函数,比如ioctl,fctnl等,由于得考虑双工通道的单向关闭,又多了shutdown这样的函数。说到底网络IO和文件IO的最大区别在于它是个“低速”的系统,是有可能阻塞调用进程的。正是有了这个区别,才导致网络IO异常的复杂,包括了同步,异步,阻塞,非阻塞等模式。为了提高效率,内核又有了select和epoll这样的系统调用来帮助我们。

            网络编程的操作对象也是文件描述符(fd),有一套称之为socket函数的操作来围绕这fd来处理网络IO。比如要连接对方的进程,那么必须本地先建立一个

            int fd = socket(AF_INET,SOCK_STREAM,0);

    还要去连接对端地址,对端的地址表示由ip+port来决定

            sockaddr_in serv;

            serv.sin_famiy = AF_INET;

            serv.sin_port = ????;

            serv.sin_addr = ???;

            connect(fd, (sockaddr*)&serv,sizeof(serv));

    这里都没有处理错误。光这些就很复杂了。connect不成功的话,socket还要重新生成。connect也是会阻塞的,因为connect在TCP协议层是会先发SYN包的,这期间是阻塞的(当然也可以设置成非阻塞模式,由epoll来监控),如果收到服务返回的ACK+SYN包,connect才会返回成功。如果不成功,协议层还会重试连接,这些都是应用层看不到的。所有这些都是因为网络是不可靠的,TCP是复杂的,所以网络IO随之也变得复杂起来。不像文件IO,可以像使用函数一样来使用,而网络IO必须处理失败或者超时的情况。

            目前来说主流的网络IO都是用的IO多路复用+非阻塞socket模式。注意,这也是同步的IO,异步的IO必须是一些特殊的API,我们主流的方式都是同步方式。IO多路复用就是select或epoll方式,更多的是epoll方式,我们在之前的文章有介绍过epoll(http://blog.csdn.net/coolmeme/article/details/9768847),这里不讨论细节。epoll的思想是不是阻塞于某个socket的读写,而是阻塞于一个新的系统调用,epoll_wait上,而这个系统调用的返回可以告诉我们有一个或者多个fd可读或可写,注意,epoll可以wait的不仅仅是socket的fd了,各种fd都可以被它来监控。由于epoll的高效,于是one loop per thead这个编程概念备提出来了,就是在一个线程上完成对成千上万设置上几十万的fd的活动来监控。然后由一组处理线程来实现业务操作(比如技术,数据库操作等)。这就是现代网络服务的基本模型,大同小异。

            网络IO的复杂性还在于数据是按流的方式来传输的,所以每次socket从内核提交给应用层的数据,你应用层不能立刻丢弃,因为可能不是你要的全部,你得保存下来,等到若干次read后,可能才是一个完整的包,所以一定要有应用层的buffer。这样就不能像udp那样单次无记忆的处理一个请求来的容易。

            网络IO的复杂性还有一点是来源于TCP协议的复杂性。比如三次握手,4次挥手,流量控制,NO_DELAY设置,TIME_WAIT状态(先发FIN包惹来的麻烦),其他众多的socket选项等,要全面理解可能才能写出比较能把控的网络IO程序来。

           目前文件IO和网络IO都是很成熟的技术了。通用高效的解决方案都有,我们自然也不必重新早轮子,找一些开源的项目就可以。但是我们若是理解了其中的原理和思想,对我们写应用层也是很有帮助的。

            

     

    展开全文
  • Linux文件操作学习总结

    万次阅读 2011-06-20 18:51:00
    文件类型:普通文件(文本文件,二进制文件)、目录文件、链接文件、设备文件、管道文件。 文件的权限:读、写、执行 文件的相关信息:目录结构、索引节点、文件数据索引节点的stat结构struct stat{dev_t st_dev;/...
  • 文章目录编程环境:man 手册的使用:系统函数读写文件:写一例子:阻塞和非阻塞:stat / lstat 函数 :文件属性相关的函数:目录操作相关函数:目录操作相关函数:目录遍历相关函数: dup / dup2 / fcntl 函数:下载...
  • Linux文件IO编程——底层文件I/O操作

    千次阅读 2018-08-06 14:54:00
     在Linux中对目录和设备的操作都等同于文件操作Linux中文件主要分为4种:普通文件、目录文件、链接文件和设备文件。  内核通过文件描述符来区分和引用特定的文件。对Linux而言,所有设备和文件操作都是使用...
  • 功能描述:用于打开或创建文件,在打开或创建文件时可以指定文件的属性及用户的权限等各种参数。 所需头文件:#include ,#include ,#include 函数原型:int open(const char *pathname,int flags,int perms) ...
  • Linux编程——文件操作

    千次阅读 2015-11-13 19:47:57
    文件在Linux系统中是一个广泛的概念,Linux将所有的硬件设备当作文件来处理,因此了解文件操作是十分重要的。 (一)文件和目录操作 1.stat 获取文件属性  #include  #include  #include  int stat...
  • 汇总:Linux文件操作接口

    千次阅读 2019-01-16 21:46:45
    写在前面: 文件描述符: 对于内核而言,所有打开的文件都通过文件描述符引用。... 按照惯例,UNIX系统shell使用文件描述符0与进程的标准输入相关联,文件描述符1与标准输出相关联,文件描述符2与...
  • Linux c文件操作总结

    千次阅读 2017-07-23 23:12:38
    这一周以来一直与Linux文件操作相关系统调用打交道,其与C语言中的文件操作函数有些许相似但又千差万别.尤其是open()函数的参数,相当复杂,因此作以记录便于查阅. 对于用Linux系统调用进行文件的常用操作作以总结 ...
  • 阻塞、非阻塞 读常规文件是不会阻塞的,不管读多少字节,read一定会在有限的时间内返回。从终端设备或网络读则不一定,如果从终端输入的数据没有换行符,调用read读终端设备就会阻塞,如果网络上没有接收到数据包,...
  • Linux文件操作API

    千次阅读 2014-10-29 16:27:25
    Linux文件操作API涉及到创建、打开、读写和关闭文件。 1.linux API  创建 int creat(const char *filename, mode_t mode);  参数mode指定新建文件的存取权限,它同umask...
  • Linux编程——文件 IO操作

    千次阅读 2015-08-21 08:15:21
    Linux文件 I\O 介绍  1. Linux系统调用  Linux系统调用(system call)是指操作系统提供给用户程序的一组“特殊接口”,用户程序可以通过这组“特殊”接口来获得操作系统提供的特殊服务。  为了更好的保护内核空间...
  • Linux c 文件操作杂笔

    2013-05-25 09:33:49
     linux系统基于文件,硬件、软件全部可以用文件表示,你对这个文件操作就相当于操作对应的硬件设备。linux下的/dev目录下就存放了linux的设备文件,按照他们的存取数据的方式,可以分为:字符设备,块设备,伪设备...
  • LINUX文件操作函数

    万次阅读 2009-11-10 15:13:00
    Linux文件操作API涉及到创建、打开、读写和关闭文件。1.linux API 创建int creat(const char *filename, mode_t mode); 参数mode指定新建文件的存取权限,它同umask一起决定文件的最终权限(mode&umask),其中...
  • linux环境:C编程文件操作

    千次阅读 2019-05-17 00:09:47
    linux环境:C编程文件操作C语言标准函数库文件操作函数Linux目录操作基于文件描述符的Linux文件操作基本文件操作-打开、关闭与读写MMAP文件映射 C语言标准函数库文件操作函数 打开文件:foen(文件名,打开格式) ...
  • Linux C:多进程文件操作之文件锁

    千次阅读 2016-10-19 21:07:46
    文件操作完后flock解锁,但需注意另一个进程操作同个文件时必须自己去检查文件是否已上锁,即在读写文件前调用flock函数即可进行判断,如果上锁,该进程则会阻塞,直到该文件被所占用的进程解锁。 具体程序如下: ...
  • Linux文件IO详解

    千次阅读 2018-06-04 19:47:26
    文件IO 不带缓存的IO函数:open, read, write, lseek和close。每个函数对应内核的一个...当用open,creat打开文件时,返回文件描述符,对文件的读写操作通过文件描述符进行。 按照惯例,文件描述符0与进程的标准输...
  • linux文件操作包括创建,打开,读写,定位,关闭等。在WINCE或是WINDOWS系统下,我们通常称这些接口为API函数。下面我们将分别介绍这些系统函数的使用方法。 1.1.1 创建 int creat(const char *filename, mode ...
  • 小何讲Linux: 基本文件操作和实例

    千次阅读 2016-05-06 20:52:52
    open()函数是用于打开或创建文件,在打开或创建文件时可以指定文件的属性及用户的权限等各种参数。 close()函数是用于关闭一个被打开的文件。当一个进程终止时,所有被它打开的文件都由内核自动关闭,很多程序都使用...
  • 1. open()函数 ...功能描述:用于打开或创建文件,在打开或创建文件时可以指定文件的属性及用户的权限等各种参数。 所需头文件:#include ,#include ,#include 函数原型:int open(const char *pathna
  • Linux C高级编程文件操作之系统调用 宗旨:技术的学习是有限的,分享的精神的无限的!    库函数是一些完成特定功能的函数,一般由某个标准组织制作发布,并形成一定的标准。使用库函数编写的函数一般可以...
  • linux操作系统下c语言编程入门--文件操作前言:我们在这一节将要讨论linux文件操作的各个函数.文件的创建和读写文件的各个属性目录文件的操作管道文件-----------------------------------------------------------...
  • linux 文件状态标识和IO操作方式

    千次阅读 2013-02-03 17:50:11
    转自:http://book.2cto.com/201212/11767.html 来自《UNIX/Linux程序设计教程》 文件状态标签指明文件的打开属性,它们由open()...文件状态标签中的标志可分为三类:访问方式、打开时标志和I/O操作方式。 1. 访
  • Linux文件I/O操作模型浅析 1.堵塞I/O操作模型: 举例说明如果你想从一块缓冲区或内存读数据,但是其中并没有数据,进程就会挂起等待数据准备好,直到数据准备好再进行read操作; 2.非堵塞I/O操作模型:面对缓存区...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 148,362
精华内容 59,344
关键字:

linux文件操作阻塞

linux 订阅