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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zm1_1zm/article/details/77072987

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

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

猜你喜欢

转载自blog.csdn.net/zm1_1zm/article/details/77072987