进程和文件共享

前几天在写基于TCP的网络银行时,想到当用进程时如何共享文件而不起冲突时,我联想到了文件锁,虽然也可以用线程来完成项目,但由于,博主是初学者,还是尝试用了一下进程来完成了这个项目.
直接上干货,冲冲冲


1.进程

我们得先了解一下进程

1.每个进程都有自己独立的一块内存空间,一个进程可以有多个线程
2.父子进程,fork之后:
父子相同处: 全局变量、.data、.text、栈、堆、环境变量、用户ID、宿主目录、进程工作目录、信号处理方式
父子不同处: 1.进程ID   2.fork返回值   3.父进程ID    4.进程运行时间    
父子进程并不共享这些存储空间,共享正文段(即代码段);因此子进程对变量的所做的改变并不会影响父进程。
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>

#define PATH "a.txt"//里面谢了 hello world

int main(){
	int fd = open(PATH,O_CREAT|O_RDWR,0644); //open在fork之前共享同一个文件描述符
	assert(fd != -1);
	char buf[128] = {};
	pid_t id = fork();
	assert(id != -1);
	if(id == 0){	//子进程
		read(fd,buf,1);
		printf("我是子进程,我打印了:%s\n",buf);
	}else{
		sleep(1); //让子进程先输出
		read(fd,buf,1);
		printf("我是父进程,我打印了:%s\n",buf);
	}
	close(fd);

	return 0;
}
我是子进程,我打印了:h
我是父进程,我打印了:e
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>

#define PATH "a.txt"//里面谢了 hello world

int main(){
	//int fd = open(PATH,O_CREAT|O_RDWR,0644);
	//assert(fd != -1);
	char buf[128] = {};
	pid_t id = fork();
	assert(id != -1);
	int fd = open(PATH,O_CREAT|O_RDWR,0644);
	assert(fd != -1);

	if(id == 0){	//子进程
		read(fd,buf,1);
		printf("我是子进程,我打印了:%s\n",buf);
		close(fd);//各自关闭自己进程的文件描述符
	}else{
		sleep(1);
		read(fd,buf,1);
		printf("我是父进程,我打印了:%s\n",buf);
		close(fd);//同上关闭文件描述符
	}
	//close(fd);

	return 0;
}
我是子进程,我打印了:h
我是父进程,我打印了:h

结论:由上可知在fork之前的open打开的文件描述符共享,也就是说对同一个文件描述符进行操作时,其V-node结点会发生偏移.而在fork之后的open就相当于父子进程各自产生一个文件表,他们的文件描述符可能相同也可能不相同,要看之前各自进程是否有对文件描述进行操作.

2.进程和文件锁

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

#define PATH "a.txt"//里面谢了 hello world

int w_lock(int fd){
	struct flock lock = {};
	lock.l_type = F_WRLCK;
	lock.l_whence = SEEK_SET;
	lock.l_start = 0;
	lock.l_len = 0;
	lock.l_pid = -1;
	return fcntl(fd,F_SETLKW,&lock);
}
int un_lock(int fd){
	struct flock lock = {};
	lock.l_type = F_UNLCK;
	lock.l_whence = SEEK_SET;
	lock.l_start = 0;
	lock.l_len = 0;
	lock.l_pid = -1;
	return fcntl(fd,F_SETLK,&lock);
}
int main(){
	int fd = open(PATH,O_CREAT|O_RDWR,0644);
	assert(fd != -1);
	w_lock(fd);
	char buf[128] = {};
	pid_t id = fork();
	assert(id != -1);
	if(id == 0){	//子进程
		read(fd,buf,1);
		printf("我是子进程,我打印了:%s\n",buf);
	//	close(fd);
	}else{
	//	sleep(1);
		read(fd,buf,1);
		printf("我是父进程,我打印了:%s\n",buf);
	//	close(fd);
	}
	sleep(1);
	un_lock(fd);
	getchar();
	close(fd);

	return 0;
}
结果为父子进程一起打印,并没有产生影响
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>

#define PATH "a.txt"//里面谢了 hello world

int w_lock(int fd){
	struct flock lock = {};
	lock.l_type = F_WRLCK;
	lock.l_whence = SEEK_SET;
	lock.l_start = 0;
	lock.l_len = 0;
	lock.l_pid = -1;
	return fcntl(fd,F_SETLKW,&lock);
}
int un_lock(int fd){
	struct flock lock = {};
	lock.l_type = F_UNLCK;
	lock.l_whence = SEEK_SET;
	lock.l_start = 0;
	lock.l_len = 0;
	lock.l_pid = -1;
	return fcntl(fd,F_SETLK,&lock);
}
int main(){
	char buf[128] = {};
	pid_t id = fork();
	assert(id != -1);
	int fd = open(PATH,O_CREAT|O_RDWR,0644);
	assert(fd != -1);
	w_lock(fd);
	if(id == 0){	//子进程
		read(fd,buf,1);
		printf("我是子进程,我打印了:%s\n",buf);
	//	close(fd);
	}else{
		sleep(1);
		read(fd,buf,1);
		printf("我是父进程,我打印了:%s\n",buf);
	//	close(fd);
	}
	sleep(1);
	un_lock(fd);
	getchar();
	close(fd);

	return 0;
}
结果为先打印父进程,随后才打印子进程,受到了文件锁的影响.

所以我们项目在用进程时,要考虑open的顺序,我建议在fork之前,然后每次使用read和write时lseek偏移到文件开始操作.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值