fcntl系统调用

fcntl系统调用

例1: 文件的状态标志

myfcntl_access.c

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <errno.h>


#define ERROR(flag)                 \
     if(flag)                \
    {                    \
        printf("%d: ",__LINE__);    \
        fflush(stdout);            \
        perror("error");        \
        exit(errno);            \
    }


int main(int argc,char *argv[])
{
    int    ret;
    int    access_mode;
    int    fd;

    fd = open(argv[1], O_RDWR );

    ERROR(fd == -1);

    ret = fcntl(fd, F_SETFL, O_APPEND | O_NONBLOCK);
    ERROR(ret < 0);
    ret = fcntl(fd, F_GETFL,0);
    ERROR(ret < 0);
        

    access_mode = ret & O_ACCMODE;

    if (access_mode == O_RDONLY)
    {
        printf("%s:  read only",argv[1]);
    }
      else if (access_mode == O_WRONLY)
    {
        printf("%s:  write only",argv[1]);
    }
    else if (access_mode == O_RDWR)
    {
        printf("%s:  read + write",argv[1]);
    }


    if (ret & O_APPEND)
    {
        printf(", append");
    }
    if (ret & O_NONBLOCK)
    {
        printf(", nonblock");
    }
    printf("\n");

    return 0;
}

编译链接执行, 结果输出文件的属性如下:

 

例2: 对文件描述符设置读写锁

myfcntl_lock.c

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

#define ERROR(flag)                 \
     if(flag)                \
    {                    \
        printf("%d: ",__LINE__);    \
        fflush(stdout);            \
        perror("error");        \
        exit(errno);            \
    }


int lock_set(int fd, struct flock * lock)
{
    if (fcntl(fd, F_SETLK, lock) == 0)
    { 
        if (lock->l_type == F_RDLCK)
        {
            printf("set read lock,  pid:%d\n", getpid());
        }
        else if (lock->l_type == F_WRLCK)
        {
            printf("set write lock,  pid:%d\n", getpid());
        }
        else if (lock->l_type == F_UNLCK)
        {
            printf("release lock, pid:%d\n", getpid());
        }
    }
    else
    {
        perror("lock operation fail\n");
        return -1;
    }

    return 0;
}

int lock_test(int fd, struct flock * lock)
{
    if (fcntl(fd, F_GETLK, lock) == 0)
    {
        if (lock->l_type == F_UNLCK)
        {
            printf("lock can be set in fd\n");
            return 0;
        }
        else
        {
            if (lock->l_type == F_RDLCK)
            {
                printf("can't set lock, read lock has been set by: %d\n",
                                       lock->l_pid);
            }
            else if (lock->l_type == F_WRLCK)
            {
                printf("can't set lock, write lock has been set by: %d\n",
                                       lock->l_pid);
            }
            return -2;
        }
    }
    else
    {    
        perror("get incompatible locks fail");
        return -1;
    }
}

int main(int argc,char *argv[1])
{
    int fd;
    int ret;
    struct flock lock;
    char read_buf[32];

    fd = open(argv[1], O_CREAT | O_TRUNC | O_RDWR, S_IRWXU);
    ERROR(fd == -1);
        
    ret = write(fd, "=====hello 123456789=====", 25);
    ERROR(ret != 25);

    memset(&lock, 0, sizeof (struct flock));
    lock.l_whence = SEEK_SET;
    lock.l_start = 0;
    lock.l_len = 0;
    
    lock.l_type = F_RDLCK;
    if (lock_test(fd, &lock) == 0)
    { 
        lock.l_type = F_RDLCK;
        lock_set(fd, &lock);
    }

    lseek(fd, 0, SEEK_SET);
    ret = read(fd, read_buf, 25);
    ERROR(ret < 0);
    read_buf[ret] = '\0';
    printf("%s\n", read_buf);

    getchar();

    lock.l_type = F_WRLCK;
    if (lock_test(fd, &lock) == 0)
    {
        lock.l_type = F_WRLCK;
        lock_set(fd, &lock);
    }
    getchar();
lock.l_type = F_UNLCK; lock_set(fd, &lock); close(fd); return 0; }

编译链接运行, 有如下输出结果:

结果1: 只在一个终端执行, 对打开文件的描述符加读锁, 写锁及解锁结果如下图:

结果2: 两个终端同时执行同样的命令, 再先后按回车键, 对打开的文件描述符加读锁,写锁及解锁, 输出结果如下:

理解如下:

 1. 此文件读写锁没有强制性(提供机制, 由接口使用者实现策略). 

    2. 不同进程对同一打开的文件描述符可以同时加读锁

 

    3. 对已加读锁的文件描述符, 不能再加写锁

结果3: 两个终端同时执行同样的命令, 其中一个先连续按两次回车, 使其对文件描述符加写锁, 如下:

理解如下:

    对已加写锁的文件,不能加读锁, 也不能加写锁

posted @ 2016-01-11 19:51  zhanglong71  阅读(244)  评论(0编辑  收藏  举报