文件I/O 小小经验谈

本文详细讲解了Linux下的文件描述符概念,包括其作用、范围以及常见文件描述符。此外,探讨了进程能打开的文件描述符数量,提供了查看和修改上限的方法。还介绍了文件I/O操作,如打开、创建、关闭、读写文件及文件指针偏移的实例。
摘要由CSDN通过智能技术生成

愿打开此篇对你有所帮助。

在这里插入图片描述


Linux下的文件

引用一句经典的话:“UNIX下一切皆文件”。
文件是一种抽象机制,它提供了一种方式用来存储信息以及在后面进行读取。

在创建一个文件后,它会给文件一个命名。当进程终止时,文件会继续存在,并且其他进程可以使用名称访问该文件。

文件描述符

在Linux下用文件描述符来表示普通文件和设备文件。文件描述符是一个整型的数据,所有对文件的操作都通过文件描述符完成。
文件描述符是文件系统中连接用户和内核空间的枢纽,当打开和创建一个文件的时候,内核空间会创建相应的结构,并生成一个整型的变量传递给用户空间的对应进程。进程通过这个文件描述符对文件进行操作。

文件描述符的范围是0~OPEN_MAX,因此是一个有限的资源,在使用完之后要及时的释放。
文件描述符仅在一个同一个进程中有效,即不同进程的文件描述符,同一个值可能描述的是不同的文件!!!

在Linux系统中有三个已经被分配的文件描述符,分别是:

0 STDIN_FILENO  标准输入流
1 STDOUT_FILENO	标准输出流
2 STDERR_FILENO 标准错误流

这三个文件描述符和它们各自的功能是绑死的。


一个进程能开多少文件描述符?

俗话说,手中有粮,心中不慌嘛,那我要连自己能开多少文件描述符都不知道,那咋整?都说Linux下一切皆文件,我要高并发的时候那描述符是蹭蹭蹭的往上涨啊。

查看进程可打开文件描述符上限:ulimit -n,1024个。
临时修改:ulimit -n 10000,改成1W个了。

永久修改:

编辑/etc/security/limits.conf 文件,在最后加入如下两行

*                               soft    nofile  65536
*                               hard    nofile  65536

请注意上面两行原样复制,不要自作聪明,勿信网传,耗子尾汁。

然后可以选择重新登录,也可以选择重启。

注:修改上限:cat /proc/1/limits |grep "Max open files",这个是init进程的值。

查看一个进程能打开多少文件描述符的另一个方法:

cat /proc/这里填pid/limits |grep "Max open files"

文件I/O操作

打开/创建文件

在Linux下,用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);

//一般用fd接收返回值
//返回值 :成功返回重新分配的文件描述符,出错则返回-1并设置errno

好多语言基本都是这个函数吧,第一个文件名,第二个打开模式,第三个,是文件权限。

打开模式:

O_RDONLY	只读
O_WRONLY	只写
O_RDWR		读写
O_APPEND	追加
O_CREAT		有就开,没就建。
O_EXCL		查看文件是否存在,如果同时指定了O_CREAT的话,那文件存在就报错。
O_TRUNC		如果文件存在,则将清空文件。

O_NONBLOCK	打开文件为非阻塞方式。默认为阻塞,即对文件的读写需要等待操作状态返回

最后的那个mode。只有在O_CREAT存在的时候才能使用。
(如果是新建文件,建议带上权限,不然不确定会有什么情况发生)

create函数可以理解问open函数的一个特例:

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

create配上O_EXCL可提高程序的容错性。


关闭文件

#include <unistd.h>

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

读取/写入文件

read函数从打开的文件中读取数据
write函数向打开的文件中写入数据

#include <unistd.h>

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

//返回值:成功返回读取/写入的字节数,失败返回-1并设置errno。

/*
buf:缓存,一般用char数组
count:要读取/写入的字节数
*/

ssize_t是一个可能不同于int、long类型的符号数,它在具体实现是可能定义为 int 或 long。


文件指针偏移

lseek()函数可以设置文件偏移量的位置。

#include <sys/types.h>
#include <unistd.h>

off_t lseek(int fd,off_t offset,int whence);
//这里允许偏移超过文件末尾,中间空出来的位置都是0.

/*
offset:文件偏移量,可以为负数
whence:操作模式
*/

操作模式:

若:SEEK_SET,offset为相对文件开始处的位置
若:SEEK_CUR,offset为相对当前位置的位置
若:SEEK_END,offset为相对文件结尾的位置

函数执行成功时返回文件的偏移量,所以可以在SEEK_CUR模式下偏移0个位置,以获取当前的偏移量


测试代码示例

#include<sys/types.h>
#include<sys/stat.h>
#include<iostream>
#include<unistd.h>
#include<fcntl.h>

using namespace std;

int main(){
	char* buf = new char[8];	//can't alloc 1024?
	int fd = open("./fileIO.txt", O_CREAT|O_RDWR|O_APPEND);
	
	//chmod("fileIO.txt",644);
	//const char* filename
	//flag O_CREAT|O_RDONLY|O_WRONLY|O_RDWR|O_APPEND


	if(fd<0){
		cout<<"open file failed!"<<endl;
	}

	int m = write(fd,"test\n",50);
	//int file_id
	//char* buf
	//int lenth
	//return real lenth

	cout<<m<<endl;
	
	close(fd);

	fd = open("./fileIO.txt",O_RDONLY);
	int n = read(fd,buf,500);
	//char* buf (empty buf)	

	cout<<n<<endl;
	printf("%s\n",buf);
	close(fd);
	return 0;
}

注:用open函数创建文件并保存关闭之后,文件出现了 S 和 T 的权限位,一开始不知道这两个权限位是什么,一查才知道这两个权限位不是什么好东西。

但是,奇怪的是,这个bug不好复现,什么时候出现全看它心情。。。

经验:以后创建文件的时候,要顺道把权限位设置了,用代码设置,不要手动

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

看,未来

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值