一、文件描述符
1.文件I/O操作函数
系统调用函数:
(1)open
-
函数原型:
int open(const char *pathname,int flags,mode_t mode);
第一个参数为文件名,第二个参数为按照上面方式打开,第三个时如果文件不存在要创建文件的权限。 -
flags:
打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算,构成flags。 -
参数:
O_RDONLY:只读打开。
O_WRONLY:只写打开。
O_RDWR:读,写打开。
三个中选一个且只能选一个。
O_CREAT:若文件不存在,则创建它。需要mode选项,来指明文件的访问权限。
O_APPEND:追加写。 -
返回值:
成功:新打开的文件描述符。
失败:-1。
(2)write -
函数原型:
ssize_t write(int fd,const void *buf,size_t count);//从指定空间获得数据放在指定文件夹中,第一个参数是文件描述符,第二个是指定空间,第三个是一次读取字节的大小
C库函数:
ssize_t read(int fd,void *buf,size_t count);//count为0,返回值为0
size_t fread(void *buffer,size_t size,size_t count,FILE *stream);
//从一个二进制方式打开的文件获取数据放在指定空间,返回值是实际读取文件的大小。
size_t fwrite(const void *buffer,size_t size,size_t count,FILE *stream);
//从指定空间获取数据放在指定文件中
#include <stdio.h>
#include <string.h>
int main()
{
FILE *fp = fopen("myfile","w");
if(NULL == fp)
{
perror("fopen");
}
const char *ptr = "hello world!!\n";
int count = 5;
while(count--)
{
fwrite(ptr,sizeof(char),strlen(ptr),fp);
}
fclose(fp);
return 0;
}
结果如下:
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
umask(0);//在创建新文件或者目录时,屏蔽掉新文件或目录不应有的访问允许权限。
int fd = open("myfile",O_WRONLY|O_CREAT,0644);
if(fd<0)
{
perror("open");
return 1;
}
int count = 5;
const char* msg = "hello world!!!\n";
while(count--)
{
write(fd,msg,strlen(msg));
}
close(fd);
return 0;
}
结果如下:
2.三大缓冲机制:
(1)全缓冲:全缓冲指的是系统在填满标准IO缓冲区之后才进行的实际IO操作;注意,对于驻留在磁盘上的文件来说通常是由标准IO库实施全缓冲。
(2)行缓冲:在这种情况下,标准IO在输入和输出中遇到换行符时进行IO操作;注意,当流涉及终端的时候,通常使用的是行缓冲。
(3)无缓冲:无缓冲指的是标准IO库不对字符进行缓冲存储;
注意,标准出错流stderr通常是无缓冲的。
3.文件描述符:
(1)概念:
文件描述符就是一个从0开始的整数(没有负数),当我们要打开文件时,操作系统就要管理文件(先描述,后组织),就要在内存中创建相应的数据结构(file结构体),而一个进程默认要打开三个文件,所以进程PCB中要有一个file指针,指向一张表file_struct*,该表最重要的部分就是包含一个文件指针数组,每一个元素都是指向打开文件的指针,所以本质上,文件描述符就是该数组的下标;
注:因为一个进程默认打开三个文件,(0–stdin,1–stdout,2–stderr),所以进程中打开文件,文件描述符默认是从3开始的。
(2)扩展:
- 查看该本机最大打开文件描述符数:
cat /proc/sys/fs/file-max
- 显示当前文件描述符:
ulimit -n
- 修改当前用户环境下的文件描述符为65536:
ulimit -HSn 65536
- 使用ulimit命令的缺点:
i)只能修改当前登录用户环境下的文件描述符,如果此用户来另外打开一个连接,此链接环境的文件描述符依然是没改前的。
ii)如果系统重启,以前修改都不再生效。 - 改进:
i)编辑/etc/security/limits.conf 文件,在最后加入如下两行:
soft nofile 65536
hard nofile 65536
保存退出,都不需要重启服务器,直接重新登陆用ulimit -n就能看到效果,这样无论使用哪个用户,无论是否重启都不会失效了。