多个进程访问同一文件的解决方法

如果多个用户对一个文件进行操作的时候?如何来解决?考虑用文件锁的形式和多路复用的形式

①文件锁

使用flock(锁定文件或解除锁定)函数

头文件#include<sys/file.h>

函数原型:int flock(int fd,int operation);

函数作用:flock()会依参数operation所指定的方式对参数fd所指的文件做各种锁定或解除锁定的动作。此函数只能锁定整个文件,无法锁定文件的某一区域。

参数

operation有下列四种情况:

LOCK_SH 建立共享锁定。多个进程可同时对同一个文件作共享锁定。

LOCK_EX 建立互斥锁定。一个文件同时只有一个互斥锁定。

LOCK_UN 解除文件锁定状态。

LOCK_NB 无法建立锁定时,此操作可不被阻断,马上返回进程。通常与LOCK_SHLOCK_EX OR(|)组合。

单一文件无法同时建立共享锁定和互斥锁定,而当使用dup()fork()时文件描述词不会继承此种锁定。

返回值返回0表示成功,若有错误则返回-1,错误代码存于errno

 

#include <sys/file.h> //flock header file

#include <unistd.h> //ftruncate header file

FILE *fin;

//读写打开一个文本文件,允许读和写

fin = fopen(szFile, "rt+");

if (!fin)

{

cout << "Fail to open the file: " << szFile << endl;

return;

}

//建立排他锁,阻塞方式

if ( (flock(fileno(fin), LOCK_EX)) < 0 )

{

cout << "Fail to lock the file: " << szFile << endl;

return;

}

本程序需要每次清空后重写

ftruncate(fileno(fin), 0); //清空文件

//写文件

......

//解除锁

if ( (flock(fileno(fin), LOCK_UN)) < 0 )

{

cout << "Fail to unlock the file: " << szFile << endl;

return;

}

fclose(fin);

 

②多路复用的方式

(1)基本概念

  IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程。IO多路复用适用如下场合:

  (1)当客户处理多个描述字时(一般是交互式输入和网络套接口),必须使用I/O复用。

  (2)当一个客户同时处理多个套接口时,而这种情况是可能的,但很少出现。

  (3)如果一个TCP服务器既要处理监听套接口,又要处理已连接套接口,一般也要用到I/O复用。

  (4)如果一个服务器即要处理TCP,又要处理UDP,一般要使用I/O复用。

  (5)如果一个服务器要处理多个服务或多个协议,一般要使用I/O复用。

  与多进程和多线程技术相比,I/O多路复用技术的最大优势是系统开销小,系统不必创建进程/线程,也不必维护这些进程/线程,从而大大减小了系统的开销。

 

(2)select函数

  该函数准许进程指示内核等待多个事件中的任何一个发送,并只在有一个或多个事件发生或经历一段指定的时间后才唤醒。函数原型如下:

int select(int maxfdp1,fd_set *readset,fd_set *writeset,fd_set *exceptset,const struct timeval *timeout)

返回值:就绪描述符的数目,超时返回0,出错返回-1

函数参数介绍如下:

1)第一个参数maxfdp1指定待测试的描述字个数,它的值是待测试的最大描述字加1(因此把该参数命名为maxfdp1),描述字012...maxfdp1-1均将被测试。

因为文件描述符是从0开始的。

2)中间的三个参数readsetwritesetexceptset指定我们要让内核测试读、写和异常条件的描述字。如果对某一个的条件不感兴趣,就可以把它设为空指针。struct fd_set可以理解为一个集合,这个集合中存放的是文件描述符,可通过以下四个宏进行设置:

void FD_ZERO(fd_set *fdset);           //清空集合

void FD_SET(int fd, fd_set *fdset);   //将一个给定的文件描述符加入集合之中

void FD_CLR(int fd, fd_set *fdset);   //将一个给定的文件描述符从集合中删除

int FD_ISSET(int fd, fd_set *fdset);   // 检查集合中指定的文件描述符是否可以读写

3timeout告知内核等待所指定描述字中的任何一个就绪可花多少时间。其timeval结构用于指定这段时间的秒数和微秒数。

struct timeval

{

    long tv_sec;   //seconds

    long tv_usec;  //microseconds

};

 

这个参数有三种可能:

1)永远等待下去:仅在有一个描述字准备好I/O时才返回。为此,把该参数设置为空指针NULL

2)等待一段固定时间:在有一个描述字准备好I/O时返回,但是不超过由该参数所指向的timeval结构中指定的秒数和微秒数。

3)根本不等待:检查描述字后立即返回,这称为轮询。为此,该参数必须指向一个timeval结构,而且其中的定时器值必须为0

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值