Linux系统编程——文件I/O

文件描述符

  • 系统调用中操作I/O的函数但是针对文件描述符的

  • 文件描述符(file descriptor)通常是一个小的非负整数,内核用以标识一个特定进程正在访问的文件。当打开一个现有文件创建一个新文件时,内核向进程返回一个文件描述符。

  • 文件描述符 0 与 进程的标准输入(standard input)关联

  • 文件描述符 1标准输出(standard output)关联

  • 文件描述符 2标准错误(standard error)关联

    #define STDIN_FILENO  0 //标准输入的文件描述符
    
    #define STDOUT_FILENO 1 //标准输出的文件描述符
    
    #define STDERR_FILENO 2 //标准错误的文件描述符
    
    
  • 0,1,2对应的物理设备: 键盘,显示器,显示器。

  • 文件描述符的作用域仅为当前进程

  • Linux 中一个进程最多只能打开 NR_OPEN_DEFAULT (即1024)个文件

系统调用I/O函数

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);
    int creat(const char *pathname,mode_t mode);
    
  • 参数:

  1. pathname:要打开或创建的文件名称。(含路径,缺省为当前路径)

  2. flags:标志位,指定打开文件的操作方式。(前三个常量必须指定且只能指定一个)

    flags 解释
    O_REONLY 只读方式打开文件
    O_WRONLY 可写方式打开文件
    O_RDWR 读写方式打开文件
    O_CREAT 如果文件不存在时就创建一个新文件,并用第三个参数为其设置权限。
    O_EXCL 如果使用O_CREAT 时文件存在,则可返回错误信息。这一参数可测试文件是否存在。
    O_NOCTTY 使用本参数时,如文件为终端,那么终端不可以作为调用open ()系统调用的那个进程的控制终端。
    O_TRUNC 如文件已经存在,并且以只读或只写成功打开,那么将其长度截短为0。
    O_APPEND 以添加方式打开文件,在打开文件的同时,文件指针指向文件末尾。
  • 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 代表其他用户具有可执行的权限。
  • 返回值:若成功返回文件描述符,否则返回-1并设置变量errno的值。

  • 示例:

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {	
    	int fd = open("./file1",O_RDWR); //打开名为"file1"的文件
    	if(fd == -1){
    		printf("open file1 failed\n");
    		fd = open("./file1",O_RDWR|O_CREAT,0600); //没有此文件则创建,6为可读可写
    		if(fd > 0){
    			printf("file1 creat success!\n");
    		}
    	}
    	close(fd);
    	return 0;
    }
    

2.write(把指定数目的数据写入文件)

  • 头文件:

    #include <unistd.h>
    
  • 函数原型:

    ssize_t write(int fd, const void *buf, size_t count);
    
  • 各参数及返回值的含义如下:

    • fd:要写入文件的描述符。

    • buf:要写入的数据。

    • count:要写入数据的字节数。

    • 返回值:若成功返回已写的字节数,出错则返回-1并设置变量errno的值。

  • size_t是无符号整型,ssize_t是有符号整型

3.read(把指定数目的数据读文件)

  • 头文件:

    #include <unistd.h>
    
  • 函数原型:

    ssize_t read(int fd, void *buf, size_t count);//从文件描述符fd读取count个字节的数据到从buf开始的缓冲区中。
    
  • 各参数及返回值的含义如下:

    • fd:要读取的文件的描述符。

    • buf:读取到的数据放入的缓冲区。

    • count:读取到的字节数。

    • 返回值:若成功返回读到的字节数,若已到文件结尾则返回0,若出错则返回-1并设置变量errno的值。

4.lseek(移动读、写指针位置)

  • 头文件:

    #include <sys/types.h>
    #include <unistd.h>
    
  • 函数原型

    off_t lseek(int fildes, off_t offset, int whence);
    
  • 各参数及返回值的含义如下:

    • filder:文件的描述符。

    • offset:offset个字节(可正可负)

    • whence:文件偏移量设置方式

    意义
    SEEK_SET 将文件偏移量设置在距文件开始处offset个字节
    SEEK_CUR 将文件偏移量设置在其当前值加offset个字节
    SEEK_END 将文件偏移量设置为文件长度加offset个字节
    • 返回值:若成功偏移则返回new file offset,若出错则返回-1并设置变量errno的值。

5.close(关闭一个文件描述符)

  • 头文件:

    #include <unistd.h>
    
  • 函数原型

    int close(int fd);
    
  • fd:要关闭的文件的描述符。

  • 返回值:若成功返回0,出错则返回-1。

  • 当close关闭动态文件时,close内核将内存中动态文件内容去更新块设备中的静态文件。

小技巧:利用lseek计算文件大小

lseek(fd,0,SEEK_SET);
int filesize = lseek(fd,0,SEEK_END);
printf("file's size is:%d\n",filesize);

函数使用示例

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{	
	int fd;
	char* buf = "NB 666 my baby!";	
	
	fd = open("./file1",O_RDWR);
	if(fd == -1){
		printf("open file1 failed\n");
		fd = open("./file1",O_RDWR|O_CREAT,0600);
		if(fd > 0){
			printf("file1 creat success!\n");
		}
	}
	printf("open success fd:%d\n",fd);
	
	int n_write = write(fd,buf,strlen(buf));
	if (n_write != -1){
		printf("write %d Byte to file\n",n_write);
	}

	lseek(fd,0,SEEK_SET);
	
	char *readBuf = (char*) malloc(sizeof(n_write+1));
	int n_read = read(fd,readBuf,n_write);
	printf("read:%d byte\n context:%s\n",n_read,readBuf);
	close(fd);

	return 0;
}

小应用:实现Linux下cp命令

功能:将文件1拷贝到文件2,没有文件2则创建文件2

./mycp src.c des.c

代码:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc,char **argv)
{	
	int fdSrc; //文件1
	int fdDes; //文件2

	if(argc != 3){     //一共三个参数
		printf("pararm error!\n");
		exit(-1);
	}	
	
	fdSrc = open(argv[1],O_RDWR);   //打开文件1
	if(fdSrc == -1){
		printf("no '%s' file\n",argv[1]);
		
	}
	
	lseek(fdSrc,0,SEEK_SET);
    int filesize = lseek(fdSrc,0,SEEK_END);//计算文件1大小
	
	lseek(fdSrc,0,SEEK_SET);  //将文件1内容读到开辟的buf内
	char *readBuf = (char*) malloc(filesize+1);
    int n_read = read(fdSrc,readBuf,filesize);
        
	
	fdDes = open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0600);  //将buf内容写入文件2
	int n_write = write(fdDes,readBuf,strlen(readBuf));


	close(fdSrc);
	close(fdDes);
	free(readBuf);

	return 0;
}

posted @ 2021-08-11 10:44  rain土  阅读(123)  评论(0)    收藏  举报