C++Linux下文件IO基础_Kuany_的博客-程序员宅基地

技术标签: C/C++  阻塞  c++  文件  Linux  IO  linux  

1. 系统api与库函数的关系

在这里插入图片描述
stdout里面有什么内容?

  1. fd,文件描述符,表示指向哪一个文件
  2. f_pos位置
  3. buffer缓冲区,默认是8k。缓冲区是为了减少IO操作。
    在这里插入图片描述
    观察下面的代码:
#include <stdio.h>
#include<fcntl.h>
#include<sys/types.h>
#include<unistd.h>
 
int main(){
    
	close(1);
	int fd = open("1.log", O_CREAT | O_TRUNC | O_WRONLY, 0644);
	printf("hello\n");
	fflush(stdout);
	close(fd);
	return 0;
}

代码分析:
close(1) 代表关闭标准输出。fflush(stdout);hellobuffer中刷到文件中。
因为:
系统内核区中负责虚拟文件系统、内存管理、进程管理和设备管理。其中进程管理里面我们要去了解PCB(进程控制块),我们可以把pcb看成一个结构体,结构体里面有一个文件描述符表。文件描述符表中的每个数字对应一个文件操作符,可以通过数字来控制文件。
在linux中,如果你启动一个进程,默认开启了0,1,2三个文件描述符,这三个文件描述符分别对应标准输入标准输出标准错误
在这里插入图片描述
上图中的buffer何时刷新:

  • 手动刷新
  • fclose()关闭
  • buffer满了

2. open函数

函数原型:

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

查看man 2 open

pathname 文件名
//=========================================================
flags
必选项:
	O_RDONLY 只读
	O_WRONLY 只写
	O_RDWR 读写
可选项
	O_APPEND 追加
	O_CREAT 创建文件
		O_EXCL与O_CREAT一起使用,如果文件存在,则报错。
	O_NONBLOCK 非阻塞
//=========================================================
mode权限位,最终(mode &~umask)
//=========================================================
返回值:
成功返回最小的可用文件描述符。失败返回-1,设置errno

对于flags选项
选项实际上就是一个位图。选项的接口是int,就是32位的位图。必选项中只能有一个的值标位1.
在这里插入图片描述

3. close函数

函数原型

int close(int fd);
fd 		: 	open打开的文件描述符
返回值 	:	成功返回0,失败返回-1,设置errno

利用open和close实现touch功能的实例

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
//close函数的头文件
#include<unistd.h>
 
int main(int argc, char *argv[]){
    
	if(argc!=2){
    
		printf("./a.out filename\n");
		return -1;
	}
 
	int fd=open(argv[1], O_RDONLY|O_CREAT, 0666);
	close(fd);
	return 0;
}

4. read函数

函数原型

ssize_t read(int fd, void *buf, size_t count);
fd  		文件描述符
buf  		缓冲区
count 		缓冲区大小

返回值:
失败	返回 -1,设置errno
成功	返回读到的大小
0 		代表读到文件末尾

非阻塞的情况下read返回-1,但是此时需要判断errno的值

5. write函数

函数原型

ssize_t write(int fd, const void *buf, size_t count);
fd  	文件描述符
buf 	缓冲区
count 	缓冲区大小

返回值
成功	返回写入的字节数
失败	返回-1,设置errno
0		代表未写入

使用read和write实现cat功能

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
//close函数的头文件
#include<unistd.h>
 
int main(int argc, char *argv[]){
    
	if(argc !=2){
    
		printf("./a.out filename\n");
		return -1;
	}
	int fd=open(argv[1], O_RDONLY);
 
	//读,输出到屏幕
	char buf[256];
	int ret=read(fd, buf, sizeof(buf));
	while(ret){
    
		//stdout的类型是FILE*,因此我们用数字也可以,用STDOUT_FILENO也可以
		write(STDOUT_FILENO, buf, ret);
		ret=read(fd, buf, sizeof(buf));
	}
 
	close(fd);
	return 0;
}

6. lseek函数——移动文件读写位置

函数原型

off_t lseek(int fd, off_t offset, int whence);
fd 		 	文件描述符
offset 		偏移量

whence
SEEK_SET  	文件开始位置
SEEK_CUR 	当前位置
SEEK_END 	结尾

返回值:
成功		返回当前位置到开始的长度
失败		返回-1,设置errno

lseek的作用

  • 移动文件读写位置
  • 计算文件大小
  • 拓展文件

6.1 lseek移动读写位置的例子

实现打开一个文件,写入内容:helloworld,然后读取一下该文件的内容,输出到屏幕.

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
//close函数的头文件
#include<unistd.h>
 
int main(int argc, char *argv[]){
    
	if(argc !=2){
    
		printf("./a.out filename\n");
		return -1;
	}
	int fd=open(argv[1], O_RDWR|O_CREAT, 0666);
	//此时不用考虑"\0"
	write(fd, "hello world", 11);
 
	//把文件读写位置向前移动,当前指向; hello world后面了
	lseek(fd, 0, SEEK_SET);
 
	char buf[256]={
    0};
	int ret=read(fd,buf, sizeof(buf));
 
	if(ret){
    
		write(STDOUT_FILENO, buf, ret);//STDIN_FILENO,STDERR_FILENO
	}
	close(fd);
 
	return 0;
}

6.2 lseek实现计算文件大小的例子

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
 
int main(int argc, char *argv[]){
    
	if(argc !=2){
    
		printf("./a.out filename\n");
		return -1;
	}
	int fd=open(argv[1], O_RDONLY, 0666);
 
	int ret=lseek(fd, 0, SEEK_END);
	printf("file size is:%d\n", ret);
 
	close(fd);
 
	return 0;
}

6.3 lseek扩展文件实例

创建文件,之后把文件大小拓展一下(类似迅雷下载文件,先占用空间,在进行下载时候的占用空间操作)。

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
 
int main(int argc, char *argv[]){
    
	if(argc !=2){
    
		printf("./a.out filename\n");
		return -1;
	}
	int fd=open(argv[1], O_WRONLY|O_CREAT,0666);
	//利用第二个参数offset指定文件的大小,就相当于把文件扩展了
	int ret=lseek(fd, 1024, SEEK_END);
	//需要至少写一次,否则不能扩展文件的大小
	write(fd,"a",1);
	printf("file size is:%d\n", ret);
 
	close(fd);
 
	return 0;
}

7. fcntl函数

设置非阻塞的两种方法
1、打开文件时,指定参数为非阻塞——O_NONBLOCK

int fd = open("/dev/tty",O_RDWR|O_NONBLOCK);

2、使用fcntl函数
fctl()函数用于实现部分辅助功能,比如设置非阻塞功能

函数原型:
在这里插入图片描述

int fcntl(int fd, int cmd, ... /* arg */ );

实现非阻塞功能,我们使用的参数是flags

在这里插入图片描述

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
int main(int argc,char *argv[]){
    
	O_NONBLOCK设置为非阻塞
    //int fd = open("/dev/tty",O_RDWR|O_NONBLOCK);
    int fd = open("/dev/tty",O_RDWR);
 
    //fcntl()函数 ,设置非阻塞。先利用F_GETFL获取当前的初始情况
    int flags = fcntl(fd,F_GETFL);
	//取或
    flags |=O_NONBLOCK;
    fcntl(fd,F_SETFL,flags);
 
    char buf[256];
    int ret = 0;
    while(1){
    
        ret = read(fd,buf,sizeof(buf));
        if(ret < 0){
    
            perror("read err:");
            printf("ret is %d\n",ret);
        }
        if(ret){
    
            printf("buf is %s\n",buf);
        }
        printf("haha\n");
        sleep(1);
    }
    close(fd);
    return 0;
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_44718794/article/details/106616549

智能推荐

福大软工1816 · 第三次作业 - 结对项目1_weixin_30311605的博客-程序员宅基地

031602204 陈加伟 (博客地址:https://www.cnblogs.com/Tony-chenjw/p/9683279.html)031602226 林淇(博客地址:https://www.cnblogs.com/q1093797687/p/9683571.html)pdf文档:https://files.cnblogs.com/files/q1093797687/%E4%BD%9...

HDU2044----一只小蜜蜂_cxyhss的博客-程序员宅基地

Problem Description有一只经过训练的蜜蜂只能爬向右侧相邻的蜂房,不能反向爬行。请编程计算蜜蜂从蜂房a爬到蜂房b的可能路线数。其中,蜂房的结构如下所示。Input输入数据的第一行是一个整数N,表示测试实例的个数,然后是N 行数据,每行包含两个整数a和b(0&amp;lt;a&amp;lt;b&amp;lt;50)。Output对于每个测试实例,请输出蜜蜂从蜂房a爬到蜂房b的可能路线数,每个实例的输出占一行...

mysql相关练习_igcllq的博客-程序员宅基地

一、如果主节点已经运行了一段时间,且有大量数据时,如何配置并启动slave节点在master节点创建复制用户查看二进制文件和位置mysql&gt; show master logs;+-------------------+-----------+| Log_name | File_size |+-------------------+-----------+| igcllq-bin.000001 | 177 || igcllq-bin.000002 |

【布局优化】基于鲸鱼算法实现3D无线传感器网(WSN)覆盖优化 Matlab源码_Matlab科研辅导帮的博客-程序员宅基地

​一、WSN模型​二、鲸鱼算法2.1.鲸鱼优化算法的生物机制​图1 座头鲸的泡泡捕食示意图据研究,鲸鱼大脑的某些区域有与人类相似的梭形细胞,而这些细胞负责人类的判断、情感和社会行为。鲸鱼的这种细胞数量是成年人类的两倍,这是它们聪明的主要原因。事实证明,鲸能像人类一样思考、学习、判断、交流,甚至变得情绪化,但显然它的智能水平要低得多。据观察,鲸鱼(主要是虎鲸)也能发展自己的方言。而座头鲸最有趣的地方是它们特殊的捕猎方法。这种觅食行为被称为泡泡网觅食法。座头鲸喜欢在接近.

IC后端物理实现自动化工具 OpenROAD系列(二)OpenROAD-flow-scripts(ORFS) 开发环境搭建_雪天鱼的博客-程序员宅基地

我是雪天鱼,一名FPGA爱好者,研究方向是FPGA架构探索。笔记同步在我的个人网站进行更新,欢迎来访查看。IC/FPGA 设计学习交流群号: 866169462文章目录一、安装依赖1.1 KLayout 安装1.2 下载包OpenROAD 目前是分成了 APP 和 OpenROAD-flow-scripts(ORFS) 两个部分。此系列博客(一)搭建的是 APP 的开发环境。这篇博客则介绍如何搭建 ORFS的开发环境。这里我采用的在本地搭建的方法,也可以采用使用docker镜像搭建。一、安装依

打开本地html加载网页慢,网页打开慢怎么办 影响网页打开速度因素有哪些【解决方法】..._cyx 22的博客-程序员宅基地

网页打开慢怎么办?有时候本地网络速度太慢,过多台电脑共享上网,或共享上网用户中有大量下载时也会出现打开网页速度慢的问题。下面,我们就来看看影响网页打开速度的因素。一、影响网页打开速度的因素主要有如下几方面1、网络防火墙的设置不允许多线程访问,例如目前WinXPSP2就对此默认做了限制,使用多线程下载工具就受到了极大限制,BT、迅雷都是如此。因此,同时打开过多页面也会出现打开网页速度慢的问题。2、系...

随便推点

黑客不讲武德,苹果好自为之_iOS_开发的博客-程序员宅基地

Python实战社群Java实战社群长按识别下方二维码,按需求添加扫码关注添加客服进Python社群▲扫码关注添加客服进Java社群▲整理 | 褚杏娟、Tina来源丨InfoQ(ID:i...

泛型数组列表,对象包装器,自动装箱_albedohale的博客-程序员宅基地

普通数组一旦运行起来就难以改变其大小,使用ArrayList类解决这一问题1.ArrayList类是泛型类,使用类型参数ArrayList&lt;Test1&gt; onearrlist =new ArrayList&lt;&gt;();//指明这个数组列表的元素类型是Test1类型//这个语句创建了一个泛型数组列表onearrlist.add(new Test1(...));使用add()方法将元素添加到数组列表中onearrlist.add(n,new Test1());插入中间n处,其后的元

scala视频课程_weixin_34111790的博客-程序员宅基地

2019独角兽企业重金招聘Python工程师标准&gt;&gt;&gt; ...

java swing 任务栏_Java如何在Swing中刷新窗口任务栏?_3type的博客-程序员宅基地

packageorg.nhooo.example.swing;importjavax.swing.*;importjava.awt.*;importjava.awt.event.ActionEvent;importjava.awt.event.ActionListener;publicclassWindowTaskbarFlashextendsJFrame{privateWi...

php状态监控源码,PHP服务器状态监控实现程序_江子星的博客-程序员宅基地

*/header('Content-type:text/html;charset=utf-8');include './smtp/class.smtp.php';include './smtp/class.phpmailer.php';function sendmail($subject = '',$body = '') {date_default_timezone_set('Asia/Shang...