Linux操作与管理文件(多次打开同一文件,文件共享,fcntl函数,标准IO库)

本文介绍了Linux系统下文件管理的基本概念,包括inode和vnode的作用,以及如何通过fd进行文件的读写操作。同时,还详细讲解了文件共享的三种方式,并提供了dup、dup2及fcntl函数的具体使用示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.linux系统如何管理文件

硬盘中的静态文件和inode:

(1)硬盘分为两大区域:一个是硬盘内容管理表项,另一个是真正存储内容的区域。先去读取硬盘内容管理表,找到要访问的存储内容的区域,再用得到我们要的文件。

(2)每一个文件有一个信息列表(叫inode,i节点,其实质是一个结构体,有很多元素,每个元素记录了这个文件的信息,有包括文件名、扇区号、块号等信息)

内存中被打开的文件和vnode:

(1)在程序中打开的文件属于某个进程,进程有对应的进程信息表,表中的指针会指向文件管理表,文件管理表中记录了当前进程的相关信息
(2)文件的管理结构体vnode记录了一个被打开的文件的各种信息。


1.多次打开同一文件

(1)设置fd1,fd2读取文件,经过实验验证,证明了结果是fd1和fd2分别读

(2)设置fd1,fd2写入文件,经过实验验证,证明了结果是fd1和fd2分别写

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



int main(int argc, char *argv[])
{
	int fd1 = -1, fd2 = -1;		// fd 就是file descriptor,文件描述符
	char buf[100] = {0};       //用来存放读取文件内容的buf
	char writebuf[20] = "l love linux";   
	int ret = -1;
	
	// 第一步:打开同一个文件,返回两个文件描述符
    fd1 = open("a.txt", O_RDWR | O_TRUNC | O_CREAT , 0666);
	fd2 = open("a.txt", O_RDWR | O_TRUNC | O_CREAT , 0666);
	if ((-1 == fd1) || (fd2 == -1))		
	{
		perror("文件打开错误");
		_exit(-1);
	}
	else
	{
		printf("文件打开成功,fd1 = %d. fd2 = %d.\n", fd1, fd2);
	}
	
#if 0  //先关掉写文件
	while (1)
	{
		// 写文件
		ret = write(fd1, "ab", 2);
		if (ret < 0)
		{
			perror("write失败");
			_exit(-1);
		}
		else
		{
			printf("write成功,写入了%d个字符\n", ret);
		}
		ret = write(fd2, "cd", 2);
		if (ret < 0)
		{
			perror("write失败");
			_exit(-1);
		}
		else
		{
			printf("write成功,写入了%d个字符\n", ret);
		}
		sleep(1);
	}	
#endif

#if 1        //先打开读文件
	while(1)
	{
		// 读文件fd1
		memset(buf, 0, sizeof(buf));      //先清空用来存放读取内容的buf
		ret = read(fd1, buf, 2);         
		if (ret < 0)
		{
			printf("read失败\n");
			_exit(-1);
		}
		else
		{	
			printf("fd1:[%s].\n", buf);
		}
		
		sleep(1);
		
		// 读文件fd2
		memset(buf, 0, sizeof(buf));
		ret = read(fd2, buf, 2);
		if (ret < 0)
		{
			printf("read失败\n");
			_exit(-1);
		}
		else
		{	
			printf("fd2:[%s].\n", buf);
		}
		
	}
	
#endif	
	// 第三步:关闭文件
	close(fd1);
	close(fd2);
	
	_exit(0);
}

(3)有时候我们希望接续写而不是分别写?办法就是在open时加O_APPEND标志即可,对文件的读写是原子操作。


2.文件共享的实现方式

(1)文件共享就是同一个文件被多个独立的读写体去同时操作。
(2)常见的有3种文件共享的情况:第一种同一个进程中多次使用open打开同一个文件第二种是在不同进程中去分别使用open打开同一个文件(这时候因为两个fd在不同的进程中,所以两个fd的数字可以相同也可以不同),第三种情况是后面要学的,linux系统提供了dup和dup2两个API来让进程复制文件描述符。

(3)dup和dup2函数

使用dup进行文件描述符复制:会返回一个新的文件描述符

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

#define FILENAME	"1.txt"

int main(void)
{
	int fd1 = -1, fd2 = -1;
	
	fd1 = open(FILENAME, O_RDWR | O_CREAT | O_TRUNC, 0644);
	if (fd1 < 0)
	{
		perror("open");
		return -1;
	}
	printf("fd1 = %d.\n", fd1);
	
	close(1);		// 1就是标准输出stdout
	
	// 复制文件描述符
	fd2 = dup(fd1);		// fd2一定等于1,因为前面刚刚关闭了1,这句话就把
	if (fd2 < 0)        // 1.txt文件和标准输出就绑定起来了,所以以后输出
	{                   // 到标准输出的信息就可以到1.txt中查看了。
		perror("dup");
		return -1;
	}                   
	                   				
	printf("fd2 = %d.\n", fd2);
	printf("this is for test\n");
	
	close(fd1);
	return -1;
}

dup2复制的文件描述符:dup2允许用户指定新的文件描述符的数字

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

#define FILENAME	"1.txt"

int main(void)
{
	int fd1 = -1, fd2 = -1;
	
	fd1 = open(FILENAME, O_RDWR | O_CREAT | O_TRUNC, 0644);
	if (fd1 < 0)
	{
		perror("open");
		return -1;
	}
	printf("fd1 = %d.\n", fd1);
	
	
	fd2 = dup2(fd1, 16);
	printf("fd2 = %d.\n", fd2);

	while (1)
	{
		write(fd1, "aa", 2);
		sleep(1);
		write(fd2, "bb", 2);
	}

	close(fd1);
	return -1;
}


3.fcntl函数
(1)fcntl的常用cmd,F_DUPFD这个cmd的作用是复制文件描述符(作用类似于dup和dup2)

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

#define FILENAME	"1.txt"

int main(void)
{
	int fd1 = -1, fd2 = -1;
	
	fd1 = open(FILENAME, O_RDWR | O_CREAT | O_TRUNC, 0644);
	if (fd1 < 0)
	{
		perror("open");
		return -1;
	}
	printf("fd1 = %d.\n", fd1);

	fd2 = fcntl(fd1, F_DUPFD, 6);
	printf("fd2 = %d.\n", fd2);

	while (1)
	{
		write(fd1, "aa", 2);
		sleep(1);
		write(fd2, "bb", 2);
	}

	close(fd1);
	return -1;
}


4.标准IO库

(1)标准IO是C库函数,而文件IO是linux系统的API

(2)常见的标准IO库函数有:fopen、fclose、fwrite、fread、ffulsh、fseek

读文件代码:

#include <stdio.h>		// standard input output
#include <stdlib.h>
#include <string.h>


#define FILENAME	"1.txt"

int main(void)
{
	FILE *fp = NULL;
	size_t len = -1;
	char buf[100] = {0};        //用来储存读取文件的内容
	
	fp = fopen(FILENAME, "r+");
	if (NULL == fp)
	{
		perror("fopen");
		exit(-1);
	}
	printf("fopen success. fp = %p.\n", fp);
	
	// 在这里去读文件
	memset(buf, 0, sizeof(buf));
	len = fread(buf, 1, 10, fp);
	printf("len = %d.\n", len);
	printf("buf is: [%s].\n", buf);
	
	fclose(fp);
	return 0;
}

写文件代码:

#include <stdio.h>		// standard input output
#include <stdlib.h>
#include <string.h>


#define FILENAME	"1.txt"

int main(void)
{
	FILE *fp = NULL;
	size_t len = -1;
	int array[10] = {1, 2, 3, 4, 5};
fp = fopen(FILENAME, "w+");
	if (NULL == fp)
	{
		perror("fopen");
		exit(-1);
	}
	printf("fopen success. fp = %p.\n", fp);
	
	// 在这里去写文件
	len = fwrite(array, 4, 10, fp);
	printf("len = %d.\n", len);
		
	fclose(fp);
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

嵌入式_笔记

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

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

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

打赏作者

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

抵扣说明:

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

余额充值