当前位置: 首页 > 工具软件 > Flock > 使用案例 >

flock函数实现文件锁

司马昕
2023-12-01

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;
}
 类似资料: