(1)c 语言中文件操作回顾
C语言操作文件分为三步
1)打开文件
2)读写文件
3)关闭文件。
有 FILE fopen ( const char * filename, const char * mode );*
filename: 文件名,包括路径,如果不显式含有路径,则表示当前路径。
mode:文件打开模式,指出对该文件可进行的操作。常见的打开模式如 “r” 表示只读, “w” 表示只写,“rw” 表示读写,“a” 表示追加写入。
返回值: 打开成功,返回该文件对应的 FILE 类型的指针; 打开失败,返回 NULL。故需定义 FILE 类型的指针变量,保存该函数的返回值。
int fclose ( FILE * stream );
strem : 指向要关闭流对象的指针。
返回值:如果流被成功关闭,返回0值。失败是,返回EOF(-1)。
size_t fread(void buffer,size_t size,size_t count, FILE stream);
buffer:存放从文件中读取的数据; size:每个单元数据的字节数; count:总共读取多少个单元数据; stream:读取数据的文件指针。
返回值 :读取成功的单元数据个数,非常重要。如果这个值少于 count 则可以判断文件已经全部 读完
*size_t fwrite(const void*buffer,size_t size,size_t count,FILE stream);
buffer: 写入文件中的数据; size:每个单元数据的字节数; count:总共写入多少个单元数据; stream:写入的文件指针。
返回值:写入成功的单元数据个数。
等函数;
(2)Linux中与文件操作有关的系统调用
参数介绍
pathname:将要打开的文件路径和名称
flags : 打开标志,如 O_WRONLY 只写打开
O_RDONLY 只读打开
O_RDWR 读写方式打开
O_CREAT 文件不存在则创建
O_APPEND 文件末尾追加
O_TRUNC 清空文件,重新写入
mode: 权限 如:“0600” 0是八进制,6是 r+w -> 4+2 , 0 : 无权限
// ugo u:表示属主 g:表示同一组用户o:表示其他用户访问权限返回值:为文件描述符二、读文件
**ssize_t read(int *fd, const void buf,size_t count);
参数介绍
fd 对应打开的文件描述符
buf 存放数据的空间
count 计划一次从文件中读多少字节数据
返回值:为实际读到的字节数
**ssize_t write(int *fd, const void buf,size_t count);
参数介绍
fd** 对应打开的文件描述符
buf 存放数据的空间
count 计划一次向文件中写多少字节数据
返回值:为实际写入的字节数
int **close(**int fd);
参数介绍
fd 要关闭的文件描述符
举例:
结果:
fd (文件描述符 )的值一定大于等于3,这是因为
操作系统为每一个进程维护了一个文件描述符表,该表的索引值都从从0开始的,其中0、1、2分别为标准输入、标准输出和标准错误输出的文件描述符
1.QS: 父进程先打开一个文件,fork 后子进程是否可以共享使用?
结论: 可以共享使用
#include
#include
#include
#include
#include
#include
int main()
{
char buff[128] = {0};
//file.txt 内容为“BCDF”
int fd = open("file.txt",O_RDONLY);
pid_t pid = fork();
assert( pid != -1 );
if ( pid == 0 )
{
read(fd,buff,1);
printf("child buff=%s\n",buff);
sleep(1);
read(fd,buff,1);
printf("child buff=%s\n",buff);
}
else
{
read(fd,buff,1);
printf("parent buff=%s\n",buff);
sleep(1);
read(fd,buff,1);
printf("parent buff=%s\n",buff);
}
close(fd);
}
由于 fork 创建的子进程的 PCB 是拷贝父进程的,子进程的 PCB 中的文件表指向打开文件的指针只是拷贝了父进程 PCB 中的值,所以父子进程会共享父进程 fork 之前打开的所有文件描述符,所以父子进程不会对同一数据重复读取。
父子进程文件描述符指向同一个struct.file,其中的引用计数为2,为避免同一个文件多次关闭,只有当引用计数减一为0是才真正关闭文件。
2.先fork(),后打开文件
#include
#include
#include
#include
#include
#include
int main()
{
char buff[128] = {0};
int fd;
pid_t pid = fork();
assert( pid != -1 );
if ( pid == 0 )
{
sleep(1);
//file.txt 内容为“BCDF”
fd = open("file.txt",O_RDONLY);
read(fd,buff,1);
printf("child buff=%s\n",buff);
read(fd,buff,1);
printf("child buff=%s\n",buff);
}
else
{
sleep(1);
//file.txt 内容为“BCDF”
fd = open("file.txt",O_RDONLY);
read(fd,buff,1);
printf("parent buff=%s\n",buff);
read(fd,buff,1);
printf("parent buff=%s\n",buff);
}
close(fd);
}
#include
#include
#include
#include
int main()
{
char* p = '1';
for( ; p!=NULL;)
{
p=(char*)malloc(1024*1024*1024);
if(p != NULL) memset(p,0,1024*1024*1024);
else
printf("malloc error");
sleep(3);
}
exit(0);
}
有两种情况下会失败
1.剩余内存足够,但是没有满足条件的连续空间,将申请失败
2.申请空间大于物理内存空间+虚拟内存空间,那么申请空间将失败
代码中我们未进行free()操作,当可用内存不够malloc时,系统会自动杀死进程,然后回收该进程的占用的空间。
如图:
QS: fork()前malloc,父子进程是共享同一块堆区空间还是各自拥有一块?
#include
#include
#include
#include
int main()
{
char* p=(char*)malloc(1024*1024*1024);
if(p == NULL) printf("malloc error");
pid_t pid = fork();
if(pid == -1)
{
printf("error fork!\n");
}
if(pid == 0)
{
strcpy(p,"child\n");
printf("child: %s",p);
}
else
{
strcpy(p,"parents\n");
printf("parent: %s",p);
}
sleep(3);
free(p);
exit(0);
}