flock函数实现文件锁

本文详细介绍了Linux flock函数的使用,包括建立共享锁(LOCK_SH)、互斥锁(LOCK_EX),解除锁定(LOCK_UN),以及如何在apr库中实现。特别强调了信号中断处理和并发操作注意事项。
摘要由CSDN通过智能技术生成

flock函数

函数使用

flock()函数:解除锁定文件

FLOCK(2)                                                                                        Linux Programmer's Manual                                                                                       FLOCK(2)

NAME
       flock - apply or remove an advisory lock on an open file

SYNOPSIS
       #include <sys/file.h>
       int flock(int fd, int operation);

DESCRIPTION
       Apply or remove an advisory lock on the open file specified by fd.  The argument operation is one of the following:
           LOCK_SH  Place a shared lock.  More than one process may hold a shared lock for a given file at a given time.
           LOCK_EX  Place an exclusive lock.  Only one process may hold an exclusive lock for a given file at a given time.
           LOCK_UN  Remove an existing lock held by this process.

       A call to flock() may block if an incompatible lock is held by another process.  To make a nonblocking request, include LOCK_NB (by ORing) with any of the above operations.
       A single file may not simultaneously have both shared and exclusive locks.
       Locks created by flock() are associated with an open file table entry.  This means that duplicate file descriptors (created by, for example, fork(2) or dup(2)) refer to the same lock, and this lock may be modified or released using any of these descriptors.  Furthermore, the lock is released either by an explicit LOCK_UN operation on any of these duplicate descriptors,  or  when  all  such  descriptors  have  been closed.
       If  a  process  uses  open(2)  (or  similar)  to  obtain more than one descriptor for the same file, these descriptors are treated independently by flock().  An attempt to lock the file using one of these file descriptors may be denied by a lock that the calling process has already placed via another descriptor.

       A process may hold only one type of lock (shared or exclusive) on a file.  Subsequent flock() calls on an already locked file will convert an existing lock to the new lock mode.
       Locks created by flock() are preserved across an execve(2).
       A shared or exclusive lock can be placed on a file regardless of the mode in which the file was opened.

RETURN VALUE
       On success, zero is returned.  On error, -1 is returned, and errno is set appropriately.

ERRORS
       EBADF  fd is not an open file descriptor.
       EINTR  While waiting to acquire a lock, the call was interrupted by delivery of a signal caught by a handler; see signal(7).
       EINVAL operation is invalid.
       ENOLCK The kernel ran out of memory for allocating lock records.
       EWOULDBLOCK
              The file is locked and the LOCK_NB flag was selected.

参数 operation 有下列四种情况:
LOCK_SH 建立共享锁定. 多个进程可同时对同一个文件作共享锁定.
LOCK_EX 建立互斥锁定. 一个文件同时只有一个互斥锁定.
LOCK_UN 解除文件锁定状态.
LOCK_NB 无法建立锁定时, 此操作可不被阻断, 马上返回进程. 通常与LOCK_SH 或LOCK_EX 做OR(|)组合.

apr库中的用法

/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "apr_arch_file_io.h"

#if APR_HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
#endif

APR_DECLARE(apr_status_t) apr_file_lock(apr_file_t *thefile, int type)
{
    int rc;

#if defined(HAVE_FCNTL_H)
    {
        struct flock l = { 0 };
        int fc;

        l.l_whence = SEEK_SET;  /* count l_start from start of file */
        l.l_start = 0;          /* lock from start of file */
        l.l_len = 0;            /* lock to end of file */
        if ((type & APR_FLOCK_TYPEMASK) == APR_FLOCK_SHARED)
            l.l_type = F_RDLCK;
        else
            l.l_type = F_WRLCK;

        fc = (type & APR_FLOCK_NONBLOCK) ? F_SETLK : F_SETLKW;

        /* keep trying if fcntl() gets interrupted (by a signal) */
        while ((rc = fcntl(thefile->filedes, fc, &l)) < 0 && errno == EINTR)
            continue;

        if (rc == -1) {
            /* on some Unix boxes (e.g., Tru64), we get EACCES instead
             * of EAGAIN; we don't want APR_STATUS_IS_EAGAIN() matching EACCES
             * since that breaks other things, so fix up the retcode here
             */
            if (errno == EACCES) {
                return EAGAIN;
            }
            return errno;
        }
    }
#elif defined(HAVE_SYS_FILE_H)
    {
        int ltype;

        if ((type & APR_FLOCK_TYPEMASK) == APR_FLOCK_SHARED)
            ltype = LOCK_SH;
        else
            ltype = LOCK_EX;
        if ((type & APR_FLOCK_NONBLOCK) != 0)
            ltype |= LOCK_NB;

        /* keep trying if flock() gets interrupted (by a signal) */
        while ((rc = flock(thefile->filedes, ltype)) < 0 && errno == EINTR)
            continue;

        if (rc == -1)
            return errno;
    }
#else
#error No file locking mechanism is available.
#endif

    return APR_SUCCESS;
}

APR_DECLARE(apr_status_t) apr_file_unlock(apr_file_t *thefile)
{
    int rc;

#if defined(HAVE_FCNTL_H)
    {
        struct flock l = { 0 };

        l.l_whence = SEEK_SET;  /* count l_start from start of file */
        l.l_start = 0;          /* lock from start of file */
        l.l_len = 0;            /* lock to end of file */
        l.l_type = F_UNLCK;

        /* keep trying if fcntl() gets interrupted (by a signal) */
        while ((rc = fcntl(thefile->filedes, F_SETLKW, &l)) < 0
               && errno == EINTR)
            continue;

        if (rc == -1)
            return errno;
    }
#elif defined(HAVE_SYS_FILE_H)
    {
        /* keep trying if flock() gets interrupted (by a signal) */
        while ((rc = flock(thefile->filedes, LOCK_UN)) < 0 && errno == EINTR)
            continue;

        if (rc == -1)
            return errno;
    }
#else
#error No file locking mechanism is available.
#endif

    return APR_SUCCESS;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Erice_s

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

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

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

打赏作者

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

抵扣说明:

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

余额充值