文件锁以及多路复用方式解决多个用户对一个文件的操作

一、 文件锁用于多个用户共同使用或操作同一个文件。有读锁的时候可以再加读锁,不能再加写锁。有写锁的时候,不能加任何锁,加读锁时,该描述符必须是读打开,加写锁时,该描述符必须是写打开, 且只在进程间有用。   

使用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 
   
   
    
    

int lock_set(int fd, int type)
{
    struct flock lock;

    lock.l_type = type;
    lock.l_start = 0;
    lock.l_whence = SEEK_SET;
    lock.l_len = 0;
    lock.l_pid = -1;

    fcntl(fd, F_GETLK, &lock);
    if(lock.l_type != F_UNLCK)
    {
        if(lock.l_type == F_RDLCK)
	{
	    printf("Read lock already set by %d\n", lock.l_pid);
	}
	else if(lock.l_type == F_WRLCK)
	{
	    printf("Write lock already set by %d\n", lock.l_pid);
	}
    }
    lock.l_type = type;
    if(fcntl(fd, F_SETLKW, &lock) < 0)
    {
        printf("lock failed :type = %d\n", lock.l_type);
    }

    switch(lock.l_type)
    {
        case F_RDLCK:
	    printf("read lock set by %d\n", getpid());
	    break;
	case F_WRLCK:
	    printf("write lock set by %d\n", getpid());
	    break;
	case F_UNLCK:
	    printf("UN lock set by %d\n", getpid());
	    break;
	default:
	    break;
    }
}
   
   

上写锁:

#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
        
        
#include 
        
        
         
         
#include "set_lock.h"

int main()
{
    int fd;
    fd = open("readme", O_RDWR | O_CREAT, 0666);
    if(fd < 0)
    {
        printf("Open file error\n");
	exit(1);
    }
    lock_set(fd, F_WRLCK);
    getchar();
    lock_set(fd, F_UNLCK);
    getchar();

    return 0;
}
        
        
       
       
      
      
     
     

上读锁:
#include 
      
      
       
       
#include 
       
       
        
        
#include 
        
        
         
         
#include 
         
         
          
          
#include "set_lock.h"

int main()
{
    int fd;
    fd = open("readme", O_RDWR | O_CREAT, 0666);
    if(fd < 0)
    {
        printf("Open file error\n");
	exit(1);
    }
    lock_set(fd, F_RDLCK);
    getchar();
    lock_set(fd, F_UNLCK);
    getchar();

    return 0;
}
         
         
        
        
       
       
      
      

在两个终端上进行测试。

二、多路复用: select poll
select:
#include 
      
      
       
       
#include 
       
       
        
        
#include 
        
        
         
         
#include 
         
         
          
          

#define MAX(a, b) ((a) > (b) ? (a) : (b))

int main()
{
    int fd[3];
    char buf[1024];
    int res;
    int max_fd;
    int i; 
    int num;
    fd_set insert;
    fd_set temp_insert;

    struct timeval tv;
    fd[0] = 0;
    if(fd[1] = open("in1", O_RDONLY | O_NONBLOCK) < 0)
    {
        printf("open in1 error!\n");
	return 1;
    }
    if(fd[2] = open("in2", O_RDONLY | O_NONBLOCK) < 0)
    {
        printf("open in2 error!\n");
	return 1;
    }
    max_fd = MAX(MAX(fd[0], fd[1]), fd[2]);
    FD_ZERO(&insert);
    for(i = 0; i < 3; i++)
    {
        FD_SET(fd[i], &insert);
    }
    tv.tv_sec = 60;
    tv.tv_usec = 0;

    while(FD_ISSET(fd[0], &insert) || FD_ISSET(fd[1], &insert) || FD_ISSET(fd[2], &insert))
    {
        temp_insert = insert;
	res = select(max_fd + 1, &temp_insert, NULL, NULL, &tv);
	switch(res)
	{
	    case -1:
	        printf("select error\n");
		return 1;
		break;
	    case 0:
	        printf("time out\n");
		return 1;
		break;
	    default:
	        for(i = 0; i < 3; i++)
		{
		    if(FD_ISSET(fd[i], &temp_insert))
		    {
		        memset(buf, 0, 1024);
			num = read(fd[i], buf, 1024);
			if(num < 0)
			{
			    return 1;
			}
			else if(num == 0)
			{
			    close(fd[i]);
			    FD_CLR(fd[i], &insert);
			}
			else
			{
			    if(i == 0)
			    {
			        if(buf[0] == 'q' || buf[0] == 'Q')
				{
				    return 0;
				}
			    }
			    write(STDOUT_FILENO, buf, num);
			}
		    }
		}
	}
    }


}
         
         
        
        
       
       
      
      

poll:
#include 
      
      
       
       
#include 
       
       
        
        
#include 
        
        
         
         
#include 
         
         
          
          
#include 
          
          
            #define BUF_SZ 1024 #define IO_IN_FILE 3 #define TIMEDELAY 60000 int main() { struct pollfd fd[IO_IN_FILE]; char buf[BUF_SZ]; int res; int real_read; int i; fd[0].fd = 0; if(fd[1].fd = open("in1", O_RDONLY | O_NONBLOCK) < 0) { printf("open in1 error!\n"); return 1; } if(fd[2].fd = open("in2", O_RDONLY | O_NONBLOCK) < 0) { printf("open in2 error!\n"); return 1; } for(i = 0; i < IO_IN_FILE; i++) { fd[i].events = POLLIN; } while(fd[0].events || fd[1].events || fd[2].events) { res = poll(fd, IO_IN_FILE, TIMEDELAY); switch(res) { case -1: printf("poll error\n"); return 1; break; case 0: printf("time out\n"); return 1; break; default: for(i = 0; i < IO_IN_FILE; i++) { if(fd[i].events) { memset(buf, 0, BUF_SZ); real_read = read(fd[i].fd, buf, BUF_SZ); if(real_read < 0) { printf("read error\n"); return 1; } else if(real_read == 0) { close(fd[i].fd); fd[i].events = 0; } else { if(i == 0) { if(buf[0] == 'q' || buf[0] == 'Q') { return 0; } } write(STDOUT_FILENO, buf, real_read); } } } } } return 0; } 
          
         
         
        
        
       
       
      
      

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值